Created on 2015-06-10.00:00:00 last changed 95 months ago
Proposed resolution (April, 2016):
Change 9.4.5 [dcl.init.list] bullet 3.1 as follows:
List-initialization of an object or reference of type T is defined as follows:
If T is
a class typean aggregate class 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)....
Change 12.2.4.2.6 [over.ics.list] paragraph 2 as follows:
If the parameter type isaan 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.
Change 12.2.4.2.6 [over.ics.list] paragraph 6 as follows, breaking the existing running text into a bulleted list:
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 C is not an initializer-list constructor 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 has Exact Match rank if U is X, or Conversion rank if U is derived from X
Otherwise, the implicit conversion sequence is a user-defined conversion sequence with the second standard conversion sequence an identity conversion.
If multiple constructors are viable...
[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?
History | |||
---|---|---|---|
Date | User | Action | Args |
2017-02-06 00:00:00 | admin | set | messages: + msg6102 |
2017-02-06 00:00:00 | admin | set | status: drafting -> cd4 |
2015-06-10 00:00:00 | admin | create |