2016-01-03 15 views
10

C++ 11でどのようにユニオンが拡張されたかを理解しようとしています。変更された点の1つは、非静的なデータメンバーを特別なメンバー関数で使用することです。労働組合が非自明な特殊なメンバ関数(デフォルトコンストラクタ、コピー/移動コンストラクタ、コピー/移動の割り当て、またはデストラクタ)と非静的データメンバが含まれている場合cppreference.comC++ 11のユニオン:デフォルトのコンストラクタが削除されているようです。

からは、その機能がデフォルトで削除されます組合では、プログラマが明示的に定義する必要があります。 多くても1つのデータメンバーにデフォルトメンバー初期化子を設定できます。

私は次のコードをしようとしている:ここ

struct X 
{ 
    ~X() {}; 
}; 

union U 
{ 
    X x; 
    ~U() {}; 
}; 

int main() 
{ 
    U s1{}; // works, probably aggregate initialization 
    U s2; // DOES NOT compile, why? 
} 

Live on Coliru

Xは(組合のデータメンバーとして使用される)ユーザ提供デストラクタの故にデストラクタを有します共用体はデフォルトで削除されます。したがって私は明示的に1つを提供します。しかし、コードがコンパイルに失敗し、エラー

ノートで:デフォルトの定義が病気に形成されたことになるので「U :: Uは()」暗黙的に削除されます。

コードがあればコンパイル私は最後の行U s2;を削除します。

質問ここでは何が起こっていますか?なぜU s1{};がコンパイルされますが、U s2;はありません。ユニオンのデフォルトのctorは削除済みとしてマークされていますか(なぜそうなのですか?)、最初のケースでは初期化を集計していますか? U(){}; // not U() = default;を提供した場合、コードはコンパイルされます(しかし、私はXのctorしか提供しません)。

組合:

EDIT

標準(N4527)に掘り後、9.5/2 [class.union]

[注意:任意の非静的な場合(12.8)、コピーコンストラクタ(12.8)、コピーコンストラクタ(12.8)、コピー代入演算子(12.8)、移動代入演算子(12.8)、またはデストラクタ(12.4)があり、対応するメンバー関数ユニオンの使用はユーザー提供するか、ユニオン用に暗黙的に削除する必要があります(8.4.3)。 -endnote]

これはgccバグ(現在はhereと報告されているようです)です。コードはclangとgcc 4.8.2以前でコンパイルされ、gcc4.9以降で動作します(指摘のために@ T.Cに感謝します)。

コンパイラ:g ++ 5.3、-std=c++11が使用されます。

+1

[Clang](http://coliru.stacked-crooked.com/a/b58a360400009fa9)はこのコードに完全に満足しています。これは実際にはGCCのバグのように見えます。 –

+0

@ T.C。はい、私は実際にあなたのコメントの後にこれを見ました。私は最初印象clangを持っていたそれを拒否していた、いくつかの変更されたバージョンをテストされている可能性があります。質問の最後の行を編集しました。ありがとうございます。 – vsoftco

+0

@ T.C。私は標準を掘り下げようとします... – vsoftco

答えて

2

cppreference quoteが不明です。何が起こるかというと労働組合のANY memeberが、その後をそれらの非自明な特殊なメンバ関数のANYを、定義されている場合、それらのすべてが組合にデフォルトで削除されることです。

したがって、Xのための自明でないデストラクタがあるので、Uデフォルトのコンストラクタが削除されます。

+0

ありがとう、これがそうなら、それは完璧な意味を成しています。そして、 'U s1 {};'は、集約初期化を使用しているので機能します。 – vsoftco

+0

ほとんど、そうです。 C++ 11の規則では、より複雑な型の共用体を使用できますが、共用体を管理するオブジェクト/関数で使用する型タグに基づいて、そのコンストラクタおよびデストラクタの呼び出しを手動で管理する必要があります。通常、これは、配置new/deleteを使用することを意味します。 –

+0

お見積もりはありますか?私はそれが標準が言っているとは思わない。 –

1

Xはデストラクタを持っているので簡単にコピーできないので、ポッドタイプではありません また、Uはポッドタイプではありません。

U s2; はエラー

U s1 {}; 使用メンバー賢明初期化と労働組合のデフォルトcostructor非ポッド部材と組合では

任意のcostructorを呼び出すことはありませんので、削除されたデフォルトのcostructorを呼び出そうメンバのデフォルトのコストラスタをコールするために削除されます。つまり、コンパイラは、どのメンバがデフォルトのコストラクタを呼び出すかわかりません。

Union XX{ 
    string m1; 
    vector <int> m2; 
} 

XXのデフォルトのcostructorは、m1とm2のデフォルトのcostructorを呼び出すことができないため、削除されます。

+1

あなたのステートメントに同意しますが、なぜ私は理解していないのは、デフォルトのコンストラクタが削除される理由です。 – vsoftco

+0

@vsoftco私はそれがappensと思うもののいくつかの説明を追加します – alangab

+0

コンパイラが最初のメンバのコンストラクタを呼び出すことができない理由はありませんが、それは事実かもしれません。 'XX x {" test "};'と同じように、コンパイラは 'm1'のctor、つまり最初のメンバのctorを呼び出します。 – vsoftco

関連する問題