Boost
C++ Libraries
...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
This is an older version of Boost and was released in 2017. The current version is 1.89.0.
Boost.Move is based on macros that are expanded to true rvalue references in C++0x compilers and emulated rvalue reference classes and conversion operators in C++03 compilers.
In C++03 compilers Boost.Move defines a class
named ::boost::rv:
template <class T> class rv : public T { rv(); ~rv(); rv(rv const&); void operator=(rv const&); };
which is convertible to the movable base class (usual C++ derived to base conversion).
When users mark their classes as BOOST_MOVABLE_BUT_NOT_COPYABLE
or BOOST_COPYABLE_AND_MOVABLE,
these macros define conversion operators to references to ::boost::rv:
#define BOOST_MOVABLE_BUT_NOT_COPYABLE(TYPE)\ public:\ operator ::boost::rv<TYPE>&() \ { return *static_cast< ::boost::rv<TYPE>* >(this); }\ operator const ::boost::rv<TYPE>&() const \ { return static_cast<const ::boost::rv<TYPE>* >(this); }\ private:\ //More stuff...
BOOST_MOVABLE_BUT_NOT_COPYABLE
also declares a private copy constructor and assignment. BOOST_COPYABLE_AND_MOVABLE
defines a non-const copy constructor TYPE
&operator=(TYPE&)
that forwards to a const version:
#define BOOST_COPYABLE_AND_MOVABLE(TYPE)\ public:\ TYPE& operator=(TYPE &t)\ { this->operator=(static_cast<const ::boost::rv<TYPE> &>(const_cast<const TYPE &>(t))); return *this;}\ //More stuff...
In C++0x compilers BOOST_COPYABLE_AND_MOVABLE
expands to nothing and BOOST_MOVABLE_BUT_NOT_COPYABLE
declares copy constructor and assigment operator private.
When users define the BOOST_RV_REF
overload of a copy constructor/assignment, in C++0x compilers it is expanded
to a rvalue reference (T&&)
overload and in C++03 compilers it is expanded to a ::boost::rv<T>
& overload:
#define BOOST_RV_REF(TYPE) ::boost::rv< TYPE >& \
When users define the BOOST_COPY_ASSIGN_REF
overload, it is expanded to a usual copy assignment (const
T &)
overload in C++0x compilers and to a const
::boost::rv &
overload in C++03 compilers:
#define BOOST_COPY_ASSIGN_REF(TYPE) const ::boost::rv< TYPE >&
As seen, in Boost.Move generates efficient and clean code for C++0x move semantics, without modifying any resolution overload. For C++03 compilers when overload resolution is performed these are the bindings:
::boost::rv< TYPE >&
const
::boost::rv< TYPE >&
TYPE&
The library does not define the equivalent of BOOST_COPY_ASSIGN_REF
for copy construction (say, BOOST_COPY_CTOR_REF)
because nearly all modern compilers implement RVO and this is much more efficient
than any move emulation. move
just casts TYPE &
into ::boost::rv<TYPE> &.
Here's an example that demostrates how different rlvalue objects bind to ::boost::rv references in the presence of three overloads
and the conversion operators in C++03 compilers:
#include <boost/move/core.hpp> #include <iostream> class sink_tester { public: //conversions provided by BOOST_COPYABLE_AND_MOVABLE operator ::boost::rv<sink_tester>&() { return *static_cast< ::boost::rv<sink_tester>* >(this); } operator const ::boost::rv<sink_tester>&() const { return *static_cast<const ::boost::rv<sink_tester>* >(this); } }; //Functions returning different r/lvalue types sink_tester rvalue() { return sink_tester(); } const sink_tester const_rvalue() { return sink_tester(); } sink_tester & lvalue() { static sink_tester lv; return lv; } const sink_tester & const_lvalue() { static const sink_tester clv = sink_tester(); return clv; } //BOOST_RV_REF overload void sink(::boost::rv<sink_tester> &) { std::cout << "non-const rvalue catched" << std::endl; } //BOOST_COPY_ASSIGN_REF overload void sink(const ::boost::rv<sink_tester> &){ std::cout << "const (r-l)value catched" << std::endl; } //Overload provided by BOOST_COPYABLE_AND_MOVABLE void sink(sink_tester &) { std::cout << "non-const lvalue catched" << std::endl; } int main() { sink(const_rvalue()); //"const (r-l)value catched" sink(const_lvalue()); //"const (r-l)value catched" sink(lvalue()); //"non-const lvalue catched" sink(rvalue()); //"non-const rvalue catched" return 0; }