C++14 - Understanding and implementing std::move()

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;

}