Tell me, what is the difference if I write T&& instead of std::move ? Here is the code:

 template<class T> void swap(T &a, T& b) { T t{ std::move(a) }; a = (T &&)(b); b = std::move(t); } 

In this case, the moving operator = will also be called (in any case, the effect is the same as from std::move ). Tell me, what is the difference from the alternative line below with std::move ?

  • Well, in a certain sense, this is the case - for example, in VC ++ 2015 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

1 answer 1

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 .