Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rules for Anonymous Aggregates

Consider the following:

#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, and Intel C++ all compile it fine. But g++4.9 foo.cpp -std=c++11 tells me:

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

Notice that the static_asserts ensure that MyType is a standard layout type, a trivial type, and moreover is actually POD (note that after C++11, PODs are allowed to have constructors).


I couldn't find anything authoritative about what types are allowed inside anonymous structures. What I did find (mostly here on SO) suggest that being a POD type is sufficient. Apparently, it is not.

My question: If being a POD type is actually insufficient for being in an anonymous structure, what is sufficient? Or perhaps, since GCC is differing from all other compilers, is this a problem with GCC?

like image 371
imallett Avatar asked Aug 21 '16 23:08

imallett


1 Answers

As far as standards are concerned, anonymous structs are a C feature. They are not allowed by any C++ standard.

I could not find detailed gcc documentation about their extension to provide the feature in C++. What little I found is here, but that page appears to only describe the extension for C (prior to C11, this feature was not standard).

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

It indeed appears to be insufficient. The error message explains quite clearly that having a (non-trivial) constructor disqualifies a class from being an anonymous aggregate (structure). A POD would guarantee this only prior to C++11.

Since there appears to be little documentation for the extension, and since anonymous structs are a C feature, I'm tempted to guess that any such aggregate must not use C++ features. I believe that pre-C++11 definition of a POD satisfies such requirement.

A quick test appears to agree with my hypothesis. If you remove the constructor, the program compiles with the extension enabled. If you name the struct member (promoting the type to be unnamed), the program becomes well formed standard C++, and also compiles.

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

Since that's the way they implemented it, it quite possibly isn't a problem with them. It could be a problem to someone who wishes to compile without modification, a non-standard program written for another compiler. This is a problem with non-standard language features in general.

like image 63
eerorika Avatar answered Nov 10 '22 04:11

eerorika