2016-08-21 49 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?

因爲這是他們實現它的方式,所以很可能不是他們的問題。對於希望無需修改地編譯爲另一個編譯器編寫的非標準程序的人可能會遇到問題。一般而言,這是非標準語言功能的問題。