web-dev-qa-db-ja.com

配列のC ++ベクトル

これが機能する理由:

std::pair<int, int> p = {1,2};
std::vector<std::pair<int, int>> vp = { {1,2}, {3,4} };

しかし、これはそうではありませんか?

std::array<int, 2> a = {1,2}; // still ok
std::vector<std::array<int, 2>> va = { {1,2}, {3,4} };

-std=c++0xでg ++ 4.5.1を使用すると、2行目は次のように失敗します。

エラー:‘{{1, 2}, {3, 4}}’‘std::vector<std::array<int, 2u> >’に変換できませんでした

ありがとう

29
andreabedini

残念ながら、std::arrayには初期化リストコンストラクターがありません。確かに、noのユーザー定義コンストラクターはありません-この「機能」は、すべてのユーザー定義コンストラクターを省略したC++ 03の残り物です。 Cスタイルのブレースの初期化を有効にする唯一の方法。これは私見ですが、現在の規格の欠陥です。

では、この場合、組み込みの中括弧の初期化が機能しないのはなぜですか?何を見てみましょうstd::array内部のように見えます:

template <typename T, int i> struct array {
    T data[i];
    // ...
}

わかりました。つまり、初期化子でdouble中括弧を使用する必要があるという意味ではありません(arrayの1つのペア、別のペアdataメンバーの場合は?

std::array<int, 2> a = { {1, 2} };

C(およびその結果としてC++)には、中括弧の省略に関する特別な規則があり、あいまいさがない限り、内側の中括弧を省略できます。 arrayはこの機能を利用して、次のように記述できるようにします。

std::array<int, 2> a = { 1, 2 };

では、なぜ元の投稿の例が機能しないのでしょうか。ブレースの省略は、Cスタイルの集計初期化のコンテキストでのみ許可されるため、ユーザー定義の初期化子リストコンストラクターなど、より複雑なものが含まれる場合は許可されません。

ただし、次のは機能するはずです

std::vector<std::array<int, 2>> vp = { {{1,2}}, {{3,4}} };

少なくともgcc4.5とgcc4.6ではそうではないという事実は、コンパイラのバグを示しているように思われます。しかし、私はそれについて完全にはわかりません。

この質問はやや関連性があります: initializer_listを使用してメンバー配列を初期化するにはどうすればよいですか?

24
JohannesD

これは機能します:

std::vector<std::array<int, 2>> va = {
  std::array<int, 2>{1,2},
  std::array<int, 2>{3,4}
};

さらに深く掘り下げると、std :: pairには初期化子リストを受け取るコンストラクターがあるようですが、std :: arrayにはありません。

std::pair<int, int> p ({1,2}) ;  // OK
std::array<int, 2> a ({1,2}) ;   // Invalid

しかし今、私は自分の深みから外れています。

4
TonyK