Erreur lors de l'utilisation en classe de l'initialisation de la non-membre de données statiques et imbriquées constructeur de la classe

Le code suivant est assez banal et j'attendais qu'il doit compiler amende.

struct A
{
    struct B
    {
        int i = 0;
    };

    B b;

    A(const B& _b = B())
        : b(_b)
    {}
};

J'ai testé ce code avec g++ version 4.7.2, 4.8.1, clang++ 3.2 et 3.3. Hormis le fait que g++ 4.7.2 de segmentation sur ce code (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57770), les autres testés compilateurs donner les messages d'erreur que de ne pas expliquer beaucoup de.

g++ 4.8.1:

test.cpp: In constructor constexpr A::B::B()’:
test.cpp:3:12: error: constructor required before non-static data member for A::B::i has been parsed
     struct B
            ^
test.cpp: At global scope:
test.cpp:11:23: note: synthesized method constexpr A::B::B()’ first required here 
     A(const B& _b = B())
                       ^

clang++ 3.2 et 3.3:

test.cpp:11:21: error: defaulted default constructor of 'B' cannot be used by non-static data member initializer which appears before end of class definition
    A(const B& _b = B())
                    ^

Du présent code compilable est possible et semble comme il devrait pas faire de différence. Il y a deux options:

struct B
{
    int i = 0;
    B(){} //using B()=default; works only for clang++
};

ou

struct B
{
    int i;
    B() : i(0) {} //classic c++98 initialization
};

Est ce code vraiment incorrect ou sont les compilateurs de mal?

Mon G++ 4.7.3 dit internal compiler error: Segmentation fault à ce code...
(erreur C2864: "A::B::i' : seulement static const partie intégrante de membres de données peuvent être initialisées dans une classe) est ce que VC2010 dit. Cette sortie est d'accord avec g++. Clang, dit-elle, si elle fait beaucoup moins de sens. Vous ne pouvez pas par défaut d'une variable dans une struct en faisant int i = 0, sauf si elle est static const int i = 0.
BTW, je voudrais éviter la tentation de penser de l'expression B() comme un appel de fonction à un constructeur. Vous jamais directement "appel" d'un constructeur. Penser à cela comme une syntaxe spéciale qui crée un temporaire B... et le constructeur est appelé comme une partie seulement de ce processus, profondément à l'intérieur du mécanisme que la façon suivante.
Hmm, l'ajout d'un constructeur à B semble faire ce travail dans gcc 4.7.
Fait intéressant, le déplacement de la définition d'Un constructeur d'Une aussi semble pour le faire fonctionner (g++ 4.7); qui s'accorde avec "par défaut dans le constructeur par défaut ne peut pas être utilisé... avant la fin de la définition de la classe".

OriginalL'auteur etam1024 | 2013-07-02