//rvalue classes and move function
template <class T>
struct r_ref {
T& ref;
r_ref(T& rhs) :ref(rhs) {}
r_ref(const r_ref& rhs) :ref(rhs.ref) {}
};
template <class T>
struct r_val : r_ref<T> {
mutable T val;
r_val(T& rhs) :r_ref<T>(val), val(rhs) {}
r_val(const r_ref<T>& rhs) :r_ref<T>(val), val(rhs) {}
};
template <class T>
r_ref<T> move(T& rhs) {return r_ref<T>(rhs);}
//demo classes
#include <iostream>
#include <string>
class demo {
public:
std::string data;
demo() : data("LONG STRING SO NO CHEATS") {std::cout<<"default construct ";}
demo(const demo& rhs) : data(rhs.data.begin(),rhs.data.end()) {std::cout<<"copy construct ";}
demo(const r_ref<demo>& rhs) : data("MOVED FROM NO CHEATS") {data.swap(rhs.ref.data); std::cout<<"move construct ";}
demo& operator=(const demo& rhs) {data.assign(rhs.data.begin(),rhs.data.end()); std::cout<<"copy assignment "; return *this;}
demo& operator=(const r_ref<demo>& rhs) {data.swap(rhs.ref.data); std::cout<<"move assignment "; return *this;}
~demo() {std::cout<<"destruct ";}
void prove() const {std::cout<<(void*)data.c_str()<<' '<<data.c_str();}
};
r_val<demo> function(demo rhs) {
std::cout << "\nwant move assignment: ";
demo obj(move(rhs));
std::cout << "\nwant VAR1: ";
obj.prove();
std::cout << "\nwant move construct, destruct, destruct, move construct, destruct:\n\t";
return move(obj);
}
//test suite
int main() {
std::cout << "\nwant default construct: "; demo a;
std::cout << "\nwant VAR1: "; a.prove();
std::cout << "\nwant move construct: "; demo b = function(move(a));
std::cout << "\nwant VAR2: "; a.prove();
std::cout << "\nwant VAR1: "; b.prove();
std::cout << "\nwant copy assignment: "; a = b;
std::cout << "\nwant VAR3: "; a.prove();
std::cout << "\nwant VAR1: "; b.prove();
std::cout << "\nwant move assign: "; a = move(b);
std::cout << "\nwant VAR1: "; a.prove();
std::cout << "\nwant VAR3: "; b.prove();
std::cout << "\nwant 2x destruct: ";
}