0

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?

7
  • Teach your developers that the std::initializer_list form always has preference? Commented Jan 3, 2024 at 10:52
  • @Botje, easy to say, but not very helpful: how do you "obviously" know that std::initializer_list is a possible option for type block but not A? Commented Jan 3, 2024 at 10:57
  • There is no simple solution to the long-standing dilemma that list initialization could also call std::initializer_list constructors. This is especially annoying in templates where you don't know whether such a constructor exists. I'm voting to close this question because the answers are inevitably stylistic recommendations and opinion-based. Commented Jan 3, 2024 at 10:58
  • @JanSchultke, don't abruptly close a question just because you find it stylistic. Actual developers may spend a long time to find bugs like this. Having reasonable programming rules or advises would be really helpful for everyone. Commented Jan 3, 2024 at 11:01
  • 1
    There is no way to tell whether T{...} calls a std::initializer_list constructor without knowing which constructors T has, so the only thing people can give you are stylistic recommendations that mitigate this problem. Stylistic recommendations are opinion-based questions are off-topic for Stack Overflow. I don't make the rules. I agree that such rules/advice can be useful and there's a place for it; but that place is rather Software Engineering Stack Exchange and not SO. Commented Jan 3, 2024 at 11:05

1 Answer 1

3

In-class member initializers also support =:

block b = block(4, 5); 

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

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.