I have a code similar to this:
class AClass { public: struct AStruct { }; AClass(){} private: const AStruct m_struct; }; int main() { AClass a; }
It throws this compilation error (with Clang LLVM version 5.1):
error: constructor for 'AClass' must explicitly initialize the const member 'm_struct'
If I specify a C++11 default constructor for struct AStruct
, I get the same error:
struct AStruct { AStruct() = default; };
However, this is solved by writing a constructor with an empty body:
struct AStruct { AStruct(){} // fixed };
Why do I need to specify an empty constructor? Isn't it automatically created with public access for structs?
Why does not the C++11 default constructor solve the problem?
Technically, a struct is like a class , so technically a struct would naturally benefit from having constructors and methods, like a class does. But this is only “technically” speaking.
Constructor creation in structure: Structures in C cannot have a constructor inside a structure but Structures in C++ can have Constructor creation.
A structure called Struct allows us to create a group of variables consisting of mixed data types into a single unit. In the same way, a constructor is a special method, which is automatically called when an object is declared for the class, in an object-oriented programming language.
You can const individual members of a struct. Declaring an entire instance of a struct with a const qualifier is the same as creating a special-purpose copy of the struct with all members specified as const .
From §8.5 [dcl.init]/7:
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.
The default constructor of AClass
default-initializes the const
member (see below), so that member must have a user-provided default constructor. Using = default
does not result in a user-provided default constructor, as can be seen in §8.4.2 [dcl.fct.def.default]/4:
A function is user-provided if it is user-declared and not explicitly defaulted or deleted on its first declaration.
The member is default-initialized per §12.6.2 [class.base.init]/8:
In a non-delegating constructor, if a given non-static data member or base class is not designated by a mem-initializer-id (including the case where there is no mem-initializer-list because the constructor has no ctor-initializer) and the entity is not a virtual base class of an abstract class (10.4), then
— if the entity is a non-static data member that has a brace-or-equal-initializer , the entity is initialized as specified in 8.5;
— otherwise, if the entity is an anonymous union or a variant member (9.5), no initialization is performed;
— otherwise, the entity is default-initialized (8.5).
Stolen from @chris's answer we have this paragraph: §8.5 [dcl.init]/7:
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.
We can then construct a completely ridiculous case that illustrates this restriction:
struct Foo {}; int main() { const Foo f; }
which fails to compile in clang, as the standard dictates. Your code is simply this, but as a member variable of another class/struct.
We can even do this:
struct Foo {int x = 3;}; int main() { const Foo f; }
where all the data is obviously initialized. This last example convinces me that this is a defect in the standard.
The thought was probably something to do with POD types being uninitialized and const
, but the wording blocks code that is unrelated. Default constructors in modern C++ are often more than good enough, and forcing Foo(){}
is poor form.
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