匿名聚合规则

时间:2016-08-21 23:44:22

标签: c++ c++11 constructor anonymous-types

请考虑以下事项:

#include <type_traits>

struct MyType {
    int val;
    MyType(void) = default;
    MyType(int v) : val(v) {}
};
static_assert(std::is_standard_layout<MyType>::value,"Implementation error!");
static_assert(std::is_trivial<MyType>::value,"Implementation error!");
static_assert(std::is_pod<MyType>::value,"Implementation error!");

struct Wrapper {
    struct {
        MyType t;
    };
};

MSVC,Clang和Intel C ++都编译得很好。但g++4.9 foo.cpp -std=c++11告诉我:

  

14:错误:成员&#39; MyType Wrapper ::&lt; anonymous struct&gt; :: t&#39;匿名聚合中不允许使用构造函数
  MyType t;
  ^
  编译失败

请注意,static_assert确保MyTypestandard layout类型,trivial type,而且实际上是POD(请注意,在C +之后+11,允许POD拥有构造函数。)

我无法找到任何关于匿名结构中允许的类型的权威内容。我所做的(主要是在SO上)表明,作为POD类型就足够了。显然,事实并非如此。

我的问题:如果作为POD类型实际上不足以进入匿名结构,那么 是否足够?或者,由于GCC与其他所有编译器不同,这是否是GCC的问题?

1 个答案:

答案 0 :(得分:5)

就标准而言,匿名结构是C功能。任何C ++标准都不允许使用它们。

我无法找到有关其扩展名的详细gcc文档,以便在C ++中提供该功能。我发现的很少here,但该页面似乎只描述C的扩展名(在C11之前,此功能不是标准的)。

  

我的问题:如果作为POD类型实际上不足以进入匿名结构,

确实似乎不够。错误消息非常清楚地解释了有一个(非平凡的)构造函数使一个类不能成为匿名聚合(结构)。 POD只能在C ++ 11之前保证这一点。

由于扩展的文档似乎很少,并且由于匿名结构是C特性,我很想猜测任何这样的聚合都不能使用C ++特性。我相信POD的前C ++ 11定义满足了这样的要求。

快速测试似乎与我的假设一致。如果删除构造函数,程序将在启用扩展时进行编译。如果您命名结构成员(将类型提升为未命名),该程序将成为格式良好的标准C ++,并且还可以编译。

  

或许,由于GCC与其他所有编译器不同,这是GCC的问题吗?

由于这是他们实施它的方式,很可能不是他们的问题。对于希望编译而不进行修改的人来说,这可能是一个问题,这是为另一个编译器编写的非标准程序。这是一般非标准语言功能的问题。