...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
Move semantics and placement insertion are two features brought by C++11 containers that can have a very positive impact in your C++ applications. Boost.Container implements both techniques both for C++11 and C++03 compilers.
All containers offered by Boost.Container
can store movable-only types and actual requirements for value_type
depend on each container operations. Following C++11 requirements even for
C++03 compilers, many operations now require movable or default constructible
types instead of just copy constructible types.
Containers themselves are also movable, with no-throw guarantee if allocator or predicate (if present) copy operations are no-throw. This allows high performance operations when transferring data between vectors. Let's see an example:
#include <boost/container/vector.hpp> #include <boost/move/move.hpp> #include <cassert> //Non-copyable class class non_copyable { BOOST_MOVABLE_BUT_NOT_COPYABLE(non_copyable) public: non_copyable(){} non_copyable(BOOST_RV_REF(non_copyable)) {} non_copyable& operator=(BOOST_RV_REF(non_copyable)) { return *this; } }; int main () { using namespace boost::container; //Store non-copyable objects in a vector vector<non_copyable> v; non_copyable nc; v.push_back(boost::move(nc)); assert(v.size() == 1); //Reserve no longer needs copy-constructible v.reserve(100); assert(v.capacity() >= 100); //This resize overload only needs movable and default constructible v.resize(200); assert(v.size() == 200); //Containers are also movable vector<non_copyable> v_other(boost::move(v)); assert(v_other.size() == 200); assert(v.empty()); return 0; }
All containers offered by Boost.Container implement placement insertion, which means that objects can be built directly into the container from user arguments without creating any temporary object. For compilers without variadic templates support placement insertion is emulated up to a finite (10) number of arguments.
Expensive to move types are perfect candidates emplace functions and in case
of node containers (list
,
set
, ...) emplace allows
storing non-movable and non-copyable types in containers! Let's see an example:
#include <boost/container/list.hpp> #include <cassert> //Non-copyable and non-movable class class non_copy_movable { non_copy_movable(const non_copy_movable &); non_copy_movable& operator=(const non_copy_movable &); public: non_copy_movable(int = 0) {} }; int main () { using namespace boost::container; //Store non-copyable and non-movable objects in a list list<non_copy_movable> l; non_copy_movable ncm; //A new element will be built calling non_copy_movable(int) contructor l.emplace(l.begin(), 0); assert(l.size() == 1); //A new element will be built calling the default constructor l.emplace(l.begin()); assert(l.size() == 2); return 0; }