Looking at the following code:
#include<string>
#include<iostream>
using T = std::string;
void baz(T& v) { std::cout << v << std::endl; }
void boo(const T& v) { std::cout << v << std::endl; }
int main() {
baz( T("Passing an rvalue to be assigned to a lvalue&") ); //<--- This call is invalid
boo( T("Passing an rvalue to be assigned to a constant lvalue&") );
}
The standard tells us the first function call is invalid for obvious reason but the second function call isn't invalid because it can be interpreted as "Generate a variable bound to the scope of the function boo, which holds an lvalue equal to the rvalue passed to the function". At least as far as my understanding of the standard goes.
However, adding an auxiliary functions such as:
constexpr T &to_lvalue(T &&value) noexcept { return value; }
And calling the function baz using it to wrap parameters:
baz( to_lvalue( T("Passing a rvalue which will be transformed into an lvalue reference bound to the scope of baz") ) );
Is considered perfectly valid code and (to my understanding) it basically results in the exact same thing, namely the construction of an lvalue that is bound to the scope of baz
So why wouldn't the compile simply generate this code for you when calling baz with an rvalue ? It ads no runtime overhead and the behavior seems to be well defined. Is there something that I'm missing here ? Or is the standard defined in such a way in order not to "mistakenly" use a function that is expected to mutate a value ?