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?
std::initializer_listform always has preference?std::initializer_listis a possible option for typeblockbut notA?std::initializer_listconstructors. 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.T{...}calls astd::initializer_listconstructor without knowing which constructorsThas, 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.