3

配列のような構造を簡略化した次のコードがあります。

template<typename T, size_t N>
struct X
{
    T a[N];

    template<typename... A>
    explicit X(A&&... a) : a{std::forward<A>(a)...} { }  // ERROR (2)
};

int main ()
{
    X<int,3> x;           // OK
    X<X<int,3>,2> y{x,x}; // OK
    X<X<int,3>,2> z;      // ERROR (1)
}

これは、clang 3.3 および gcc 4.8.1 で正常にコンパイルされ、両方とも-std=c++11. gcc をアップグレードしようとしているので、今は 4.9.0 を試しています。この場合、3 番目の例 ( ) はのコンストラクター ( ) をERROR (1)インスタンス化し、その時点でコンパイラーは報告します。XERROR (2)

error: converting to 'X<int, 3ul>' from initializer list would use explicit
   constructor 'X<T, N>::X(A&&...) [with A = {}; T = int; long unsigned int N = 3ul]

zこの最後の例では、配列とそれに含まれる配列をデフォルトで初期化しようとしています。ただし、これが正しい場合、ここで gcc は基本的に、含まれている配列が によってリスト初期化されていることを示しています{}。これは、コンストラクターが明示的であるため許可されていません。

次のいずれかの形式の別のデフォルト コンストラクターを追加すると、エラーはなくなります。

explicit X() {}
explicit X() : a() {}

しかしそうではない

explicit X() : a{} {}

この回避策は難しいものではありませんが、誰が間違っていて誰が正しいのか、私が何をしているのか、そしてその理由を知るためにはどうすればよいでしょうか?

4

1 に答える 1

3

これは GCC のバグ、PR 60417です。

PR 54835の以前の変更は、コアの問題 1518を修正するために C++ 委員会が提案した方向性を実装することを目的としていました。残念ながら、PR 60417 の最初の例で示されているように、この変更により一部の有効な C++03 プログラムが機能しなくなります。PR 60417 の修正がコミットされましたが、一部のケースのみを処理します。具体的には、この質問のように、明示的なコンストラクターを使用して型の配列をリスト初期化するケースは修正されません。

于 2014-03-28T11:47:19.590 に答える