Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does an explicitly declared constructor prevent member initialisation with a C++ 11 initialisation list?

I want to initialize a struct with an initialisation list like this:

struct S
{
    int a;
    int b;

    // S() : a(0), b(0){}  // uncommenting will cause compile error: 
                           // error C2440: 'initializing' : cannot convert from 'initializer-list' to 'S'

    // S(int aArg, int bArg) : a(aArg), b(bArg) {}    // adding this removes the error
}

int main()
{
    S s{1,2};   // initialise with list
}

Is there a good reason, why the explicitly declared default constructor will cause the error? I thought the initialisation lists where introduced to spare the programmer from writing tedious code like the second constructor.

like image 453
Knitschi Avatar asked Jun 27 '26 18:06

Knitschi


2 Answers

Aggregate initialization - as the name implies - only works for aggregates. Adding a non-trivial constructor to a class makes it a non-aggregate. [dcl.init.list]/3:

List-initialization of an object or reference of type T is defined as follows:
— If the initializer list has no elements and T is a class type with a default constructor, the object is value-initialized.
— Otherwise, if T is an aggregate, aggregate initialization is performed (8.5.1).
— Otherwise, […]

And

An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1), […]
When an aggregate is initialized by an initializer list, as specified in 8.5.4, the elements of the initializer list are taken as initializers for the members of the aggregate, in increasing subscript or member order.

Once your class isn't an aggregate anymore, list-initialization will look for a constructor to call, not the members to initialize.

The reason is quite simple: If a class has non-trivial constructors, the only way to validly initialize an object of that class type is to call one of the constructors for that object. Initializing a class object without a corresponding constructor would be a devastating design failure.

like image 170
Columbo Avatar answered Jun 29 '26 06:06

Columbo


It is supposed that it is the explicit defined constructor that will initialize the structure. So when an initializer list is used then the compiler searches an appropriate constructor. As you already pointed out yourself if to declare a constructor with two parameters of type int then you can use the initializer list to initialize data members of the structure because this constructor will be called. Or you could provide a constructor that has one parameter of type std::initializer_list.

For example

S( std::initializer_list<int> );
like image 34
Vlad from Moscow Avatar answered Jun 29 '26 07:06

Vlad from Moscow



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!