I am referring to "The working draft N3337", which is said most similar to the published C++11 standard.
If there are matchable constructors, then it call constructors.
Example (p200):
struct S {
// no initializer-list constructors
S(int, double, double); // #1
S(); // #2
// ...
};
S s1 = { 1, 2, 3.0 }; // OK: invoke #1
S s2 { 1.0, 2, 3 }; // error: narrowing
Otherwise, it will use aggregate initialization.
Now, here is an example using vector
, which has an explicit constructor from size_t
and an initializer_list
constructor:
vector<double> v1(7); // ok: v1 has 7 elements
vector<double> v1{7}; // ok: v1 has 1 element (with its value 7.0)
Here I am confused. Why is there different behavior for the vector
constructors than there was for S
?
Because the initializer_list
overload is strongly preferred to all the other ones. From [over.match.list]:
When objects of non-aggregate class type
T
are list-initialized (8.5.4), overload resolution selects the constructor in two phases:(1.1) — Initially, the candidate functions are the initializer-list constructors (8.5.4) of the class
T
and the argument list consists of the initializer list as a single argument.
(1.2) — If no viable initializer-list constructor is found, overload resolution is performed again, where the candidate functions are all the constructors of the classT
and the argument list consists of the elements of the initializer list.
vector
is a non-aggregate class, which has two relevant constructors:
explicit vector( size_type count ); // (3)
vector( std::initializer_list<T> init, // (7)
const Allocator& alloc = Allocator() );
Based on the ordering described in [over.match.best], since (7) is a viable constructor candidate, we don't get to point (1.2) where (3) would be considered.