How can you tell whether list-initialization calls a std::initializer_list constructor?

118 views Asked by At

My question is about the confusion in C++ default class member initialization between using an initializer list and calling a constructor.

There is no ambiguity in the language but a possible confusion in the developer's mind, leading to obscure bugs. Do you know a good way to detect or avoid this confusion?

When declaring a variable, there is no confusion because using an initializer_list and calling a constructor use distinct syntaxes:

using block = std::vector<int>;
block a{4, 5};  // brackets => initializer list, 2 elements, with values 4 and 5
block b(4, 5);  // parentheses => constructor call, 4 elements, all with value 5

Calling a constructor in a default member initializer uses braces instead of parentheses. However, when the type of the member accepts a initializer_list, this becomes confusing:

class A
{
public:
    A(int size, int value);
};

class C
{
public:
    A     a{4, 5};        // Call constructor A(4, 5)
    block b{4, 5};        // Initializer list, not constructor call, even though same syntax
    block c{block(4, 5)}; // Force a constructor call, but awkward syntax
};

The confusion comes from whether the member's type accepts an initializer_list or not.

Do you know a nice way to handle this?

1

There are 1 answers

0
HolyBlackCat On

In-class member initializers also support =:

block b = block(4, 5);

This is slightly less awkward than block b{block(4, 5)};.