Due to the fact that the general question "how std::forward
works" is too complicated I decided to start with a question on a particular example:
#include <utility>
#include <iostream>
namespace
{
void foo(const int&)
{
std::cout << "const l-value" << std::endl;
}
void foo(int&)
{
std::cout << "l-value" << std::endl;
}
void foo(int&&)
{
std::cout << "r-value" << std::endl;
}
template <typename T>
void deduce(T&& x)
{
//foo(std::forward<T>(x));
foo(x);
}
}
int main()
{
deduce(1);
return 0;
}
The output:
l-value
Why?
We pass r-value and the argument of deduce
is r-value, right? Why is foo(int&)
called?
When I call directly
foo(1);
it prints r-value
. When does it become l-value inside deduce
?
EDIT1
If I add foo2
to the code above:
void foo2(int&& val)
{
static_assert(std::is_same_v<decltype(val), int&&>);
foo(val);
}
and then call it from main
foo2(1);
l-value
is printed but not r-value
as I probably expected.
So, as mentioned in comments and answers, val
is l-value because it is a named variable and it does not matter if it is declared as int&&
or int&
. That is something that I did not know before.