diff --git a/include/boost/move/core.hpp b/include/boost/move/core.hpp index b34740d..7b604e6 100644 --- a/include/boost/move/core.hpp +++ b/include/boost/move/core.hpp @@ -58,6 +58,7 @@ #include #define BOOST_MOVE_TO_RV_CAST(RV_TYPE, ARG) reinterpret_cast(ARG) + #define BOOST_MOVE_TO_LV_CAST(LV_TYPE, ARG) static_cast(ARG) //Move emulation rv breaks standard aliasing rules so add workarounds for some compilers #if defined(BOOST_GCC) && (BOOST_GCC >= 40400) && (BOOST_GCC < 40500) @@ -218,6 +219,10 @@ return x; } + template + BOOST_MOVE_FORCEINLINE T& unrv(::boost::rv &rv) BOOST_NOEXCEPT + { return BOOST_MOVE_TO_LV_CAST(T&, rv); } + } //namespace move_detail { } //namespace boost { @@ -229,6 +234,11 @@ ::boost::move((BASE_TYPE&)(ARG)) // + #define BOOST_MOVE_TO_LV(ARG) \ + ::boost::move_detail::unrv(ARG) + // + + ////////////////////////////////////////////////////////////////////////////// // // BOOST_MOVABLE_BUT_NOT_COPYABLE @@ -480,6 +490,17 @@ ::boost::move((BASE_TYPE&)(ARG)) // + //!This macro is used to achieve portable optimal move constructors. + //! + //!In C++03 mode, when accessing a member of type through a rvalue (implemented as a `rv &` type, where rv derives + //!from T) triggers a potential UB as the program never creates objects of type rv. This macro casts back `rv` to + //!`T&` so that access to member types are done through the original type. + //! + //!In C++11 compilers the cast from a rvalue reference of a derived type to a rvalue reference of + //!a base type is implicit, so it's a no-op. + #define BOOST_MOVE_TO_LV(ARG) ARG + // + namespace boost { namespace move_detail {