24

std::piecewise_construct<utility> で定義されている は、宣言されているため、内部リンケージがありconstexprます。std::piecewise_constructヘッダーで を使用すると、ODR に違反する可能性があるのではないかと思います。例えば:

a.hpp

#include <utility>
#include <tuple>

struct point
{
    point(int x, int y)
      : x(x), y(y)
    {}

    int x, y;
};

inline std::pair<point, point> f(int x1, int y1, int x2, int y2)
{
    return {
        std::piecewise_construct,
        std::forward_as_tuple(x1, y1), std::forward_as_tuple(x2, y2)
    };
}

翻訳単位 1

#include "a.hpp"

翻訳単位 2

#include "a.hpp"

TU 1のstd::piecewise_constructinは、TU 2のfin とは異なるオブジェクトを参照しています。ODR に違反していると思われます。ff

N3290 (おそらく ISO/IEC 14882:2011 も) は、次のケースは 3.2/5 の ODR の例外であると述べています。

オブジェクトが D のすべての定義で同じリテラル型を持ち、オブジェクトが定数式 (5.19) で初期化され、値 (アドレスではない) がオブジェクトが使用され、オブジェクトは D のすべての定義で同じ値を持ちます。

fほとんどすべての要件を満たしていますが、「オブジェクトの値(アドレスではなく)が使用される」というのは曖昧に思えます。状態がないのは事実ですstd::piecewise_construct_tが、 の区分コンストラクターの呼び出しには、引数が であるstd::pairの暗黙的に宣言されたコピー コンストラクターの呼び出しが含まれます。アドレスは「使用済み」ですね。std::piecewise_construct_tconst std::piecewise_construct_t &

とても困惑しています。

参照: http://lists.boost.org/Archives/boost/2007/06/123353.php

4

2 に答える 2

6

そのブースト メーリング リストの投稿で、既に回答が得られているようです。はい、私の意見では、それは未定義の動作であるか、少なくとも定義された動作が十分に明確ではありません。

議論されている同じ問題については、このユースネットの議論を参照してください。

于 2011-10-03T11:55:32.750 に答える
0

私見では、ODR の下で競合はありません。

名前のない名前空間には、内部リンケージ (静的) をマークするのと同じ効果があります。これは実際、すべての TU がそのような型/関数に対して独自の独自の定義を使用することを意味します。

私がそれらを見る方法、プレースホルダー (::::_1 と競合するフレーバー) がどのように機能するかは、インスタンス化によるものではなく、コンパイル時の型推論によるものです。

_1、_2 などは単なるプレースホルダーであり、実際に互換性を保つ必要はありません (値をある TU から別の TU に渡す必要はありません。型推論パラメーターとしてのみ渡されるため、実際の型は推論されます)。identity現在の TU から取得する必要があります)。

IOW: いくつかの特性を特殊化することで、独自のプレースホルダーを簡単に定義できますが、それでも魅力的に機能するはずです。

namespace boost
{
    template<int I> struct is_placeholder< 
           my_funny_own_placeholder_no_ODR_involved<I> >
    {
        enum _vt { value = I };
    };
}

piecewise_construction についても同じロジックが成り立つと思います (しかし、あまり詳しくは見ていません)。

于 2011-10-03T12:03:42.500 に答える