Related: How to initialize a non-POD member in Union
The standard says
At most one non-static data member of a union may have a brace-or-equal-initializer.
But
struct Point {
Point() {}
Point(int x, int y): x_(x), y_(y) {}
int x_, y_;
};
union U {
int z;
double w;
Point p = Point(1,2);
};
#include <iostream>
int main () {
U u;
std::cout << u.p.x_ << ":" << u.p.y_ << std::endl;
}
prints 4196960:0
instead of the expected 1:2
.
I consider this a compiler bug. Is that so?
C++11 [class.ctor]/5 states:
Since the struct
Point
in the OP has a non-trivial default constructor,a defaulted default constructor for a union containing a member of type
Point
should be defined as deleted according to the first bullet:resulting in the program presented in the OP being ill-formed.
However, the committee seems to consider this to be a defect in the case that a member of a union has a brace-or-equal-initializer, per core working group issue 1623:
Issue 1623 has the status "drafting," indicating that the committee believes the issue is probably a defect - why else allow a brace-or-equal-initializer for a union member? - but hasn't yet devoted the time to determine the proper wording for a resolution. Indeed, the paragraph is largely the same in the current C++14 draft N3936 ([class.ctor]/4), except that the wording "any direct or virtual base class or non-static data member" is everywhere replaced by the simpler "any potentially constructed subobject."
Although the behavior of both compilers is not strictly conforming, I would consider Clang to be behaving in the spirit of the standard. It would appear that GCC becomes confused by the combination of deleted default constructor and brace-or-equal-initializer:
with the brace-or-equal-initializer present and maximum warnings GCC 4.8.2 performs no initialization of the union at all, and even warns that the members are used uninitialized:
GCC should probably either conform to the standard and diagnose the program as ill-formed, or emulate clang's behavior and generate a proper constructor from the brace-or-equal-initializer.