#include #include #include #include #include #include #include enum ConstructionType { Copied, Moved, Other }; class conversion_source { public: conversion_source(){} operator int() const { return 0; } }; class conversion_target { ConstructionType c_type_; public: conversion_target(conversion_source) { c_type_ = Other; } conversion_target() { c_type_ = Other; } conversion_target(const conversion_target &) { c_type_ = Copied; } ConstructionType construction_type() const { return c_type_; } }; class conversion_target_copymovable { ConstructionType c_type_; BOOST_COPYABLE_AND_MOVABLE(conversion_target_copymovable) public: conversion_target_copymovable() { c_type_ = Other; } conversion_target_copymovable(conversion_source) { c_type_ = Other; } conversion_target_copymovable(const conversion_target_copymovable &) { c_type_ = Copied; } conversion_target_copymovable(BOOST_RV_REF(conversion_target_copymovable) ) { c_type_ = Moved; } conversion_target_copymovable &operator=(BOOST_RV_REF(conversion_target_copymovable) ) { c_type_ = Moved; return *this; } conversion_target_copymovable &operator=(BOOST_COPY_ASSIGN_REF(conversion_target_copymovable) ) { c_type_ = Copied; return *this; } ConstructionType construction_type() const { return c_type_; } }; class conversion_target_movable { ConstructionType c_type_; BOOST_MOVABLE_BUT_NOT_COPYABLE(conversion_target_movable) public: conversion_target_movable() { c_type_ = Other; } conversion_target_movable(conversion_source) { c_type_ = Other; } conversion_target_movable(BOOST_RV_REF(conversion_target_movable) ) { c_type_ = Moved; } conversion_target_movable &operator=(BOOST_RV_REF(conversion_target_movable) ) { c_type_ = Moved; return *this; } ConstructionType construction_type() const { return c_type_; } }; struct not_a_type; #if defined(BOOST_NO_RVALUE_REFERENCES) #define BOOST_MOVE_CATCH_CONST(U) \ typename ::boost::mpl::if_< ::boost::is_class, BOOST_CATCH_CONST_RLVALUE(U), const U &>::type #define BOOST_MOVE_CATCH_RVALUE(U)\ typename ::boost::mpl::if_< ::boost::is_class, BOOST_RV_REF(T), not_a_type>::type #else #define BOOST_MOVE_CATCH_CONST(U) BOOST_CATCH_CONST_RLVALUE(U) #define BOOST_MOVE_CATCH_RVALUE(U) BOOST_RV_REF(U) #endif template class container { typename ::boost::aligned_storage::value>::type storage_; public: void push_back(BOOST_MOVE_CATCH_CONST(T) x) { return priv_push_back(static_cast(x)); } void push_back(BOOST_MOVE_CATCH_RVALUE(T) x) { return priv_push_back(::boost::move(x)); } //Tricks for C++03 #if defined(BOOST_NO_RVALUE_REFERENCES) void push_back(T &x) { priv_push_back(const_cast(x)); } template typename ::boost::enable_if_c < ::boost::is_class::value && ::boost::is_same::value && !::boost::has_move_emulation_enabled::value >::type push_back(const U &u) { return priv_push_back(u); } template typename ::boost::enable_if_c < ::boost::is_class::value && !::boost::is_same::value && !::boost::move_detail::is_rv::value >::type push_back(const U &u) { T t(u); priv_push_back(::boost::move(t)); } #endif ConstructionType construction_type() const { return construction_type_impl(typename ::boost::is_class::type()); } ConstructionType construction_type_impl(::boost::true_type) const { return reinterpret_cast(storage_).construction_type(); } ConstructionType construction_type_impl(::boost::false_type) const { return Copied; } private: template void priv_push_back(BOOST_FWD_REF(U) x) { new (&storage_) T(::boost::forward(x)); } }; int main() { conversion_target_movable a; conversion_target_movable b(::boost::move(a)); { container c; { conversion_target x; c.push_back(x); assert(c.construction_type() == Copied); } { const conversion_target x; c.push_back(x); assert(c.construction_type() == Copied); } { c.push_back(conversion_target()); assert(c.construction_type() == Copied); } { conversion_source x; c.push_back(x); assert(c.construction_type() == Copied); } { const conversion_source x; c.push_back(x); assert(c.construction_type() == Copied); } { c.push_back(conversion_source()); assert(c.construction_type() == Copied); } } { container c; { conversion_target_copymovable x; c.push_back(x); assert(c.construction_type() == Copied); } { const conversion_target_copymovable x; c.push_back(x); assert(c.construction_type() == Copied); } { c.push_back(conversion_target_copymovable()); assert(c.construction_type() == Moved); } { conversion_source x; c.push_back(x); assert(c.construction_type() == Moved); } { const conversion_source x; c.push_back(x); assert(c.construction_type() == Moved); } { c.push_back(conversion_source()); assert(c.construction_type() == Moved); } } { container c; //This should not compile {/* conversion_target_movable x; c.push_back(x); assert(c.construction_type() == Copied); } { const conversion_target_movable x; c.push_back(x); assert(c.construction_type() == Copied); */} { c.push_back(conversion_target_movable()); assert(c.construction_type() == Moved); } { conversion_source x; c.push_back(x); assert(c.construction_type() == Moved); } { const conversion_source x; c.push_back(x); assert(c.construction_type() == Moved); } { c.push_back(conversion_source()); assert(c.construction_type() == Moved); } } { container c; { int x; c.push_back(x); assert(c.construction_type() == Copied); } { const int x = 0; c.push_back(x); assert(c.construction_type() == Copied); } { c.push_back(int(0)); assert(c.construction_type() == Copied); } { conversion_source x; c.push_back(x); assert(c.construction_type() == Copied); } { const conversion_source x; c.push_back(x); assert(c.construction_type() == Copied); } { c.push_back(conversion_source()); assert(c.construction_type() == Copied); } } return 0; }