AFAIK,下面的代码不应该编译,但它在clang和GCC中。我在这里错过了什么?

时间:2015-02-20 19:02:51

标签: c++ c++11 language-lawyer

下面的代码显示了一个类似联合的类,其中包含一个非平凡的默认构造函数(成员y使用大括号或等于初始化程序进行初始化),因此如果是默认值这类的构造函数是默认的,应根据§12.1/ 5第一个要点删除它。也就是说,声明T t;不应该编译,因为union T没有默认构造函数。但是clang和GCC中的code compiles and executes

#include <iostream>
union T
{
    int y{1};
    float x;
    char c;
    T() = default;
};

int main()
{
    T t;
    std::cout << t.y << '\n';
}

编辑

我的上述问题从一开始就是错误的,因为联盟T 类似联盟的类。我刚刚了解了C ++ 11中的§9.5/ 8,其中说:

  

类似于联盟的类是具有匿名联合的联合或类   作为直接会员。类似联合的类X有一组变体成员。   如果X是联合,则其变体成员是非静态数据成员;   否则,其变体成员是所有的非静态数据成员   作为X成员的匿名工会。

现在,请考虑下面的代码段。它不会编译,因为会删除union的默认构造函数。但我仍然,不知道§12.1/ 5中哪个要点对这个结果是负责任的。请注意,union再次不是类似于union的类,因此,§12.1/ 5中的第一个要点不适用。但这就是clang和GCC中的错误消息。请参阅live example

#include <iostream>

union T{
    int y;
    struct A{ int i; A():i{1} {} } a;
};

int main()
{
    T t;
    std::cout << t.a.i << '\n';
}

1 个答案:

答案 0 :(得分:11)

子弹是

  

X是一个类似联合的类,其变体成员具有非平凡性   默认构造函数

被解析为

  

X是一个类似联盟的类,具有(一个非平凡的变体成员)   默认构造函数)

即,“使用非平凡的默认构造函数”适用于变体成员的类型,而不是X