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