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 2013. The current version is 1.90.0.
Like any emulation effort, the library has some limitations users should take in care to achieve portable and efficient code when using the library with C++03 conformant compilers:
When initializing base classes in move constructors, users must cast the reference to a base class reference before moving it. Example:
//Portable and efficient Derived(BOOST_RV_REF(Derived) x) // Move ctor : Base(boost::move(static_cast<Base&>(x))), mem_(boost::move(x.mem_)) { }
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 error (for non-copyable types)
or a less-efficient move constructor (for copyable types):
//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_)) { }
The emulation can't deal with C++0x reference collapsing rules that allow perfect forwarding:
//C++0x template<class T> void forward_function(T &&t) { inner_function(std::forward<T>(t); } //Wrong C++03 emulation template<class T> void forward_function(BOOST_RV_REF<T> t) { inner_function(boost::forward<T>(t); }
In C++03 emulation BOOST_RV_REF doesn't catch any const rlvalues. For more details on forwarding see Constructor Forwarding chapter.
The first rvalue reference proposal allowed the binding of rvalue references to lvalues:
func(Type &&t); //.... Type t; //Allowed func(t)
Later, as explained in Fixing a Safety Problem with Rvalue References this behaviour was considered dangerous and eliminated this binding so that rvalue references adhere to the principle of type-safe overloading: Every function must be type-safe in isolation, without regard to how it has been overloaded
Boost.Move can't emulate this type-safe overloading principle for C++03 compilers:
//Allowed by move emulation movable m; BOOST_RV_REF(movable) r = m;
The macro BOOST_COPYABLE_AND_MOVABLE
needs to define a copy constructor for copyable_and_movable
taking a non-const parameter in C++03 compilers:
//Generated by BOOST_COPYABLE_AND_MOVABLE copyable_and_movable &operator=(copyable_and_movable&){/**/}
Since the non-const overload of the copy constructor is generated, compiler-generated
assignment operators for classes containing copyable_and_movable
will get the non-const copy constructor overload, which will surely surprise
users:
class holder { copyable_and_movable c; }; void func(const holder& h) { holder copy_h(h); //<--- ERROR: can't convert 'const holder&' to 'holder&' //Compiler-generated copy constructor is non-const: // holder& operator(holder &) //!!! }
This limitation forces the user to define a const version of the copy assignment, in all classes holding copyable and movable classes which might annoying in some cases.
An alternative is to implement a single operator
=() for copyable and movable classes
using
"pass by value" semantics:
T& operator=(T x) // x is a copy of the source; hard work already done { swap(*this, x); // trade our resources for x's return *this; // our (old) resources get destroyed with x }
However, "pass by value" is not optimal for classes (like containers, strings, etc.) that reuse resources (like previously allocated memory) when x is assigned from a lvalue.