confused about std::forward

Mar 9, 2021 at 3:36am
Hello everyone, I am learning about std::forward which is confusing.

The returned value type of std::forward keeps all the traits of its parameter.

If the real parameter is rvalue like 40 in the following code, after std::forward(40), the returned value type is rvalue reference, since it is anonymous, so it can be used as a rvalue (real parameter) passed to rvalue formal parameter v1 in f(int &&v1, int &v2). (Guess the logic up to now is correct)

While for a lvalue real parameter i, after std::forward, the returned type is lvalue reference. If use the logic in last paragraph, it is also an anonymous variable. Then it should also be regarded as a rvalue and should not be passed to lvalue reference v2 in f(int &&v1, int &v2). But it works.

What is wrong with the logic ?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
using namespace std;

template <typename F, typename T1, typename T2>
void flip(F f, T1 &&t1, T2 &&t2)
{
    f(std::forward<T1>(t1), std::forward<T2>(t2));
}
void f(int &&v1, int &v2)
{
    cout << v1 << " " << ++v2 << endl;
    // other things...
}
int main()
{
    int i = 42;
    flip(f, 40, i);
    cout << "i = " << i << endl;
    return 0;
}
Last edited on Mar 9, 2021 at 3:37am
Mar 9, 2021 at 4:09am
std::forward is simple in isolation -- it is equivalent to static_cast<T&&>(x) -- but the background information that's required is not.

since it is anonymous

Anonymity isn't the right criteria. Whether or not an expression e is an rvalue is better approximated by whether or not the expression &e compiles.

This is the best approximation I know of, and it isn't particularly good. To know for sure you'll need to become familiar with this reference page:
https://en.cppreference.com/w/cpp/language/value_category

Read this post as well:
https://www.cplusplus.com/forum/general/273175/#msg1178146

Last edited on Mar 9, 2021 at 4:14am
Mar 9, 2021 at 7:11am
Oh, my god, I understand a little bit now.

the lvalue and rvalue are the traits of the expression. the value categories includes lvalue, rvalue(prvalue, and xvalue)...

For the std::forward<int>(40), (with a rvalue ref as returned type), it is a xvalue expression, which is still rvalue category instead of a lvaue, and so it can be passed to rvalue ref formal parameter.

While the std::forward<int>(i), (with a lvalue ref as the returned type), is lvalue expression, so it can be binded to lvalue ref.

Guess it is like this...
Mar 9, 2021 at 7:10pm
Guess it is like this...

Yes, you got it.
Topic archived. No new replies allowed.