#include <iostream>
using namespace std;
template< class T > struct my_remove_reference {typedef T type;};
template< class T > struct my_remove_reference<T&> {typedef T type;};
template< class T > struct my_remove_reference<T&&> {typedef T type;};
template <typename T>
typename my_remove_reference<T>::type&& my_move(T&& arg)
{
return static_cast<typename my_remove_reference<T>::type&&>(arg);
}
struct S
{
int *ptr = nullptr;
S() { cout << "S() default constructor, ptr = " << ptr << endl; }
S(int *p) : ptr(p) { cout << "S(int*) constructor, ptr = " << ptr << endl; }
};
class MoveTester
{
private:
int *m_ptr = nullptr;
public:
MoveTester() { cout << "MT() default constructor" << endl; }
MoveTester(const MoveTester &) = delete;
MoveTester(MoveTester&& src) : m_ptr(src.m_ptr) { src.m_ptr = nullptr; cout << "MT(MT&&) move constructor" << endl; }
MoveTester(int *ptr) : m_ptr(ptr) { cout << "MT(int*) constructor" << endl; }
MoveTester(S&& src) : m_ptr(src.ptr) { src.ptr = nullptr; cout << "MT(S&&) move constructor" << endl; }
MoveTester& operator=(const MoveTester &) = delete;
MoveTester& operator=(MoveTester&& rhs) { m_ptr = rhs.m_ptr; rhs.m_ptr = nullptr; cout << "MT::operator=(MT&&) move assignment" << endl; return *this; }
MoveTester& operator=(int *rhs) { m_ptr = rhs; cout << "MT::operator=(int*) copy assignment" << endl; return *this; }
MoveTester& operator=(S&& src) { m_ptr = src.ptr; src.ptr = nullptr; cout << "MT::operator=(S&&) move assignment" << endl; return *this; }
void display(const char *name) const { cout << name << ".m_ptr = " << m_ptr << endl; }
};
int* int_to_ptr(intptr_t value) { return reinterpret_cast<int*>(value); }
int main()
{
cout << "MoveTester mt1;" << endl;
MoveTester mt1;
mt1.display("mt1");
cout << endl;
cout << "MoveTester mt2 = int_to_ptr(12345);" << endl;
MoveTester mt2 = int_to_ptr(12345);
mt2.display("mt2");
cout << endl;
//MoveTester mt3 = mt2; // compiler error! Copy constructor is deleted
cout << "MoveTester mt3 = my_move(mt2);" << endl;
MoveTester mt3 = my_move(mt2);
mt2.display("mt2");
mt3.display("mt3");
cout << endl;
cout << "MoveTester mt4 = S();" << endl;
MoveTester mt4 = S();
mt4.display("mt4");
cout << endl;
cout << "MoveTester mt5 = S(int_to_ptr(67890));" << endl;
MoveTester mt5 = S(int_to_ptr(67890));
mt5.display("mt5");
cout << endl;
//mt1 = mt5; // compiler error! Copy assignment is deleted
cout << "mt1 = my_move(mt5);" << endl;
mt1 = my_move(mt5);
mt1.display("mt1");
mt5.display("mt5");
cout << endl;
cout << "mt1 = int_to_ptr(13579);" << endl;
mt1 = int_to_ptr(13579);
mt1.display("mt1");
cout << endl;
cout << "mt1 = S();" << endl;
mt1 = S();
mt1.display("mt1");
cout << endl;
cout << "mt1 = S(int_to_ptr(24680));" << endl;
mt1 = S(int_to_ptr(24680));
mt1.display("mt1");
return 0;
}