これは私が話している関係です:
struct A{
int i = 1;
};
struct B{
union{A a;};
};
void main(){
B b;
};
このコンステレーションでは、私のコンパイラ(vs2015)は、B B::B(void)
beeingのデフォルトのコンストラクタが削除されたことについて文句を言いますが、コンパイラが次のように生成したことに注意してくださいB::B
。
../test.cpp(155): error C2280: "B::B(void)" : Es wurde versucht, auf eine gelöschte Funktion zu verweisen
../test.cpp(152): note: Compiler hat hier "B::B" generiert
(申し訳ありませんが、msvcに英語を話すように説得することはできませんでした)
これらの2つのコード変更のいずれかがそれを修正します:
struct A{
int i; //removed initialzation of member to 1
};
または
struct B{
B(){} //adding explicit default constructor
union{A a;};
};
何もしないデフォルトのコンストラクターを追加することは、必ずしも複雑で面倒な回避策ではないことを私は知っていますが、C ++がなぜこれを強制するのかを本当に知りたいです。
これは、[class.default.ctor] p2が次のように言っているためです。
クラスXのデフォルトのデフォルトコンストラクタは、次の場合に削除済みとして定義されます。
- (2.1)Xは、重要なデフォルトコンストラクターを持つバリアントメンバーを持ち、Xのバリアントメンバーにはデフォルトメンバー初期化子を持たないユニオンです。
....。
そしてA
、[class.default.ctor] p3からの簡単なデフォルトコンストラクタがない理由がわかります。
デフォルトのコンストラクターは、ユーザーが提供しない場合、および次の場合は簡単です
。-(3.1)-そのクラスには仮想関数(10.6.2)および仮想基本クラス(10.6.1)がなく、
-(3.2)-非-そのクラスの静的データメンバーにはデフォルトのメンバー初期化子(10.3)があり、
-(3.3)—そのクラスのすべての直接基本クラスには簡単なデフォルトコンストラクターがあり、
-(3.4)—のすべての非静的データメンバーに対してクラスタイプ(またはその配列)であるそのクラスでは、そのような各クラスには簡単なデフォルトコンストラクタがあります。
このライブのgodboltの例から、非静的メンバーの初期化子を削除すると、プログラムが適切に形成されることがわかります。
struct A{
int i ; // no NSDMI
};
struct B{
union{A a;};
};
私たちが今日持っている言葉遣いをもたらした論文はn2544:1 Unrestricted Unions(Revision 2)であり、ここでその理論的根拠をカバーしています。
また、暗黙的に宣言されたユニオンの特殊メンバー関数が生成される方法を次のように変更しました。重要な特殊メンバー関数がユニオンのメンバー、またはクラス内の匿名ユニオンのメンバーに対して定義されている場合、その特殊メンバーユニオンまたはクラスのメンバー関数は暗黙的に削除されます(8.4¶10)。これにより、コンパイラーは、書き方がわからないコードを書き込もうとするのを防ぎ、必要に応じてプログラマーにそのコードを書かせます。コンパイラーがそのような関数を書くことができないという事実は、プログラマーにそうさせない理由ではありません。
ユニオンにはアクティブなメンバーが1つしかない場合、1つ以上のメンバーをデフォルトで構築できない場合、コンパイラーはデフォルトでアクティブにするメンバーをどのように選択する必要がありますか?
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加