C++11 anonymous union with non-trivial members

anonymous-class, c++, c++11, constructor, unions

Solution

There is no need for placement new here.

Variant members won't be initialized by the compiler-generated constructor, but there should be no trouble picking one and initializing it using the normal ctor-initializer-list. Members declared inside anonymous unions are actually members of the containing class, and can be initialized in the containing class's constructor.

This behavior is described in section 9.5. `[class.union]`:

A union-like class is a union or a class that has an anonymous union as a direct member. A union-like class `X` has a set of variant members. If `X` is a union its variant members are the non-static data members; otherwise, its variant members are the non-static data members of all anonymous unions that are members of `X`.

and in section 12.6.2 `[class.base.init]`:

A ctor-initializer may initialize a variant member of the constructor’s class. If a ctor-initializer specifies more than one mem-initializer for the same member or for the same base class, the ctor-initializer is ill-formed.

So the code can be simply:

#include <new>

struct Point  {
    Point() {}
    Point(int x, int y): x_(x), y_(y) {}
    int x_, y_;
};

struct Foo
{
  Foo() : p() {} // usual everyday initialization in the ctor-initializer
  union {
    int z;
    double w;
    Point p;
  };
};

int main(void)
{
}

Of course, placement new should still be used when vivifying a variant member other than the other initialized in the constructor.

Problem

I'm updating a struct of mine and I was wanting to add a std::string member to it. The original struct looks like this: ``` struct Value { uint64_t lastUpdated; union { uint64_t ui; int64_t i; float f; bool b; }; }; ``` Just adding a std::string member to the union, of course, causes a compile error, because one would normally need to add the non-trivial constructors of the object. In the case of std::string (text from informit.com) Since std::string defines all of the six special member functions, U will have an implicitly deleted default constructor, copy constructor, copy assignment operator, move constructor, move assignment operator and destructor. Effectively, this means that you can't create instances of U unless you define some, or all of the special member functions explicitly. Then the website goes on to give the following sample code: ``` union U { int a; int b; string s; U(); ~U(); }; ``` However, I'm using an anonymous union within a struct. I asked ##C++ on freenode and they told me the correct way to do that was to put the constructor in the struct instead and gave me this example code: ``` #include <new> struct Point { Point() {} Point(int x, int y): x_(x), y_(y) {} int x_, y_; }; struct Foo { Foo() { new(&p) Point(); } union { int z; double w; Point p; }; }; int main(void) { } ``` But from there I can't figure how to make the rest of the special functions that std::string needs defined, and moreover, I'm not entirely clear on how the ctor in that example is working. Can I get someone to explain this to me a bit clearer?

Original source