Date
2014-06-15.00:00:00
Message id
5386

Content

Proposed resolution (June, 2014):

  1. Change 9.5.5 [dcl.init.list] paragraph 3 as follows:

  2. List-initialization of an object or reference of type T is defined as follows:

    • If T is a class type and the initializer list has a single element of type cv U, where U is T or a class derived from T, the object is initialized from that element (by copy-initialization for copy-list-initialization, or by direct-initialization for direct-list-initialization).

    • Otherwise, if T is a character array and the initializer list has a single element that is an appropriately-typed string literal (9.5.3 [dcl.init.string]), initialization is performed as described in that section.

    • If Otherwise, if T is an aggregate,

    • Otherwise, if the initializer list has no elements...

    • Otherwise, if T is a specialization of std::initializer_list<E>...

    • Otherwise, if T is a class type...

    • Otherwise, if the initializer list has a single element of type E and either T is not a reference type or its referenced type is reference-related to E, the object or reference is initialized from that element (by copy-initialization for copy-list-initialization, or by direct-initialization for direct-list-initialization); if a narrowing conversion (see below) is required to convert the element to T, the program is ill-formed. [Example:...

    • Otherwise...

  3. Change 12.2.2.8 [over.match.list] paragraph 1 as follows:

  4. When objects of non-aggregate class type T are list-initialized (9.5.5 [dcl.init.list]) such that 9.5.5 [dcl.init.list] specifies that overload resolution is performed according to the rules in this section, overload resolution selects the constructor...
  5. Change 12.2.4.2 [over.best.ics] paragraph 4 as follows:

  6. ...and the constructor or user-defined conversion function is a candidate by

    • 12.2.2.4 [over.match.ctor], when the argument is the temporary in the second step of a class copy-initialization, or

    • 12.2.2.5 [over.match.copy], 12.2.2.6 [over.match.conv], or 12.2.2.7 [over.match.ref] (in all cases), or

    • the second phase of 12.2.2.8 [over.match.list] when the initializer list has exactly one element, and the target is the first parameter of a constructor of class X, and the conversion is to X or reference to (possibly cv-qualified) X,

    user-defined conversion sequences are not considered.

  7. Change 12.2.4.2.6 [over.ics.list] paragraphs 1-2 as follows, moving the footnote from paragraph 3:

  8. When an argument is an initializer list (9.5.5 [dcl.init.list]), it is not an expression and special rules apply for converting it to a parameter type.

    If the parameter type is a class X and the initializer list has a single element of type cv U, where U is X or a class derived from X, the implicit conversion sequence is the one required to convert the element to the parameter type.

    Otherwise, if the parameter type is a character array [Footnote: Since there are no parameters of array type, this will only occur as the underlying type of a reference parameter. —end footnote] and the initializer list has a single element that is an appropriately-typed string literal (9.5.3 [dcl.init.string]), the implicit conversion sequence is the identity conversion.

    If Otherwise, if the parameter type is std::initializer_list<X> and...

  9. Change 12.2.4.2.6 [over.ics.list] paragraph 7 as follows:

  10. Otherwise, if the parameter type is not a class:

    • if the initializer list has one element that is not itself an initializer list, the implicit conversion sequence is the one required to convert the element to the parameter type; [Example:...

  11. Move the final bullet of 12.2.4.3 [over.ics.rank] paragraph 3 to the beginning of the list and change it as follows:

    • List-initialization sequence L1 is a better conversion sequence than list-initialization sequence L2 if

      • L1 converts to std::initializer_list<X> for some X and L2 does not, or, if not that,

      • L1 converts to type “array of N1 T”, L2 converts to type “array of N2 T”, and N1 is smaller than N2.,

      even if one of the other rules in this paragraph would otherwise apply. [Example:

        void f1(int);                                 // #1
        void f1(std::initializer_list<long>);         // #2
        void g1() { f1({42}); }                       // chooses #2
      
        void f2(std::pair<const char*, const char*>); // #3
        void f2(std::initializer_list<std::string>);  // #4
        void g2() { f2({"foo","bar"}); }              // chooses #4
      

      end example]

This resolution also resolves issues 1490, 1589, 1631, 1756, and 1758.