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 the documentation for an old version of Boost. Click here to view this page for the latest version.
PrevUpHomeNext

Cloning Boost.Intrusive containers

As previously mentioned, Boost.Intrusive containers are non-copyable and non-assignable, because intrusive containers don't allocate memory at all. To implement a copy-constructor or assignment operator, the user must clone one by one all the elements of the container and insert them in another intrusive container. However, cloning by hand is usually more inefficient than a member cloning function and a specialized cloning function can offer more guarantees than the manual cloning (better exception safety guarantees, for example).

To ease the implementation of copy constructors and assignment operators of classes containing Boost.Intrusive containers, all Boost.Intrusive containers offer a special cloning function called clone_from.

Apart from the container to be cloned, clone_from takes two function objects as arguments. For example, consider the clone_from member function of list:

template <class Cloner, class Disposer>
void clone_from(const list &src, Cloner cloner, Disposer disposer);

This function will make *this a clone of src. Let's explain the arguments:

The cloning function works as follows:

Here is an example of clone_from:

#include <boost/intrusive/list.hpp>
#include <iostream>
#include <vector>

using namespace boost::intrusive;

//A class that can be inserted in an intrusive list
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_;

   //...
};

//Definition of the intrusive list
typedef list<my_class> my_class_list;

//Cloner object function
struct new_cloner
{
   my_class *operator()(const my_class &clone_this)
   {  return new my_class(clone_this);  }
};

//The disposer object function
struct delete_disposer
{
   void operator()(my_class *delete_this)
   {  delete delete_this;  }
};

int main()
{
   const int MaxElem = 100;
   std::vector<my_class> nodes(MaxElem);

   //Fill all the nodes and insert them in the list
   my_class_list list;

   for(int i = 0; i < MaxElem; ++i) nodes[i].int_ = i;

   list.insert(list.end(), nodes.begin(), nodes.end());

   //Now clone "list" using "new" and "delete" object functions
   my_class_list cloned_list;
   cloned_list.clone_from(list, new_cloner(), delete_disposer());

   //Test that both are equal
   if(cloned_list != list)
      std::cout << "Both lists are different" << std::endl;
   else
      std::cout << "Both lists are equal" << std::endl;

   //Don't forget to free the memory from the second list
   cloned_list.clear_and_dispose(delete_disposer());
   return 0;
}

PrevUpHomeNext