I recently read a description of default constructors for unions: Default Constructor
There is a following rule:
Blockquote Deleted implicitly-declared default constructor: [...] T is a union with at least one variant member with non-trivial default constructor, and no variant member of T has a default member initializer.[...]
Then I decided to make an exercise and verify the rule.
struct Member {
public:
// Member() : mX(0) {}
virtual int GetX() {
return mX;
}
int mX;
};
union DefaultConstructor {
int mA;
Member mMember;
int GetA();
};
With use of gcc v5.3.1 (I know it is pretty old) I receive expected error:
> ../src/DefaultConstrcutors.cpp: In function ‘void
> Test_DefaultConstructors()’: ../src/DefaultConstrcutors.cpp:26:22:
> error: use of deleted function
> ‘DefaultConstructor::DefaultConstructor()’ DefaultConstructor foo;
> ^ In file included from ../src/DefaultConstrcutors.cpp:19:0:
> ../src/DefaultConstructors.h:155:7: note:
> ‘DefaultConstructor::DefaultConstructor()’ is implicitly deleted
> because the default definition would be ill-formed: union
> DefaultConstructor {
> ^ ../src/DefaultConstructors.h:157:10: error: union member ‘DefaultConstructor::mMember’ with non-trivial ‘Member::Member()’
> Member mMember;
> ^
Ok, so according to rule, if I provide a default member initializer for a variant member, then it should compile. So I've changed union definition to:
union DefaultConstructor {
int mA = 0;
Member mMember;
int GetA();
};
And now it should compile, but I've received the same error.
Next step was to provide default initializer for a mMember instead of mA (only one union variant member may have default initializer).
union DefaultConstructor {
int mA;
Member mMember{};
int GetA();
};
Now it compiles.
The question is: why it didn't compile in second case, when mA had default initializer? According to mentioned rule it should be possible. What more similar rule is provided here: Union declaration
If a union contains a non-static data member with a non-trivial default constructor, the default constructor of the union is deleted by default unless a variant member of the union has a default member initializer .
Anyone has an idea why doesn't it work?
Greetings, Piotr