22

他のトピックでは、@Dietmarがこの解決策を提供しました。

template <typename... T>
std::tuple<T...> parse(std::istream& in) 
{
    return std::tuple<T...>{ T(in)... };
}

それを述べて、

中括弧の初期化の使用は、中括弧の初期化子リスト内の引数の評価の順序がそれらが表示される順序であるため、機能します。(私のことを強調してください)

C ++標準(n3485)の関連テキストは、

braced-init-listのinitializer-list内で、パック拡張(14.5.3)の結果を含むinitializer-clausesは、表示される順序で評価されます。つまり、特定の初期化子句に関連付けられたすべての値の計算と副作用は、初期化子リストのコンマ区切りリストでそれに続く初期化子句に関連付けられたすべての値の計算と副作用の前に順序付けられます。[注:この評価の順序は、初期化のセマンティクスに関係なく適用されます。たとえば、通常、呼び出しの引数に順序付けの制約がない場合でも、initializer-listの要素がコンストラクター呼び出しの引数として解釈される場合に適用されます。—エンドノート]


そこで、次のコードでこれをテストしようとしました。

template<int N>
struct A 
{ 
    std::string data;
    A(std::istream & stream) { stream >> data; }
    friend std::ostream& operator<<(std::ostream & out, A<N> const & a) 
    {
        return out << "A"<<N<<"::data = " << a.data;
    }
};
typedef A<1> A1;
typedef A<2> A2;

template<typename ...Args>
void test(std::istream & stream)
{
    std::tuple<Args...> args { Args(stream)... };
    std::cout << std::get<0>(args) << std::endl;
    std::cout << std::get<1>(args) << std::endl;
}

int main()
{
    std::stringstream ss("A1 A2");
    test<A1,A2>(ss);
}

期待される出力:

A1::data = A1
A2::data = A2

実際の出力:

A1::data = A2
A2::data = A1

テストコードで何か問題がありましたか?コードを次のように変更しました。

std::stringstream ss("A1 A2");
std::tuple<A1,A2> args{A1(ss), A2(ss)};
std::cout << std::get<0>(args) << std::endl;
std::cout << std::get<1>(args) << std::endl

以前と同じ出力。MinGW (GCC) 4.7.0とでコードをテストしました4.7.2。ideoneでさえこの出力を提供します。

コンパイラのバグですか?

4

1 に答える 1

11

私自身の質問に答えます。将来誰かが同じ質問をする可能性があるため、質問を削除することはお勧めできません。

はい。これはGCCコンパイラのバグです。

質問に対する@JohannesSchaubのコメントから引用。

于 2012-12-27T20:37:30.670 に答える