#include using namespace std; struct SType { int x = 123; template inline SType &operator=(Tp_ &&rhs); }; template struct Assign; template struct Assign { static SType &assign(SType *lhs, Tp_ &&tp); }; template struct Assign { static SType &assign(SType *lhs, Tp_ const &tp); }; template <> struct Assign { static SType &assign(SType *lhs, SType const &tp); }; template inline SType &Assign::assign(SType *lhs, Tp_ &&tp) { cout << "move assignment of some rhs type\n"; lhs->x = tp; return *lhs; } template inline SType &Assign::assign(SType *lhs, Tp_ const &tp) { cout << "std assign of some rhs type\n"; lhs->x = tp; return *lhs; } inline SType &Assign::assign(SType *lhs, SType const &tp) { cout << "Assignment of Stype to Stype through copy-assignment\n"; lhs->x = tp.x; return *lhs; } template inline SType &SType::operator=(Tp_ &&rhs) { return Assign< // the is_rvalue_reference is needed to set the first template // param. true, resuling in move assignment, using the first // overload: // Assign::assign(SType *lhs, Tp_ &&tp) std::is_rvalue_reference::value, // the rm ref. is needed to distinguish // Assign::assign(SType *lhs, Tp_ const &tp) and // Assign::assign(SType *lhs, SType const &tp) typename std::remove_reference::type >::assign(this, std::forward(rhs)); } // ==================================================================== double fact() { return 3.14; } int main() { SType st; int x = 10; st = st; cout << st.x << '\n'; st = x; cout << st.x << '\n'; st = int(5); cout << st.x << '\n'; st = fact(); cout << st.x << '\n'; }