web-dev-qa-db-ja.com

非静的メンバー初期化子を持つクラスのC ++ 11集約初期化

標準で許可されていますか:

struct A
{
  int a = 3;
  int b = 3;
};

A a{0,1}; // ???

このクラスはまだ集約されていますか? clangはこのコードを受け入れますが、gccは受け入れません。

33
Bikineev

C++ 11では、クラス内のメンバー初期化子を使用すると、構造体/クラスが集計ではなくなります。ただし、これはC++ 14で変更されました。これは私が最初に遭遇したときに私が驚いたことです。この制限の理論的根拠は、クラス内の初期化子がユーザー定義のコンストラクターに非常に似ているということですが、反論は、クラス内の初期化子を追加することで誰も実際に期待していないということです彼らのクラス/コンストラクターは非集合体ですが、私は確かにそうしませんでした。

ドラフトC++ 11標準 セクション8.5.1集合体今後の私の強調)::

集合体は、ユーザー提供のコンストラクター(12.1)がない配列またはクラス(節9)、非静的データメンバー用の中括弧または等しい初期化子がない(9.2)、プライベートまたは保護された非静的データメンバー(条項11)、基本クラス(条項10)、および仮想関数(10.3)はありません。

そして C++ 14 で同じ段落は次のようになります。

集合体は、ユーザー提供のコンストラクター(12.1)、プライベートまたは保護された非静的データメンバー(条項11)、基本クラス(条項10)、および仮想関数(10.3)を含まない配列またはクラス(条項9)です。 )。

この変更については、 N3605:メンバー初期化子と集計 で説明されています。これには次の要約があります。

BjarneStroustrupとRichardSmithは、集計の初期化とメンバーの初期化子が連携しないという問題を提起しました。このペーパーは、集計にmember-initializersを含めることができないという制限を削除するスミスの提案された表現を採用することにより、問題を修正することを提案しています。

このコメントは、基本的に、それらを集合体にすることへの抵抗を要約しています。

集合体はユーザー定義のコンストラクターを持つことはできず、member-initializersは基本的にある種のユーザー定義のコンストラクター(要素)です(コア障害886も参照)。私はこの拡張に反対しているわけではありませんが、集計のモデルが実際に何であるかに影響を与えます。この拡張機能を受け入れた後集合体とは何かを教える方法を知りたいです。

改訂版 N3652013年5月 に採用されました。

更新

emsrは、 G ++ 5.0は非静的データメンバー初期化子を使用したC++ 14集計をサポートするようになりましたstd=c++1yまたは-std=c++14のいずれかを使用することを指摘しています。

struct A { int i, j = i; };
A a = { 42 }; // a.j is also 42

それが機能しているのを見てください ライブ

43
Shafik Yaghmour