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?
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With