The std::move() function does two things -
1. it removes any references in its input, by making use of std::remove_reference
2. then casts it to a rvalue reference
Here is an implementation of move -
template<typename T>
//typename remove_reference<T>::type && //alternate way to specify return type in C++11
//remove_reference_t<T> && //return type in C++14
decltype(auto) move(T&& input) //least typing required if we use decltype in C++14
{
//return static_cast<typename remove_reference<T>::type &&>(input); //alternate return type in C++11
return static_cast<remove_reference_t<T> &&>(input);
};
Its return type is 'typename remove_reference<T>::type &&' which can be reduced to 'decltype(auto)' in C++14.
Here is an implementation of remove_reference -
template <typename T>
struct remove_reference { typedef T type; };
/*
* remove_reference is specialized for lvalue and rvalue references.
* This ensures that if an lvalue is passed to move, which is passed to remove_reference the return type is T i.e. type
* and the same if an rvalue is passed to move.
*/
template <typename T>
struct remove_reference<T&> { typedef T type; };
template <typename T>
struct remove_reference<T&&> { typedef T type; };
/*
* alias template
* so that we don't have to refer to ::type
*/
template <typename T>
using remove_reference_t = typename remove_reference<T>::type;
The comments describe the need for specializations of the remove_reference template.
This is how you can use the code to invoke move and verify that it works -
include <iostream>
class Small {
public:
int x;
Small () { x = 1; std::cout <<"Default Ctor"<<std::endl; }
Small (Small& i) { x = i.x; std::cout <<"Copy Ctor"<<std::endl; }
Small (Small&& i) { x = i.x; std::cout <<"Move Ctor"<<std::endl; }
};
int main()
{
Small obj1;
Small obj2(obj1);
Small obj3(my_move(obj1));
return 0;
}