Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do I really need to implement user-provided constructor for const objects?

I have the code:

class A {   public:     A() = default;    private:     int i = 1; };  int main() {   const A a;   return 0; } 

It compiles fine on g++ (see ideone), but fails on clang++ with error:

default initialization of an object of const type 'const A' requires a user-provided default constructor

I reported this issue on LLVM bug-tracker and got it INVALID.

I see it absolutly pointless to try to convince the clang developers. On the other side, I don't see the reason for such restriction.


Can anyone advise, if the C++11 Standard somehow implies this code to be invalid? Or should I just report a bug to g++? Or maybe there is enough freedom in language rules to handle this code in many ways?

like image 610
abyss.7 Avatar asked Feb 20 '14 06:02

abyss.7


People also ask

Are default constructors necessary?

What is the default constructor? Java doesn't require a constructor when we create a class. However, it's important to know what happens under the hood when no constructors are explicitly defined. The compiler automatically provides a public no-argument constructor for any class without constructors.

Can we declare constructor as const?

Constructors may be declared as inline , explicit , friend , or constexpr . A constructor can initialize an object that has been declared as const , volatile or const volatile . The object becomes const after the constructor completes.


Video Answer


2 Answers

N3797 §8.5/7 says:

If a program calls for the default initialization of an object of a const-qualified type T, T shall be a class type with a user-provided default constructor.

There's no further example or explanation of this. I agree it seems pretty bizarre. Furthermore the rule was updated in C++11 to be more restrictive than it was in C++03, when class types needed user-declared constructors. (Your constructor is user-declared.)

The workaround is be to ask for value initialization using {}, or use Dietmar's clever out-of-class inline definition.

GCC does provide a diagnosis (and quite a nice one, referring to the newer C++11 requirements) if you add another member without an initializer.

  private:     int i = 1;     int j; 

 

unmem.cpp:11:11: error: uninitialized const ‘a’ [-fpermissive]    const A a;            ^ unmem.cpp:1:7: note: ‘const class A’ has no user-provided default constructor  class A {        ^ unmem.cpp:3:5: note: constructor is not user-provided because it is explicitly defaulted in the class body      A() = default;      ^ unmem.cpp:7:9: note: and the implicitly-defined constructor does not initialize ‘int A::j’      int j; 

The GCC source refers to DR 253, Why must empty or fully-initialized const objects be initialized? This is an open issue in the standard, last updated in August 2011 (post-C++11) with this note:

If the implicit default constructor initializes all subobjects, no initializer should be required.

Therefore whereas Clang complies with C++11 (and will comply as-is with C++14), GCC is implementing the latest thinking of the standardization committee.

Filed a GCC bug. I predict that you'll need -pedantic to get a diagnosis when (and if) the bug is fixed.

like image 139
Potatoswatter Avatar answered Sep 20 '22 15:09

Potatoswatter


Note that you can turn your class easily into one which has a user-defined default constructor:

class A {   public:     A();    private:     int i = 1; };  inline A::A() = default; 

According to 8.4.2 [dcl.fct.def.default] paragraph 4:

... A special member function is user-provided if it is user-declared and not explicitly defaulted or deleted on its first declaration. ...

This implicitly states that a function which is not explicitly defaulted on its first declaration is not user-provided. In combination with 8.5 [dcl.init] paragraph 6

... If a program calls for the default initialization of an object of a const-qualified type T, T shall be a class type with a user-provided default constructor.

it seems clear that you cannot use a default constructor defaulted on its first declaration to initialize a const object. However, you can use a defaulted definition if it isn't the first declaration as is done in the code above.

like image 44
Dietmar Kühl Avatar answered Sep 23 '22 15:09

Dietmar Kühl