According to the Language Standard, the std::move(T&& t) template function returns :
static_cast<remove_reference_t<T>&&>(t)
Those. while the template function has T& in the signature - you will not see the difference. But if the function takes a T&& argument, the result will be different:
#include <iostream> #include <utility> template<class T> void fr(T& a) { std::cout << "& " << std::is_same_v<decltype(std::move(a)), decltype((T&&)(a))> << "\n"; } template<class T> void frr(T&& a) { std::cout << "&& " << std::is_same_v<decltype(std::move(a)), decltype((T&&)(a))> << "\n"; } int main() { int i = 42; fr(i); frr(i); }
Conclusion :
& 1 && 0
This happens because, for frr type T is displayed as int& , and a record of the form T&& turns into int&&& , which in turn gives int& again, and not int&& .
My code uses constructs from c ++ 17, so if you want it to be going to c ++ 11 you need to replace std::is_same_v<T1, T2> with std::is_same<T1, T2>::value .
template<class _Ty> inline constexpr typename remove_reference<_Ty>::type&& move(_Ty&& _Arg) _NOEXCEPT { // forward _Arg as movable return (static_cast<typename remove_reference<_Ty>::type&&>(_Arg)); }template<class _Ty> inline constexpr typename remove_reference<_Ty>::type&& move(_Ty&& _Arg) _NOEXCEPT { // forward _Arg as movable return (static_cast<typename remove_reference<_Ty>::type&&>(_Arg)); }- Harry