This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115e. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2024-11-11
Consider an example like:
template<typename T> struct A { A(const T&); // #1 A(T&&); // #2 }; template<typename U> A(U&&)->A<double>; // #3 int main(){ int i =0; const int ci =0; A a1(0); A a2(i); A a3(ci); }
This example is covered by 13.10.3.5 [temp.deduct.partial] paragraph 9:
If, for a given type, deduction succeeds in both directions (i.e., the types are identical after the transformations above) and both P and A were reference types (before being replaced with the type referred to above):
if the type from the argument template was an lvalue reference and the type from the parameter template was not, the parameter type is not considered to be at least as specialized as the argument type; otherwise,
if the type from the argument template is more cv-qualified than the type from the parameter template (as described above), the parameter type is not considered to be at least as specialized as the argument type.
For a2(i), the deduction guide is the best match, so this is an A<double>.
For a3(ci), the first bullet applies, which prefers #1 to #3 since #1 comes from an lvalue reference and #3 does not, resulting in an A<int>.
For a1(0), the case is not covered by partial ordering, so 12.2.4 [over.match.best] bullet 1.10 applies and prefers #3 to #2, which is again an A<double>.
It seems inconsistent to prefer #1 to #3 (T const & to U&&), but to prefer #3 to #2 (U&& to T&&). Should the rules be expanded to basically prefer any non-forwarding-reference to a forwarding reference?
Rationale (June, 2018):
There was no consensus to make a change at this point; the behavior is as intended.