Consider what would happen if you didn't have that overload, and try to pass in a const
rvalue:
template <typename T> const T &as_const(T &t) { return t; }
struct S { };
const S f() { return S{}; }
int main() {
// auto & ref = as_const(S()); // correctly detected as invalid already
auto & ref = as_const(f()); // accepted
}
This would be accepted because T
would be deduced as const S
, and temporaries can bind to const S &
. The result would be that you accidentally get an lvalue reference to a temporary, which will be destroyed right after ref
has been initialised. Almost all users taking lvalues (whether variables or function parameters) don't expect to be passed temporaries; silently accepting temporaries means that you easily silently get dangling references.