We are in partial-ordering land again. The type of the synthesized function template parameters are
T&& // #1: not a forwarding reference
const T& // #2
U&& // #3: a forwarding reference
The pre-partial ordering transformation strips away referenceness and after that the top-level cv-qualification, leaving us with a bare type in all three cases. It follows that in all three cases deduction succeeds in both directions. We are now left with [temp.deduct.partial]/9's tiebreaker:
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 U&&
vs T&&
, neither rule applies and there's no ordering. For U&&
vs const T&
, however, the parameter type U&&
is not considered to be at least as specialized as the argument type const T&
, per the first bullet.
Partial ordering therefore finds #2 to be more specialized than #3, but finds #1 and #3 to be indistinguishable. GCC is correct.
That said, this may well be an oversight in the partial ordering rules. Class template deduction is the first time we have a "rvalue reference to cv-unqualified template parameter that isn't a forwarding reference" thing. Previously, in double-reference cases, forwarding references will always lose to non-forwarding rvalue references at the second bullet (because the only way you get non-forwarding rvalue references is if you have cv T&&
for some non-empty cv
).