Consider the following code:
#include <cstdio>
struct S {
S(int) {}
};
void f(const S&) { std::puts("const S&"); }
void f(S&&) { std::puts("S&&"); }
int main() {
f(42);
}
It may be obvious, and GCC and Clang agree, that the S&& overload should be called, but my reading of the standard is that there is actually no rule requiring this to be the case!
Of course, you will say that the call to f has to initialize a temporary S object and that overload resolution prefers to bind an rvalue reference to an rvalue rather than binding an lvalue reference. However, this is what the standard actually says in [over.ics.rank]/(3.2):
Standard conversion sequence
S1is a better conversion sequence than standard conversion sequenceS2if...
S1andS2are reference bindings (11.6.3) and neither refers to an implicit object parameter of a non-static member function declared without a ref-qualifier, andS1binds an rvalue reference to an rvalue andS2binds an lvalue reference...
Thus, this tiebreaker concerning lvalue and rvalue reference bindings only applies to standard conversion sequences. But a user-defined conversion sequence would be required in order to call either overload of f given the int argument. The rule for ranking user-defined conversion sequences is (3.3),
User-defined conversion sequence
U1is a better conversion sequence than another user-defined conversion sequenceU2if they contain the same user-defined conversion function or constructor or they initialize the same class in an aggregate initialization and in either case the second standard conversion sequence ofU1is better than the second standard conversion sequence ofU2.
Clearly, both conversion sequences (to const S& and S&&) call the same constructor, so the second one could be better than the first if its second standard conversion is better than that of the first. However, [over.ics.ref]/2 says:
When a parameter of reference type is not bound directly to an argument expression, the conversion sequence is the one required to convert the argument expression to the referenced type according to 16.3.3.1. Conceptually, this conversion sequence corresponds to copy-initializing a temporary of the referenced type with the argument expression. Any difference in top-level cv-qualification is subsumed by the initialization and does not constitute a conversion.
Based on my reading of this, the implicit conversion sequence for int to const S& is identical to the user-defined conversion sequence for int to const S, which is simply a single user-defined conversion with the second standard conversion being the identity conversion; similarly, the implicit conversion sequence for int to S&& is identical to the user-defined conversion sequence for int to S, which is also a single user-defined conversion with the second standard conversion being the identity conversion.
Therefore, there's no textual basis for the "obvious" choice of the second overload... or is there one that I'm missing?