How the library works

| Home | Libraries | People | FAQ | More

## 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:

- a) non-const rvalues (e.g.: temporaries), bind to `::boost::rv< TYPE >&`
- b) const rvalue and lvalues, bind to `const ::boost::rv< TYPE >&`
- c) non-const lvalues (e.g. non-const references) bind to `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;
    }