Search code examples
c++c++11vectorinitializationlist-initialization

C++11: () or {} in List-initialization?


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?


Solution

  • 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 class T 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.