The std::move( ) is a function template which perform static casts. The std::move( ) unconditionally casts its argument (an L-value or R-value) to an R-value. This template function takes a reference to an object (using a universal reference parameter) and it returns a R-value reference to the same object.
Example,
int x = 9;
int && y = std::move(x); //Move taking L-value argument
//& returning R-value
int && z = std::move(4); //Move taking R-value argument
//& returning R-value
auto up1 = std::make_unique<int>();
std::unique_ptr<int> up2 = std::move(up1); //Move taking unique_ptr
//& returning R-value of data
std::move does not move anything but it simply cast its argument to an R-value. Please note that everything happens only in compile time.
The simplest implementation of move is as follows:
template <typename T>
typename std::remove_reference<T>::type&& move(T&& param)
{
using ReturnType = typename std::remove_reference<T>::type&&;
return static_cast<ReturnType>(param);
}
- The parameter type is T&& (universal reference), which means it accepts both L-value and R-value arguments.
- The “&&” part of the function’s return type means that std::move returns only an r-value reference.
- The function uses typename because, we are using a datatype inside a template class T (dependent type)
using ReturnType = typename std::remove_reference<T>::type&&;
The funciton uses remove_reference because this ensures that whatever is the calling type (L-value or R-value), the return type always correspond to R-value of basic type.
The std::remove_reference template class is part of C++ library, however, we can easily implement this in following way:
template <class T>
struct remove_reference { typedef T type; };
template <class T>
struct remove_reference<const T> { typedef const T type; };
template <class T>
struct remove_reference<T&> { typedef T type; };
template <class T>
struct remove_reference<const T&> { typedef const T type; };
template <class T>
struct remove_reference<T&&> { typedef T type; };
template <class T>
struct remove_reference<const T&&> { typedef const T type; };
Code Example: Demonstration of local implementation of move function
#include <iostream>
using namespace std;
template <typename T>
typename std::remove_reference<T>::type&& my_move(T&& param)
{
using ReturnType = typename std::remove_reference<T>::type&&;
return static_cast<ReturnType>(param);
}
void check(int& a) //L-value version
{
cout << "L-value check() called" << endl;
}
void check(int&& a) //R-value version
{
cout << "R-value check() called" << endl;
}
int main()
{
check(5); //Calls check(&&)
int w;
check(w); //Calls check(&)
check(my_move(w)); //Calls check(&&)
return 0;
}
The output is:
R-value check() called
L-value check() called
R-value check() called