std::forward
Most of the article was inspired from this brilliant answer from stackoverflow.
Forwarding
Given an expression E(a,b,c,d ...)
, each of some templated type, we want f(a,b,c,d...)
to be equivalent. So nest E
inside f
.
This cannot be accomplished by C++03.
- Case 1: you use lvalue refs for
f
. This fails to handle rvalue cases. - Case 2: const lvalue refs. Now the arguments are rendered unmodifiable for
E
. - Case 3: The infamous
const_cast
. Can lead to undefined behaviour. - Case 4: Handle all combinations. Overloads become exponential with the number of parameters.
What std::forward does
- If
f
got an lvalue ref andE
needs an lvalue ref, then it obviously works out. Neither of them can take ownership of the object so neither of them will have it. - If
f
got an rvalue ref andE
needs an rvalue ref, it still checks out. Both can take ownership, both can have it. This mechanism also makes sure thatE
doesn’t receive it as an lvalue, which is what happens with an rvalue ref inside a function block (See rvalue refernces) - If
f
got an lvalue ref andE
needs an rvalue ref, it will be given an lvalue ref. This is because it cannot be given ownership of the object, sincef
doesn’t have it itself. - If
f
got an rvalue ref andE
needs an lvalue ref, do we even care? Let it have that, it was going to get lvalue ref without intervention anyways.
This combination is called as perfect forwarding.