Reputation: 13956
I think I'm getting awfully close to understanding this. It seems that there are two overloads for the forward
function, and I thought two overloads are needed to make it work, but as far as I can see one of them is completely useless, and it works with just one:
template <typename T>
T&& forward(T&& arg)
{// Never gets called.
// I can't see how since every argument from another function is always
// an lvalue, nothing can bind to it
return static_cast<T&&>(arg);
}
template <typename T>
T&& forward(T& arg)
{// Just this one seems to do the job
return static_cast<T&&>(arg);
}
template <typename Type>
void emplace(Type&& arg)
{
forward<Type>(arg);
}
int main()
{
int a = 0;
int& intref = a;
emplace(a);
emplace(int());
}
Both call the one forward
function, the other one can go, right?
Upvotes: 1
Views: 101
Reputation: 122657
For illustration, you can change the code to this:
#include <iostream>
template <typename T>
T&& forward(T&& arg)
{
// gets called when the parameter is a rvalue reference
std::cout << "called\n";
return static_cast<T&&>(arg);
}
template <typename T>
T&& forward(T& arg)
{
return static_cast<T&&>(arg);
}
template <typename Type>
void emplace(Type&& arg)
{
forward<Type>(forward<Type>(arg));
}
int main()
{
emplace(int());
}
To get output:
called
In emplace
the call forward<Type>(arg);
does not call T&& forward(T&& arg)
because arg
in emplace
is not a rvalue reference, sloppy speaking, because it has a name. You can call void emplace(Type&& arg)
with an rvalue, but the argument arg
isn't one. Actually thats the reason std::forward
is needed in the first place.
Upvotes: 1
Reputation: 172934
The 1st overload is used for forwarding rvalues (as rvalues). E.g.
forward<int>(0);
In emplace
you're forwarding arg
which is lvalue as named variable.
Upvotes: 4