C++ Passing Rvalue Reference to Functions That Takes Lvalue Reference
Asked Answered
S

1

6

When I was reading Effective Modern C++ by Scott Meyer about how std::forward function works, I got one question that I don't quite understand. Say if we have a function foo as follows:

template<typename T>
void foo(T&& fooParam)
{
    ...
    someFunc(std::forward<T>(fooParam));
}

In the book, Scott explains that the std::forward<T> could be implemented in the following way:

template<typename T>
T&& forward(typename remove_reference<T>::type& param)
{
    return static_cast<T&&>(param);
}

Suppose the argument passed to foo is an rvalue of type Widget. Then the std::forward function template would be initialized like this:

Widget&& forward(Widget& param)
{ return static_cast<Widget&&>(param); }

So my question is, when fooParam (which is of type Widget &&) passed to std::forward, how could the function that takes a parameter of type Widget& param match fooParam? I know fooParam itself is a lvalue. But its type is still rvalue reference (Widget &&) right? How could they match each other?

If a function which takes a parameter of lvalue reference type could be passed with a rvalue reference, then this function could do whatever it wants to even modify the passed in rvalue (like a temporary object). This doesn't make sense to me...

Schizothymia answered 19/12, 2016 at 5:40 Comment(1)
Its the caller side which should be concerned with implication of passing rvales. If rvalue is passed to a function then the caller of function should not use it further. However, the function receiving the rvalue just see the parameter as a normal value.Quincey
A
7
#include <iostream>
using std::cout;
using std::endl;

template<class T>
void my_print(T&& arg)
{
    my_print_impl(std::forward<T>(arg));
}
template<class T>
void my_print_impl(T& arg)
{
    cout << "lvalue reference" << endl;
}

template<class T>
void my_print_impl(T&& arg)
{
    cout << "rvalue reference" << endl;
}

int main()
{
    int i = 1;
    int & l_ref = i;
    int && r_ref = 1;
    my_print(l_ref);            //print lvalue reference
    my_print(r_ref);            //print lvalue reference
    my_print(std::move(l_ref)); //print rvalue reference
    my_print(1);                //print rvalue reference, 1 is a true rvalue
    system("pause");

    return 0;
}

As you say, r_ref is a lvalue reference, you should not make it to match as a rvalue reference.If you want pass parameter as rvalue reference,use std::move() or just pass rvalue to your function.

Arabela answered 19/12, 2016 at 8:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.