请考虑以下事项:
#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
确保MyType
是standard layout类型,trivial type,而且实际上是POD(请注意,在C +之后+11,允许POD拥有构造函数。)
我无法找到任何关于匿名结构中允许的类型的权威内容。我所做的(主要是在SO上)表明,作为POD类型就足够了。显然,事实并非如此。
我的问题:如果作为POD类型实际上不足以进入匿名结构,那么 是否足够?或者,由于GCC与其他所有编译器不同,这是否是GCC的问题?
答案 0 :(得分:5)
就标准而言,匿名结构是C功能。任何C ++标准都不允许使用它们。
我无法找到有关其扩展名的详细gcc文档,以便在C ++中提供该功能。我发现的很少here,但该页面似乎只描述C的扩展名(在C11之前,此功能不是标准的)。
我的问题:如果作为POD类型实际上不足以进入匿名结构,
确实似乎不够。错误消息非常清楚地解释了有一个(非平凡的)构造函数使一个类不能成为匿名聚合(结构)。 POD只能在C ++ 11之前保证这一点。
由于扩展的文档似乎很少,并且由于匿名结构是C特性,我很想猜测任何这样的聚合都不能使用C ++特性。我相信POD的前C ++ 11定义满足了这样的要求。
快速测试似乎与我的假设一致。如果删除构造函数,程序将在启用扩展时进行编译。如果您命名结构成员(将类型提升为未命名),该程序将成为格式良好的标准C ++,并且还可以编译。
或许,由于GCC与其他所有编译器不同,这是GCC的问题吗?
由于这是他们实施它的方式,很可能不是他们的问题。对于希望编译而不进行修改的人来说,这可能是一个问题,这是为另一个编译器编写的非标准程序。这是一般非标准语言功能的问题。