This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 116a. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2024-12-19


2137. List-initialization from object of same type

Section: 9.4.5  [dcl.init.list]     Status: CD4     Submitter: Richard Smith     Date: 2015-06-10

[Adopted at the June, 2016 meeting.]

It is not clear in code like the following that selecting a copy/move constructor is the correct choice when an initializer list contains a single element of the type being initialized, as required by issue 1467:

  #include <initializer_list>
  #include <iostream>

  struct Q {
    Q() { std::cout << "default\n"; }
    Q(Q const&) { std::cout << "copy\n"; }
    Q(Q&&) { std::cout << "move\n"; }
    Q(std::initializer_list<Q>) { std::cout << "initializer list\n"; }
  };

  int main() {
    Q x = Q { Q() };
  }

Here the intent is that Q objects can contain other Q objects, but this is broken by the resolution of issue 1467.

Perhaps the presence of an initializer-list constructor should change the outcome?

Proposed resolution (April, 2016):

  1. Change 9.4.5 [dcl.init.list] bullet 3.1 as follows:

  2. List-initialization of an object or reference of type T is defined as follows:
  3. Change 12.2.4.2.6 [over.ics.list] paragraph 2 as follows:

  4. If the parameter type is a an aggregate 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.
  5. Change 12.2.4.2.6 [over.ics.list] paragraph 6 as follows, breaking the existing running text into a bulleted list:

  6. Otherwise, if the parameter is a non-aggregate class X and overload resolution per 12.2.2.8 [over.match.list] chooses a single best constructor C of X to perform the initialization of an object of type X from the argument initializer list, list:

    If multiple constructors are viable...