I've read many articles saying that if there are no templates for the function, std::forward<>()
does not become a conditional cast anymore and just basically casts objects to RValue reference. Is that true?
Asked
Active
Viewed 165 times
0
-
i think you are confusing universal references with using `std::forward`. `std::forward` is always a cast, but a `T&&` parameter is different depending on `T` being a template parameter or not – 463035818_is_not_an_ai Jun 22 '21 at 19:06
-
What is a `conditional cast`? – SergeyA Jun 22 '21 at 19:11
-
If there's no template, you already know the value category and don't need help preserving it in a generic way, so `std::forward` won't help you. Of course you could still use it (it'll cast to whatever you tell it to), but for no benefit and the chance of using it incorrectly. – chris Jun 22 '21 at 19:11
1 Answers
2
std::forward
has a relatively simple implementation. It could look like this:
template <typename T>
T&& forward( std::remove_reference_t<T> & param )
{
return static_cast<T &&>(param);
}
As you can see, it's just a static_cast
, and not conditional. Given some type T
, it casts the result to T&&
.
If T
is a value type like std::string
or an r-value reference like std::string&&
, the result will always be an r-value reference.
If T
is an l-value reference like std::string&
, you are effecively performing static_cast<std::string& &&>(param)
and the rules of reference collapsing will cast it to a l-value std::string&
.
The reason that std::forward
may feel like a conditional cast is because it is intended to be used with forwarding references. Forwarding reference types are either value types or l-value references, depending on the calling context.

Drew Dormann
- 59,987
- 13
- 123
- 180
-
It is conditionally an identity cast or a cast to rvalue (with a possible implicit "cast" first) – Yakk - Adam Nevraumont Jun 22 '21 at 20:57
-
Wait, let me get this straight, if T is a non-reference (eg. std::string, int), it is a RValue? – Jun 22 '21 at 21:23
-
It is always cast to `T&&`. `std::string` will be cast to `std::string &&`. – Drew Dormann Jun 22 '21 at 21:57
-
@Joanadivertos It is a prvalue, a special case of rvalue. That happen when the type of an expression is `T`, whithout reference. For example, `1` is int. But `int x =0; x;` then the expression `x;` is `int&` – Guillaume Racicot Jun 23 '21 at 16:47