Семантика перемещения и вставка размещения - это две функции, привнесенные контейнерами C++11, которые могут оказать очень положительное влияние на ваши приложения C++. Повышаю. Контейнер реализует обе технологии как для компиляторов C++11, так и C++03.
Все контейнеры, предлагаемые Boost.Container, могут хранить только подвижные типы и фактические требования для value_type зависят от каждой операции с контейнером. Следуя требованиям C++11 даже для компиляторов C++03, многие операции теперь требуют подвижных или конструируемых по умолчанию типов вместо просто копируемых конструируемых типов.
Сами контейнеры также являются подвижными, с гарантией отсутствия броска, если операции с выделением или предикатом (если присутствуют) не являются броском. Это позволяет выполнять высокопроизводительные операции при передаче данных между векторами. Давайте посмотрим пример:
#include <boost/container/vector.hpp>
#include <boost/move/utility_core.hpp>
#include <cassert>
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;
   
   vector<non_copyable> v;
   non_copyable nc;
   v.push_back(boost::move(nc));
   assert(v.size() == 1);
   
   v.reserve(100);
   assert(v.capacity() >= 100);
   
   v.resize(200);
   assert(v.size() == 200);
   
   vector<non_copyable> v_other(boost::move(v));
   assert(v_other.size() == 200);
   assert(v.empty());
   return 0;
}
Все контейнеры, предлагаемые Boost.Container, реализуют вставку размещения, что означает, что объекты могут быть встроены непосредственно в контейнер из аргументов пользователя без создания какого-либо временного объекта. Для компиляторов без вариадных шаблонов поддержка размещения вставки эмулируется до конечного (10) числа аргументов.
Дорогие для перемещения типы являются идеальными кандидатами для размещения функций и в случае контейнеров узлов ( список , набор , ...) место позволяет хранить неподвижные и некопируемые типы в контейнерах! Давайте посмотрим пример:
#include <boost/container/list.hpp>
#include <cassert>
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;
   
   list<non_copy_movable> l;
   non_copy_movable ncm;
   
   l.emplace(l.begin(), 0);
   assert(l.size() == 1);
   
   l.emplace(l.begin());
   assert(l.size() == 2);
   return 0;
}
Неполные типы позволяют  стирать типы  и рекурсивные типы данных, а программисты C и C++ годами используют его для построения сложных структур данных, таких как структуры деревьев, где узел может иметь произвольное количество детей.
Как насчет стандартных контейнеров? Контейнеры неполных типов уже давно обсуждаются, как объясняется в замечательной статье Мэтта Остерна (Стандартный библиотекарь: Контейнеры неполных типов):
“Unlike most of my columns, this one is about something you
        can't do with the C++ Standard library: put incomplete types in one of the
        standard containers. This column explains why you might want to do this,
        why the standardization committee banned it even though they knew it was
        useful, and what you might be able to do to get around the restriction.”
      
“In 1997, shortly before the C++ Standard was completed,
        the standardization committee received a query: Is it possible to create
        standard containers with incomplete types? It took a while for the committee
        to understand the question. What would such a thing even mean, and why on
        earth would you ever want to do it? The committee eventually worked it out
        and came up with an answer to the question. (Just so you don't have to skip
        ahead to the end, the answer is "no.") But the question is much
        more interesting than the answer: it points to a useful, and insufficiently
        discussed, programming technique. The standard library doesn't directly support
        that technique, but the two can be made to coexist.”
      
“In a future revision of C++, it might make sense to relax
        the restriction on instantiating standard library templates with incomplete
        types. Clearly, the general prohibition should stay in place - instantiating
        templates with incomplete types is a delicate business, and there are too
        many classes in the standard library where it would make no sense. But perhaps
        it should be relaxed on a case-by-case basis, and vector
        looks like a good candidate for such special-case treatment: it's the one
        standard container class where there are good reasons to instantiate it with
        an incomplete type and where Standard Library implementors want to make it
        work. As of today, in fact, implementors would have to go out of their way
        to prohibit it!”
      
Стандарт C++11 также осторожно относится к неполным типам и STL: “17.6.4.8 Другие функции (...) 2. последствия не определены в следующих случаях: (...) В частности, если неполный тип (3.9) используется в качестве аргумента шаблона при инстанцировании компонента шаблона, если специально не разрешено для этого компонента ”.
К счастью, все контейнеры Boost.Container, за исключением static_vector и basic_string, предназначены для поддержки неполных типов. static_vector является специальным, поскольку он статически выделяет память для value_type и для этого требуются полные типы и basic_string реализует оптимизацию малых струн, которая также требует полных типов.
Boost.Container containers supporting incomplete
        types also support instantiating iterators to those incomplete elements.
      
Для определения рекурсивных контейнеров можно использовать большинство контейнеров Boost.Container:
#include <boost/container/vector.hpp>
#include <boost/container/stable_vector.hpp>
#include <boost/container/deque.hpp>
#include <boost/container/list.hpp>
#include <boost/container/map.hpp>
#include <boost/container/string.hpp>
using namespace boost::container;
struct data
{
   int               i_;
   
   vector<data>      v_;
   vector<data>::iterator vi_;
   
   stable_vector<data> sv_;
   stable_vector<data>::iterator svi_;
   
   deque<data> d_;
   deque<data>::iterator di_;
   
   list<data>        l_;
   list<data>::iterator li_;
   
   map<data, data>   m_;
   map<data, data>::iterator   mi_;
   friend bool operator <(const data &l, const data &r)
   { return l.i_ < r.i_; }
};
struct tree_node
{
   string name;
   string value;
   
   list<tree_node>            children_;
   list<tree_node>::iterator  selected_child_;
};
int main()
{
   
   stable_vector<data> sv;
   sv.resize(100);
   
   
   tree_node root;
   root.name  = "root";
   root.value = "root_value";
   root.children_.resize(7);
   root.selected_child_ = root.children_.begin();
   return 0;
}
Контейнеры неполных типов полезны для разрушения зависимостей файла заголовка и улучшения типов компиляции. С Бустом. Контейнер, вы можете написать файл заголовка, определяющий класс с контейнерами неполных типов в качестве членов данных, если вы тщательно поместите все детали реализации, которые требуют знания размера value_type в файл реализации:
В этом файле заголовка мы определяем класс (MyClassHolder), который содержит вектор MyClass), который объявлен только вперед.
#include <boost/container/vector.hpp>
class MyClass;
class MyClassHolder
{
   public:
   void AddNewObject(const MyClass &o);
   const MyClass & GetLastObject() const;
   private:
   ::boost::container::vector<MyClass> vector_;
};
Затем мы можем определить MyClass в собственном файле заголовка.
class MyClass
{
   private:
   int value_;
   public:
   MyClass(int val = 0) : value_(val){}
   friend bool operator==(const MyClass &l, const MyClass &r)
   {  return l.value_ == r.value_;  }
   
};
          And include it only in the implementation file of MyClassHolder
#include "MyClassHolder.h"
#include "MyClass.h"
void MyClassHolder::AddNewObject(const MyClass &o)
{  vector_.push_back(o);  }
const MyClass & MyClassHolder::GetLastObject() const
{  return vector_.back();  }
Наконец, мы можем просто собрать, связать и запустить!
#include "MyClassHolder.h"
#include "MyClass.h"
#include <cassert>
int main()
{
   MyClass mc(7);
   MyClassHolder myclassholder;
   myclassholder.AddNewObject(mc);
   return myclassholder.GetLastObject() == mc ? 0 : 1;
}
В статье N2913, озаглавленной SCARY Iterator Assignment and Initialization, предложено требование о том, что типы итераторов стандартного контейнера не зависят от какого-либо аргумента типа, кроме типа контейнера value_type, difference_type, pointer и const_pointer. В частности, согласно предложению, типы итераторов стандартного контейнера не должны зависеть от типов контейнера key_compare, hasher, key_equal или allocator.
Этот документ продемонстрировал, что операции SCARY имеют решающее значение для эффективного внедрения общих шаблонов проектирования с использованием компонентов STL. Он показал, что реализации, поддерживающие операции SCARY, уменьшают раздувание объектного кода, устраняя избыточные специализации итераторов и шаблонов алгоритмов.
Boost.Container containers implement SCARY
        iterators so the iterator type of a container is only dependent on the allocator_traits<allocator_type>::pointer type (the pointer type of the
        value_type to be inserted
        in the container). Reference types and all other typedefs are deduced from
        the pointer type using the C++11 pointer_traits
        utility. This leads to lower code bloat in algorithms and classes templated
        on iterators.