Как уже упоминалось,Boost.Intrusiveконтейнеры являютсянекопируемыми и неназначаемыми, потому что интрузивные контейнеры вообще не выделяют память. Для реализации копи-конструктора или оператора присваивания пользователь должен клонировать один за другим все элементы контейнера и вставлять их в другой навязчивый контейнер. Однако клонирование вручную обычно более неэффективно, чем функция клонирования члена, и специализированная функция клонирования может предложить больше гарантий, чем ручное клонирование (например, лучшие гарантии безопасности исключения).
Для облегчения реализации конструкторов копий и операторов присвоения классов, содержащихBoost.Intrusiveконтейнеры, всеBoost.Intrusiveконтейнеры предлагают специальную функцию клонирования под названиемClone_from
.
Помимо клонируемого контейнераклон_ из
принимает в качестве аргументов два функциональных объекта. Например, рассмотримклон_ из
функции членасписка
:
template <class Cloner, class Disposer>
void clone_from(const list &src, Cloner cloner, Disposer disposer);
Эта функция сделает*это
клонsrc
. Давайте объясним аргументы:
- Первым параметром является список подлежащих клонированию.
- Второй параметр — функциональный объект, который будет клонировать
значение_тип
объекты и возвращать указатель на клон. Он должен выполнять следующую функцию:указательоператор()constзначение_тип&]
.
- Второй параметр — объект функции, который будет располагать
значением_типа
объектов. Сначала он используется для опорожнения контейнера перед клонированием и утилизации элементов, если заброшено исключение.
Функция клонирования работает следующим образом:
- Сначала он очищает и утилизирует все элементы от этого с помощью объекта функции диспергатора.
- После этого он начинает клонирование всех элементов исходного контейнера с помощью объекта функции клонера.
- Если выполняется какая-либо операция в функции клонирования (например, объект функции клонера), все сконструированные элементы утилизируются с использованием объекта функции клонирования.
Вот примерклона
:
#include <boost/intrusive/list.hpp>
#include <iostream>
#include <vector>
using namespace boost::intrusive;
class my_class : public list_base_hook<>
{
public:
friend bool operator==(const my_class &a, const my_class &b)
{ return a.int_ == b.int_; }
int int_;
};
typedef list<my_class> my_class_list;
struct new_cloner
{
my_class *operator()(const my_class &clone_this)
{ return new my_class(clone_this); }
};
struct delete_disposer
{
void operator()(my_class *delete_this)
{ delete delete_this; }
};
int main()
{
const int MaxElem = 100;
std::vector<my_class> nodes(MaxElem);
my_class_list list;
for(int i = 0; i < MaxElem; ++i) nodes[i].int_ = i;
list.insert(list.end(), nodes.begin(), nodes.end());
my_class_list cloned_list;
cloned_list.clone_from(list, new_cloner(), delete_disposer());
if(cloned_list != list)
std::cout << "Both lists are different" << std::endl;
else
std::cout << "Both lists are equal" << std::endl;
cloned_list.clear_and_dispose(delete_disposer());
return 0;
}