Little question about std::forward (reference collapsing)

Let's have a function called Y that overloads:

1
2
3
4
5
void Y(int& lvalue)
{ cout << "lvalue!" << endl; }

void Y(int&& rvalue)
{ cout << "rvalue!" << endl; }


Now, let's define a template function that acts like std::forward

1
2
3
4
5
template<class T>
void f(T&& x)
{
   Y( static_cast<T&&>(x) );   // Using static_cast<T&&>(x) like in std::forward
}



Now look at the main()

1
2
3
4
5
6
7
int main()
{
   int i = 10;

   f(i);       // lvalue >> T = int&
   f(10);      // rvalue >> T = int&&
}


As expected, the output is

1
2
lvalue!
rvalue!


Now come back to the template function f() and replace

static_cast<T&&>(x)

with this

static_cast<T>(x)

Let's see the output:

1
2
lvalue!
rvalue!


It's the same!

If we follow the Reference Collapsing rules, this actually makes sense

& + & = &
& + && = &
&& + & = &
&& + && = &&

----------------------------------------------------------------------

[1] When we call f(i) where T = int& this happens

(a) Our static_cast<T&&> becomes static_cast<int& &&>(x) which becomes static_cast<int&>(x)

(b) Our static_cast<T> becomes static_cast<int&>(x)


[2] When we call f(10) where T = int&& this happens

(a) Our static_cast<T&&> becomes static_cast<int &&>(x)

(b) Our static_cast<T> becomes static_cast<int>(x)



Question: since both the casts produce the same result, why was std::forward made to return a static_cast<T&&> conversion instead of static_cast<T>?

Last edited on
in the rvalue case, T deduces to int, not int&&. And then static_cast<T> creates a new object instead of forwarding: it makes an extra call to the copy constructor and then to the destructor of T, while static_cast<T&&> does not (try replacing int with a class with noisy special member functions)
Last edited on
Hi Cubbi, really thanks for the reply.

This argument has been discussed also here http://stackoverflow.com/questions/38251660/why-does-stdforward-return-static-castt-and-not-static-castt
Last edited on
Topic archived. No new replies allowed.