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 the documentation for an old version of Boost. Click here to view this page for the latest version.
PrevUpHomeNext

How the library works

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:

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;
}


PrevUpHomeNext