配列のような構造を簡略化した次のコードがあります。
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)
インスタンス化し、その時点でコンパイラーは報告します。X
ERROR (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{} {}
この回避策は難しいものではありませんが、誰が間違っていて誰が正しいのか、私が何をしているのか、そしてその理由を知るためにはどうすればよいでしょうか?