web-dev-qa-db-ja.com

初期化リストでstd :: arrayを使用する

誤解がない限り、次の方法でstd:arrayを作成することができます。

std::array<std::string, 2> strings = { "a", "b" };
std::array<std::string, 2> strings({ "a", "b" });

それでも、GCC 4.6.1を使用すると、これらのいずれも機能させることができません。コンパイラは単に次のように言います。

expected primary-expression before ',' token

それでも、初期化リストはstd :: vectorで正常に機能します。それでどちらですか? std :: arrayが初期化リストを受け入れるべきだと思うのは間違っているのでしょうか、またはGNU Standard C++ Libraryチームが間違えたのでしょうか?

54
Chris_F

std::array は面白い。基本的には次のように定義されます:

template<typename T, int size>
struct std::array
{
  T a[size];
};

配列を含む構造体です。初期化リストを受け取るコンストラクタはありません。だが std::arrayはC++ 11の規則による集約であるため、集約の初期化により作成できます。配列を集約して初期化するにはinside構造体、中括弧の2番目のセットが必要です。

std::array<std::string, 2> strings = {{ "a", "b" }};

この場合、標準では余分なブレースを省略できることが示唆されていることに注意してください。したがって、おそらくGCCのバグです。

86
Nicol Bolas

受け入れられた回答に追加するには:

std::array<char, 2> a1{'a', 'b'};
std::array<char, 2> a2 = {'a', 'b'};
std::array<char, 2> a3{{'a', 'b'}};
std::array<char, 2> a4 = {{'a', 'b'}};

すべてGCC 4.6.3(Xubuntu 12.01)で動作します。しかしながら、

void f(std::array<char, 2> a)
{
}

//f({'a', 'b'}); //doesn't compile
f({{'a', 'b'}});

上記のコンパイルには二重中括弧が必要です。中括弧が1つのバージョンでは、次のエラーが発生します。

../src/main.cc: In function ‘int main(int, char**)’:
../src/main.cc:23:17: error: could not convert ‘{'a', 'b'}’ from ‘<brace-enclosed initializer list>’ to ‘std::array<char, 2ul>’

型推論/変換のどの側面が物事をこのように機能させるのか、またはこれがGCCの実装の奇癖であるかどうかはわかりません。

11
Joseph