c ++ 11无限制工会的例子

时间:2014-04-01 08:03:01

标签: c++11 unions

我看了http://www.stroustrup.com/C++11FAQ.html#unions

但是我无法编译给定的例子:

union U1 {
    int m1;
    complex<double> m2; // ok
};

union U2 {
    int m1;
    string m3;  // ok
};

U1 u;       // ok
u.m2 = {1,2};   // ok: assign to the complex member

结果:

main.cpp:85:8: error: use of deleted function 'U1::U1()'
     U1 u;       // ok
        ^   
main.cpp:75:11: note: 'U1::U1()' is implicitly deleted because the default definition would be ill-formed:
     union U1 {
           ^   
main.cpp:77:25: error: union member 'U1::m2' with non-trivial 'constexpr std::complex<double>::complex(double, double)'
         complex<double> m2; // ok
                         ^   
main.cpp:86:5: error: 'u' does not name a type
     u.m2 = {1,2};   // ok: assign to the complex member
     ^   
make: *** [main.o] Error 1

问题:

我认为在非限制联合中,如果没有手动给出默认构造函数,则将构造第一个元素。这是真的,如何写一个有效的例子?

以下也不会编译:

class Y
{   
    public:
        constexpr Y() {}
};  

union X
{   
    int a;
    float b;
    Y x;
    //X(){}
};  

X x;

int main(){}

相同的错误消息:

main.cpp:112:7: error: use of deleted function 'X::X()'
     X x;
       ^   
main.cpp:104:11: note: 'X::X()' is implicitly deleted because the default definition would be ill-formed:
     union X
           ^   
main.cpp:108:11: error: union member 'X::x' with non-trivial 'constexpr Y::Y()'
         Y x;
           ^   
make: *** [main.o] Error 1

2 个答案:

答案 0 :(得分:5)

在标准中,第2段(注释中)中的[class.union]提及说明了这一点:

  

union可以有成员函数(包括构造函数和   析构函数),但不是虚函数(10.3)。工会不应该有   基类。联合不得用作基类。如果一个工会   包含程序所引用的非静态数据成员   病态的。最多一个联盟的非静态数据成员可能有一个   大括号或相等的初始值设定。 [注意:如果有任何非静态数据成员   union有一个非平凡的默认构造函数(12.1),复制构造函数   (12.8),移动构造函数(12.8),复制赋值运算符(12.8),移动   赋值运算符(12.8),或析构函数(12.4),对应的   union的成员函数必须是用户提供的,否则就是   隐含删除(8.4.3)联盟。 - 结束说明]

由于您的类具有not-default构造函数,因此编译失败。

第3段甚至提供了一个例子:

union U {
int i;
float f;
std::strings;
};

并说:

  

由于std :: string(21.3)声明了所有特殊成员函数的非平凡版本,因此U将具有隐式删除的默认构造函数,复制/移动构造函数,复制/移动赋值运算符和析构函数。要使用U,必须由用户提供部分或全部这些成员函数。


Bjarne写了同样的话:

  

如果union具有带有用户定义的构造函数,复制或析构函数的成员,则删除该特殊函数;也就是说,它不能用于union类型的对象。这是新的。

但错误的例子。 std::stringstd::complex都有非默认构造函数。因此,拥有这些的工会需要工会的构造函数。

答案 1 :(得分:0)

问题是联盟中存在m2。因为complex具有“用户定义的”构造函数,所以包含它的union的构造函数是deleted

“如果联合具有带有用户定义的构造函数,复制操作,移动操作或析构函数的成员,则会删除该联合的特殊函数; 也就是说,它不能用于联合类型的对象。“,”C ++编程语言“,第215页。

union U { int m1;
complex<double> m2; // complex has a constructor
string m3; // string has a constructor (maintaining a serious invariant) 
};

“幸运的是U不会编译。” (同一参考)