From CPP reference on list-initialisation:
Otherwise, the constructors of T are considered, in two phases:
All constructors that take std::initializer_list as the only argument, or as the first argument if the remaining arguments have default values, are examined, and matched by overload resolution against a single argument of type std::initializer_list
If the previous stage does not produce a match, all constructors of T participate in overload resolution against the set of arguments that consists of the elements of the braced-init-list, with the restriction that only non-narrowing conversions are allowed. If this stage produces an explicit constructor as the best match for a copy-list-initialization, compilation fails (note, in simple copy-initialization, explicit constructors are not considered at all)
So a constructor using initializer_list
is considered first. Failing that, each element of the list is considered as arguments for constructors. However
#include <iostream>
using namespace std;
struct A{
template <typename... Args> A(Args... li) { cout << sizeof...(Args) << endl;}
};
int main(){
A a = {2,3,4};
}
The output is 3
which indicates that Args...
unpacks as int, int, int
. Why is it that Args... was not simply made the singular initializer_list<int>
, which the details on list-initialisation indicated would be the first attempted type of constructor?
[temp.deduct.call]/1 Template argument deduction is done by comparing each function template parameter type (call it
P
) with the type of the corresponding argument of the call (call itA
) as described below. If removing references and cv-qualifiers fromP
givesstd::initializer_list<P'>
for someP'
and the argument is an initializer list (8.5.4), then deduction is performed instead for each element of the initializer list, takingP'
as a function template parameter type and the initializer element as its argument. Otherwise, an initializer list argument causes the parameter to be considered a non-deduced context (14.8.2.5).
Emphasis mine. For this reason, template argument deduction for the constructor from an argument of type initializer_list<int>
fails.