This is the relationship I am talking about:
struct A{
int i = 1;
};
struct B{
union{A a;};
};
void main(){
B b;
};
In this constellation, my compiler (vs2015) complains about the default constructor of B B::B(void)
beeing deleted, with the note that the compiler has generated 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
(sorry, I could not convince msvc to talk english to me)
Either of these two code changes fixes it:
struct A{
int i; //removed initialzation of member to 1
};
or
struct B{
B(){} //adding explicit default constructor
union{A a;};
};
I know that adding a default constructor that does nothing is not exactly a complicated or annoying workaround, but I really want to know why C++ forces me to do this.
This is because of [class.default.ctor]p2 which says:
A defaulted default constructor for class X is defined as deleted if:
- (2.1) X is a union that has a variant member with a non-trivial default constructor and no variant member of X has a default member initializer,
.....
and we can see why A
does not have a trivial default constructor from [class.default.ctor]p3 which says:
A default constructor is trivial if it is not user-provided and if:
- (3.1) — its class has no virtual functions (10.6.2) and no virtual
base classes (10.6.1), and
- (3.2) —no non-static data member of its
class has a default member initializer (10.3), and
- (3.3) — all the
direct base classes of its class have trivial default constructors,
and
- (3.4) — for all the non-static data members of its class that are
of class type (or array thereof), each such class has a trivial
default constructor.
We can see from this live godbolt example
that removing the non-static member initializer makes the program well formed.
struct A{
int i ; // no NSDMI
};
struct B{
union{A a;};
};
The paper that resulted in the wording we have today is n2544:1
Unrestricted Unions (Revision 2), it covers the rational here:
We have also changed the way implicitly declared special
member functions of unions are generated in the following
way: if a non-trivial special member function is defined for
any member of a union, or a member of an anonymous union inside a
class, that special member function will be implicitly deleted (8.4
¶10) for t he union or class. This prevents the compiler from trying
to write code that it cannot know how t o write, and forces the
programmer to write that code if it’s needed. The fact that the
compiler can’t write such a function is no reason not to let the
programmer do so.
A union has only one active member, if one or more of the members can not be default constructed how should the compiler choose which one to make active by default?