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 {