5

私は、POD、STL、および配列などの複合型用のささいな (きれいな) プリンターに取り組んでいます。そうしている間、私も初期化リストをいじっていて、次の宣言に出くわしました

std::vector<double[3]> arr{ { 10, 11, 12 }, { 20, 21, 22 } }; 

VC2013 と G++ 4.8 の両方が満足していないようで、一貫したエラー メッセージが表示されますが、どちらの場合も私にとってはあまり役に立ちません。

VC++ の場合: error C3074: an array can only be initialized with an initialize-list

G++ 4.8 の場合: error: array must be initialized with a brace-enclosed initialize

ここでは初期化リストを使用できないか、構文がまったく正しくありませんか?

同様の面で、次の構文は有効なようです

std::vector<std::array<int, 3>>  arr{ { 10, 11, 12 }, { 20, 21, 22 } };

初期化リストで考えられる問題は何ですか?

  • std::arrayC型配列の代わりに 使用する必要があることは理解していますが、実験中です。
  • これをいじりたくない場合は、ここにIDEONEバージョンがあります
  • 注記また、標準を参照していただけると非常に有益です。
4

2 に答える 2

5

現在の C++1y ドラフト標準を読む。

表 99 の前から:

T is EmplaceConstructible into X from args , 0 個以上の引数 args の場合、次の式が整形式であることを意味します: allocator_traits::construct(m, p, args)

表 100:

X(il);              |  Equivalent to      | X(il.begin(), il.end());
--------------------+---------------------+--------------------------------
X(i, j);            |                     | Requires:
X a(i, j);          |                     | T shall be EmplaceConstructible
                                          | into X from *i.

に渡されるイニシャライザリストの要素としてis fromでstd::vector<double[3]> v{ {1,2,3}, {4,5,6} };ある場合は有効です。double[3]EmplaceConstructible{1,2,3}std::vector<double[3]>

前方反復子に関する節もありますが、それは問題ありません (std::initialzier_list反復子は前方反復子であるため)。

std::vector<T>パラメータを取りstd::initializer_list<T>ます。

候補std::initializer_list<double[3]>リストも同様です。

まず、std::initializer_list<double[3]> x = {{1.0, 2.0, 3.0}};gcc でのコンパイルに失敗します。しかし、それが gcc のバグだとします。

第 2 に、適切なオーバーライドがない場合に縮小される::new (nullptr) double[3](std::initializer_list<double>{1.0, 2.0, 3.0});配置 new は、コンパイルに失敗します。EmplaceConstructableconstruct

アロケータが回避するために私が認識していない魔法を行わない限り、 だからですdouble[3]。新しい配置。EmplaceConstrublestd::initalizer_list<double>double[3]

したがって、あなたのコードは現在のドラフト標準に違反しており、おそらく C++11、そして確実に C++03 (コンテナーに関するより厳しい要件がありました) に違反しています。

于 2014-08-15T16:57:45.553 に答える
3

これは gcc と MSVC のバグです。clang はコードを正しくコンパイルします。

gcc の最近のバージョンでは、実際にコンパイラがクラッシュ ("ice") します。

内部コンパイラ エラー: ツリー チェック: 期待されるクラス 'type'、useless_type_conversion_p の tree-ssa.c:1189 に 'exceptional' (error_mark) があります

基準はかなり明確です。[dcl.init.list]から:

5 - type のオブジェクトは、実装が type の要素のstd::initializer_list<E>配列を割り当てたかのように、初期化子リストから構築されます。ここで、 は初期化子リスト内の要素の数です。その配列の各要素は、初期化子リストの対応する要素でコピー初期化され、オブジェクトはその配列を参照するように構築されます。[...]NENstd::initializer_list<E>

その段落の例を適応させる:

using E = double[3];
using X = std::vector<E>;
E __a[2] = {{10, 11, 12}, {20, 21, 22}};
X x(__a, __a+2);

ただし、これは少しチートです。より厳密に翻訳すると と記述されますE __a[2] = {E{10, 11, 12}, E{20, 21, 22}};が、これは有効ではありません。しかし、ブレース初期化リストから配列をコピーして初期化することは確かに可能です:double[3]E __a0 = {10, 11, 12};

于 2014-08-15T17:01:29.287 に答える