#include #include #include #include #define BOOST_MOVE_RETURNS_T 1 #define BOOST_MOVE_RETURNS_RV_T 2 //#define BOOST_MOVE_RETURN_OPTION BOOST_MOVE_RETURNS_T #define BOOST_MOVE_RETURN_OPTION BOOST_MOVE_RETURNS_RV_T //#define ALT1 namespace boost { #if ALT1 namespace detail{ template class rv { private: rv &operator=(const rv&); T& r_; public: explicit rv(T& r) : r_(r) {} T* operator->() {return &r_;} T& operator*() {return r_;} }; } //namespace detail template class is_movable { public: static const bool value = boost::is_convertible< T, detail::rv >::value; }; #if (BOOST_MOVE_RETURN_OPTION == BOOST_MOVE_RETURNS_T) template typename boost::enable_if, T >::type move(T& t) { return T(detail::rv(t)); } #elif (BOOST_MOVE_RETURN_OPTION == BOOST_MOVE_RETURNS_RV_T) template typename boost::enable_if, detail::rv >::type move(T& t) { return detail::rv(t); } #else #error "Bad option" #endif #else namespace detail{ template struct rv : T { private: rv(); ~rv(); rv(rv const&); void operator=(rv const&); }; } template typename boost::enable_if, detail::rv&>::type move(T& x) { return static_cast& >(x); } #endif } //namespace boost class movable { movable(movable &); movable & operator=(movable &); public: movable() {} #if ALT1 operator boost::detail::rv() { return boost::detail::rv(*this); } movable(boost::detail::rv) {} movable & operator=(boost::detail::rv) { return *this; } #else operator boost::detail::rv&() { return static_cast& >(*this); } movable(boost::detail::rv&) {} movable & operator=(boost::detail::rv&) { return *this; } #endif }; movable function(movable m) { return movable(boost::move(m)); } movable functionr(movable& m) { return movable(boost::move(m)); } #if ALT1 boost::detail::rv #else boost::detail::rv& #endif function2(movable m) { return boost::move(m); } #if ALT1 boost::detail::rv #else boost::detail::rv& #endif function2r(movable& m) { return boost::move(m); } #if ALT1 movable function3(boost::detail::rv m) #else movable function3(boost::detail::rv& m) #endif { return movable(m); } movable function3r(boost::detail::rv& m) { return movable(m); } #if ALT1 boost::detail::rv function4(boost::detail::rv m) #else boost::detail::rv& function4(boost::detail::rv& m) #endif { movable tmp(m); return boost::move(tmp); } #if ALT1 boost::detail::rv #else boost::detail::rv& #endif function4r(boost::detail::rv& m) { movable tmp(m); return boost::move(tmp); } #if 0 movable move_return_function () { movable m; return m; } #endif movable move_return_function2 () { return movable(); } movable move_return_function () { movable m; return movable(boost::move(m)); } int main() { #if ALT1 BOOST_STATIC_ASSERT((boost::is_movable::value == true)); #endif //this works both with Visual 7.1 and GCC 4.3 { movable m; movable m2(boost::move(m)); movable m3(function(movable(boost::move(m2)))); #if ALT1 //movable m4(function(boost::move(m3))); // do not compile #else movable m4(function(boost::move(m3))); m3=boost::move(m4); #endif //movable m5(function(m3)); // do not compile m2=boost::move(m3); m3=function(movable(boost::move(m2))); } { movable m; movable m2(boost::move(m)); #if ALT1 //movable m3(functionr(movable(boost::move(m2)))); // do not compile //movable m4(functionr(boost::move(m2))); // do not compile #else movable m3(functionr(movable(boost::move(m2)))); movable m4(functionr(boost::move(m3))); m2=boost::move(m4); #endif movable m5(functionr(m2)); m2=function(movable(boost::move(m5))); } { movable m; movable m2(boost::move(m)); movable m3(function2(movable(boost::move(m2)))); #if ALT1 //movable m4(function2(boost::move(m2))); // do not compile //movable m5(function2(m4)); // do not compile #else movable m4(function2(boost::move(m3))); //movable m5(function2(m4)); // do not compile m3=boost::move(m4); #endif m2=function2(movable(boost::move(m3))); } { movable m; movable m2(boost::move(m)); #if ALT1 //movable m3(function2r(movable(boost::move(m2)))); //movable m4(function2r(boost::move(m3))); // do not compile #else movable m3(function2r(movable(boost::move(m2)))); movable m4(function2r(boost::move(m3))); m2=boost::move(m4); #endif movable m4(function2r(m2)); m2=function2r(m4); } { movable m; movable m2(boost::move(m)); movable m3(function3(movable(boost::move(m2)))); movable m4(function3(boost::move(m3))); m2 =function3(boost::move(m4)); } { movable m; movable m2(boost::move(m)); movable m3(function4(movable(boost::move(m2)))); movable m4(function4(boost::move(m3))); m2 =function4(boost::move(m4)); } { movable m; movable m2(boost::move(m)); movable m3(move_return_function()); //movable m4(function4(boost::move(m3))); } return 0; }