Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::forward vs std::move while binding lvalue to rvalue reference

Tags:

c++

c++11

is there a difference between move and forward here:

void test(int && val)
{
    val=4;
}

void main()
{  
    int nb;
    test(std::forward<int>(nb));
    test(std::move(nb));
    std::cin.ignore();    
}
like image 771
Guillaume Paris Avatar asked Jul 28 '11 19:07

Guillaume Paris


1 Answers

In your specific case, no, there isn't any difference.

Detailed answer:

Under the hood, std::move(t) does static_cast<typename std::remove_reference<T>::type&&>(t), where T is type of t (see §20.2.3/6). In your case, it resolves to static_cast<int&&>(nb).

forward is a little bit tricky, because it is tailored for use in templates (to allow perfect forwarding) and not as a tool to cast lvalue to rvalue reference.

Standard library provides two overloads (one for lvalue references and the second for rvalue ones, see §20.2.3/2):

template <class T> T&& forward(typename remove_reference<T>::type& t) noexcept;
template <class T> T&& forward(typename remove_reference<T>::type&& t) noexcept;

Substituting int, we get:

int&& forward(int& t) noexcept;
int&& forward(int&& t) noexcept;

And since nb is lvalue, the first version is chosen. According to standard draft, the only effect of forward is static_cast<T&&>(t). With T being int, we get static_cast<int&&>(nb), i.e. - we get two exactly same casts.

Now, if you want to cast lvalue to rvalue (to allow moving), please use only std::move, which is the idiomatic way to do this conversion. std::forward is not intended to be used this way.

like image 150
Vitus Avatar answered Nov 12 '22 06:11

Vitus