It is said that std::forward() perfectly forwards a lvalue to lvalue, and rvalue to rvalue. But the code below seems to show a different conclusion?
when I run the code below
#include <iostream>
class A {
public:
int x;
A() {x = 0;}
explicit A(int x) : x(x) {}
A& operator= (A&& other) {
std::cout << " && =" << std::endl;
x = other.x;
}
A& operator= (const A& other) {
std::cout << " & =" << std::endl;
x = other.x;
}
};
int main() {
A p1(1), p2, p3;
p2 = p1;
p3 = std::forward<A>(p1);
return 0;
}
The result is:
& =
&& =
it seems that std::forward<A>(p1) forwards p1 as rvalue.
The source code of std::forward() is:
/**
* @brief Forward an lvalue.
* @return The parameter cast to the specified type.
*
* This function is used to implement "perfect forwarding".
*/
template<typename _Tp>
constexpr _Tp&&
forward(typename std::remove_reference<_Tp>::type& __t) noexcept
{ return static_cast<_Tp&&>(__t); }
/**
* @brief Forward an rvalue.
* @return The parameter cast to the specified type.
*
* This function is used to implement "perfect forwarding".
*/
template<typename _Tp>
constexpr _Tp&&
forward(typename std::remove_reference<_Tp>::type&& __t) noexcept
{
static_assert(!std::is_lvalue_reference<_Tp>::value, "template argument"
" substituting _Tp is an lvalue reference type");
return static_cast<_Tp&&>(__t);
}
gdb shows that when running p3 = std::forward<A>(p1);, it steps into the first function forward(typename std::remove_reference<_Tp>::type& __t) noexcept and returns a value of type A &&
(gdb) p __t
$2 = (std::remove_reference<A>::type &) @0x7fffffffd1cc: {
x = 1
}
(gdb) p static_cast<_Tp&&>(__t)
$3 = (A &&) @0x7fffffffd1cc: {
x = 1
}
I am totally confused. Would you please explain what happened when calling std::forward()? If std::forward<A>(p1) forwards p1 as rvalue, then what's the difference of std::forward and std::move?
The difference is that
std::forward<A&>(p1)returns an lvalue, andstd::movedoes not.You're misusing
std::forward. Passing a constant template type argument is pointless. They're useful when a function template has a forwarding reference argument whose type is deduced from function argument: Example: