Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error when using in-class initialization of non-static data member and nested class constructor

The following code is quite trivial and I expected that it should compile fine.

struct A {     struct B     {         int i = 0;     };      B b;      A(const B& _b = B())         : b(_b)     {} }; 

I've tested this code with g++ version 4.7.2, 4.8.1, clang++ 3.2 and 3.3. Apart from fact that g++ 4.7.2 segfaults on this code (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57770), the other tested compilers give error messages that don't explain much.

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 and 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())                     ^ 

Making this code compilable is possible and seems like it should make no difference. There are two options:

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

or

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

Is this code really incorrect or are the compilers wrong?

like image 242
etam1024 Avatar asked Jul 02 '13 16:07

etam1024


People also ask

Where can a non-static reference member variable of a class be initialised?

Member initialization Non-static data members may be initialized in one of two ways: 1) In the member initializer list of the constructor.

What is non-static member c++?

A non-static member function is a function that is declared in a member specification of a class without a static or friend specifier. ( see static member functions and friend declaration for the effect of those keywords)

What is non-static data member in C++ with example?

Non-static data members are the variables that are declared in a member specification of a class. And they have the example: class S { int& r; // non-static data member of reference type };

How do you initialize a data member in C++?

Static Data Member Initialization in C++ We can put static members (Functions or Variables) in C++ classes. For the static variables, we have to initialize them after defining the class. To initialize we have to use the class name then scope resolution operator, then the variable name. Now we can assign some value.


1 Answers

Is this code really incorrect or are the compilers wrong?

Well, neither. The standard has a defect -- it says both that A is considered complete while parsing the initializer for B::i, and that B::B() (which uses the initializer for B::i) can be used within the definition of A. That's clearly cyclic. Consider this:

struct A {   struct B {     int i = (A(), 0);   };   A() noexcept(!noexcept(B())); }; 

This has a contradiction: B::B() is implicitly noexcept iff A() does not throw, and A() does not throw iff B::B() is not noexcept. There are a number of other cycles and contradictions in this area.

This is tracked by core issues 1360 and 1397. Note in particular this note in core issue 1397:

Perhaps the best way of addressing this would be to make it ill-formed for a non-static data member initializer to use a defaulted constructor of its class.

That's a special case of the rule that I implemented in Clang to resolve this issue. Clang's rule is that a defaulted default constructor for a class cannot be used before the non-static data member initializers for that class are parsed. Hence Clang issues a diagnostic here:

    A(const B& _b = B())                     ^ 

... because Clang parses default arguments before it parses default initializers, and this default argument would require B's default initializers to have already been parsed (in order to implicitly define B::B()).

like image 154
Richard Smith Avatar answered Sep 21 '22 21:09

Richard Smith