Is there any potential semantic difference when I use trailing comma during uniform initialization?
std::vector< std::size_t > v1{5, }; // allowed syntax
std::vector< std::size_t > v2{10};
Can I use trailing comma to make compiler to select std::vector::vector(std::initializer_list< std::size_t >)
constructor instead of std::vector::vector(std::size_t, const std::size_t &)
or are there any other tricks with mentioned syntax?
Can I use it to detect is there std::initializer_list
-constructor overloading?
Considering the following code, which constructor must be selected?
struct A { A(int) { ; } A(double, int = 3) { ; } };
A a{1};
A b{2, };
This code is accepted by gcc 8
and A(int)
is selected in both cases.
First, The C++ grammar rules makes the trailing
,
optional for braced-init-list. To quote dcl.init/1Secondly, you can't pretty much override the overload resolution system. It will always use the
std::initializer_list
constructor if you use such syntax and suchstd::initializer_list
constructor is available.dcl.init.list/2:
The program below prints
Using InitList
:Despite the fact that
5
is a literal of typeint
, it should have made sense to select the single argument constructor since its a perfect match; and thestd::initializer_list<double>
constructor wants a list ofdouble
. However, the rules favourstd::initializer_list<double>
because its an initializer-list constructor.As a result, even the program below fails because of narrowing conversion:
In response to your comment below, "what if there is no overloading with std::initializer_list, or it is not the first constructor's parameter?" - then overload resolution doesn't choose it. Demo:
Prints:
If there is no initializer-list constructor available, then the
{initializer-list...,}
initializer pretty much falls back to direct initialization as per dcl.init/16, whose semantics are covered by the proceeding paragraph of dcl.init/16