You're not "passing x
as an rvalue reference", since that statement doesn't even really make sense.
Here are a selection of facts about the taxonomy of types and expressions in C++:
There are object types and there are reference types. (There are also a few other kinds of types.)
Variables can be either objects or references.
Expressions have types, those types are (almost) always object types, never references. (That's why your statement of "passing something as a reference" doesn't make sense; you pass arguments and arguments are always expressions.) Expressions can be lvalues, xvalues or prvalues.
Lvalue references bind to lvalues. Rvalue references bind to rvalues. (An rvalue is either a prvalue or an xvalue.)
An id-expression naming a variable or parameter is an lvalue. (It's a "thing with a name", or "a location", if you will.)
Hence in the expression overloaded(x)
, the subexpression x
is an lvalue, and it does not bind to the function that expects an rvalue (on account of its rvalue reference parameter).
The "l" and "r" in "lvalue reference" and "rvalue reference" refers to the categories of values to which the reference can bind, not to the category of the id-expression naming a variable of this reference type.
You can convert an lvalue to an rvalue by casting it to an xvalue; this is conveniently encapsulated into the type-deducing cast helper std::move
.