Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is a constructor necessary in a const member struct?

Tags:

c++

c++11

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?

like image 305
ChronoTrigger Avatar asked Jul 24 '14 20:07

ChronoTrigger


People also ask

Do I need a constructor for a struct?

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.

Can a struct have a constructor?

Constructor creation in structure: Structures in C cannot have a constructor inside a structure but Structures in C++ can have Constructor creation.

When struct constructor is called?

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.

Can a struct member be const?

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 .


2 Answers

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).

like image 98
chris Avatar answered Sep 21 '22 14:09

chris


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.

like image 28
Yakk - Adam Nevraumont Avatar answered Sep 18 '22 14:09

Yakk - Adam Nevraumont