From ad50fba54fd2278762045ab3b03c32c0df8ac231 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sat, 1 Nov 2014 19:32:36 +0100 Subject: [PATCH] Added BOOST_MOVE_BASE utility --- doc/move.qbk | 29 +++++++++++++++++++++-------- example/doc_clone_ptr.cpp | 8 ++++---- include/boost/move/core.hpp | 16 +++++++++++++++- 3 files changed, 40 insertions(+), 13 deletions(-) diff --git a/doc/move.qbk b/doc/move.qbk index dbd7d11..0d47f52 100644 --- a/doc/move.qbk +++ b/doc/move.qbk @@ -532,19 +532,26 @@ care to achieve portable and efficient code when using the library with C++03 co [section:emulation_limitations_base Initializing base classes] When initializing base classes in move constructors, users must -cast the reference to a base class reference before moving it. Example: +cast the reference to a base class reference before moving it or just +use `BOOST_MOVE_BASE`. Example: [c++] - //Portable and efficient Derived(BOOST_RV_REF(Derived) x) // Move ctor - : Base(boost::move(static_cast(x))), - mem_(boost::move(x.mem_)) { } + : Base(boost::move(static_cast(x))) + //... +or + +[c++] + + Derived(BOOST_RV_REF(Derived) x) // Move ctor + : Base(BOOST_MOVE_BASE(Base, x)) + //... If casting is not performed the emulation will not move construct -the base class, because no conversion is available from `BOOST_RV_REF(Derived)` -to `BOOST_RV_REF(Base)`. Without the cast we might obtain a compilation +the base class, because no conversion is available from `BOOST_RV_REF(Derived)` to +`BOOST_RV_REF(Base)`. Without the cast or `BOOST_MOVE_BASE` we might obtain a compilation error (for non-copyable types) or a less-efficient move constructor (for copyable types): [c++] @@ -552,8 +559,8 @@ error (for non-copyable types) or a less-efficient move constructor (for copyabl //If Derived is copyable, then Base is copy-constructed. //If not, a compilation error is issued Derived(BOOST_RV_REF(Derived) x) // Move ctor - : Base(boost::move(x)), - mem_(boost::move(x.mem_)) { } + : Base(boost::move(x)) + //... [endsect] @@ -755,6 +762,12 @@ Many thanks to all boosters that have tested, reviewed and improved the library. [section:release_notes Release Notes] +[section:release_notes_boost_1_58_00 Boost 1.58 Release] + +* Added `BOOST_MOVE_BASE` utility. + +[endsect] + [section:release_notes_boost_1_57_00 Boost 1.57 Release] * Added `unique_ptr` smart pointer. Thanks to Howard Hinnant for his excellent unique_ptr emulation code and testsuite. diff --git a/example/doc_clone_ptr.cpp b/example/doc_clone_ptr.cpp index 8842e38..e0fa73c 100644 --- a/example/doc_clone_ptr.cpp +++ b/example/doc_clone_ptr.cpp @@ -64,19 +64,19 @@ class Derived : public Base // Compiler-generated copy constructor... Derived(BOOST_RV_REF(Derived) x) // Move ctor - : Base(boost::move(static_cast(x))), + : Base(BOOST_MOVE_BASE(Base, x)), mem_(boost::move(x.mem_)) { } Derived& operator=(BOOST_RV_REF(Derived) x) // Move assign { - Base::operator=(boost::move(static_cast(x))); - mem_ = boost::move(x.mem_); + Base::operator=(BOOST_MOVE_BASE(Base, x)); + mem_ = boost::move(x.mem_); return *this; } Derived& operator=(BOOST_COPY_ASSIGN_REF(Derived) x) // Copy assign { - Base::operator=(static_cast(x)); + Base::operator=(x); mem_ = x.mem_; return *this; } diff --git a/include/boost/move/core.hpp b/include/boost/move/core.hpp index ccdcc52..113a95d 100644 --- a/include/boost/move/core.hpp +++ b/include/boost/move/core.hpp @@ -198,6 +198,10 @@ boost::move_detail::move_return< RET_TYPE >(REF) // + #define BOOST_MOVE_BASE(BASE_TYPE, ARG) \ + ::boost::move((BASE_TYPE&)(ARG)) + // + ////////////////////////////////////////////////////////////////////////////// // // BOOST_MOVABLE_BUT_NOT_COPYABLE @@ -373,7 +377,6 @@ const TYPE & \ // - #endif //#if !defined(BOOST_MOVE_DOXYGEN_INVOKED) #if !defined(BOOST_MOVE_MSVC_AUTO_MOVE_RETURN_BUG) || defined(BOOST_MOVE_DOXYGEN_INVOKED) @@ -436,6 +439,17 @@ #endif //!defined(BOOST_MOVE_MSVC_AUTO_MOVE_RETURN_BUG) || defined(BOOST_MOVE_DOXYGEN_INVOKED) + //!This macro is used to achieve portable optimal move constructors. + //! + //!When implementing the move constructor, in C++03 compilers the moved-from argument must be + //!cast to the base type before calling `::boost::move()` due to rvalue reference limitations. + //! + //!In C++11 compilers the cast from a rvalue reference of a derived type to a rvalue reference of + //!a base type is implicit. + #define BOOST_MOVE_BASE(BASE_TYPE, ARG) \ + ::boost::move((BASE_TYPE&)(ARG)) + // + namespace boost { namespace move_detail {