2016-08-21 46 views
5

考虑以下几点:规则的匿名聚合

#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,锵,和英特尔C++编译所有它的罚款。但g++4.9 foo.cpp -std=c++11告诉我:

14 : error: member 'MyType Wrapper::<anonymous struct>::t' with constructor not allowed in anonymous aggregate
MyType t;
^
Compilation failed

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


我找不到任何关于匿名结构中允许的类型的权威性。我所发现的(大多数是在SO上)表明,作为POD类型就足够了。显然,它不是。

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

+2

[不在Clang中编译](http://melpon.org/wandbox/permlink/EymdTe46Ss7Sn1xA);不是格式良好的C++。 –

+0

@KerrekSB:当您将匿名结构更改为常规未命名结构时,它会[编译](http://melpon.org/wandbox/permlink/4S88COP93nH4zyeV)。当然,我不确定OP是否能够理解差异。(http://stackoverflow.com/q/14248044/734069)虽然我认为他的问题主要是关于未命名结构中复杂类型的行为,但OP在我们可以继续之前需要澄清。 –

+0

@NicolBolas我现在更好地理解术语。但是,问题仍然存在于哪些条件下 - GCC接受该代码。显然,这不是必需的 - 因为只有未命名的结构是目前为止的标准 - 但我很惊讶是POD类型是不够的。 – imallett

回答

5

就标准而言,匿名结构是C特征。它们不被任何C++标准所允许。

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

My question: If being a POD type is actually insufficient for being in an anonymous structure,

确实看起来不足。该错误消息非常清楚地解释了具有(非平凡)构造函数使类不能作为匿名聚合(结构)。 POD只能在C++ 11之前保证这一点。

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

一个快速测试似乎与我的假设一致。如果您删除构造函数,程序将在启用扩展的情况下编译。如果你命名结构成员(提升类型为未命名的),程序就会形成标准的C++,并编译。

Or perhaps, since GCC is differing from all other compilers, is this a problem with GCC?

因为这是他们实现它的方式,所以很可能不是他们的问题。对于希望无需修改地编译为另一个编译器编写的非标准程序的人可能会遇到问题。一般而言,这是非标准语言功能的问题。