Why do unions have a deleted default constructor if just one of its members doesn't have one?

空扰寡人 提交于 2019-11-28 23:32:59

The relevant wording is in C++11 [class.ctor]p5 (emphasis mine):

A default constructor for a class X is a constructor of class X that can be called without an argument. If there is no user-declared constructor for class X, a constructor having no parameters is implicitly declared as defaulted (8.4). [...] A defaulted default constructor for class X is defined as deleted if:

[...]

  • X is a union-like class that has a variant member with a non-trivial default constructor,

[...]

  • any direct or virtual base class, or non-static data member with no brace-or-equal-initializer, has class type M (or array thereof) and either M has no default constructor or overload resolution (13.3) as applied to M's default constructor results in an ambiguity or in a function that is deleted or inaccessible from the defaulted default constructor, or

[...]

Your class A has no default constructor, so a defaulted default constructor (whether implicit or explicit) for a class X (whether union or non-union) containing a non-static data member of type A without an initialiser leads to the default constructor for X being deleted. It has to: there's simply no way for the compiler to generate any other default constructor.

As for your follow-up question in the comments:

If instead of A not having a default constructor, it has a non-trivial default constructor, then there is a difference between using that in a union and in a non-union class, and that is also part of [class.ctor]p5: it is the first bullet point that I included, without emphasis, in my earlier quote.

In your example, the problem is not that your code has no non trivial defautl constructor, but that it has a copy constructor.

But generally, a union has several members: "at most one of the non-static data members can be active at any time, that is, the value of at most one of the non-static data members can be stored in a union at any time" (9.5/1).

Suppose you have a union with several members some of them having non trivial constructors or copy constructors:

union W {
    A a; 
    int i; 
};

When you would create an object:

W w;  

how should this object be default constructed ? Which member should be the active one ? How should such an object be default-copied ? Is it the A or the int that should be constructed/copied ?

This is why the standard foresses that your union has a deleted default constructor (copy constructor in your case). It should be sufficient to user-provide the missing default function.

union W
{
    int i;
    A a;
    W() { /*...*/ }
    W(const W&c) { /*...*/ }
};

This paper explains the rationale and the wording of C++11 on the topic in its full details.

Important remark: Unfortunately, unrestricted unions are not supported by MSVC13 : it still does not accept ANY member having ANY of the non-trivial default function user defined. GCC accepts it since 4.6 and clang since 3.1.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!