I was reading this answer, which has the following example:
struct R {};
struct S { S(R); };
struct T {
T(const T &); //1
T(S); //2
};
void f(T);
void g(R r) {
f({r});
}
The answer is related to an old version of [over.best.ics]/4, which back then looked like this:
However, when considering the argument of a constructor or user-defined conversion function that is a candidate by [over.match.ctor] when invoked for the copying/moving of the temporary in the second step of a class copy-initialization, by [over.match.list] when passing the initializer list as a single argument or when the initializer list has exactly one element and a conversion to some class X or reference to (possibly cv-qualified) X is considered for the first parameter of a constructor of X, or by [over.match.copy], [over.match.conv], or [over.match.ref] in all cases, only standard conversion sequences and ellipsis conversion sequences are considered.
In the answer it is said that without the highlighted part in the above quote, f({r})
would be ambiguous, because it could use either the first constructor of T
(1) or the second constructor (2).
However, as much as I tried, I cannot see how the first constructor (1) is an option. f({r})
results in a copy-list-initialization of T
from {r}
. If the first constructor is used, the standard allows a conversion from r
to the type of the parameter of the constructor. However, just one conversion is not enough, as one would have to go R --> S (using the converting constructor of S
)
and then S --> T (using the converting constructor of T
(2)). And I cannot find anything in the standard that allows more than one user-defined conversion in the cast of list initialization.
I may be missing something. I would appreciate if someone pointed out where I am mistaken, or if I am not, I would like to know what is the purpose of the highlighted section in the quote from the standard.
The current version of the quoted paragraph requires that the only element of the initializer list be an initializer list itself, which would make sense in the example above, if instead of f({r})
there was f({{r}})
. In that case, the explanation would be correct.
Thank you.
struct S{}; struct T{ T(T&); T(S); }
? Because now both constructors of T could be chosen? – Papaw