Boost logo

Boost :

From: Olaf Krzikalla (krzikalla_at_[hidden])
Date: 2007-08-09 05:03:53


Hi Tobias,

as Ion already wrote the idea is interesting.
However I have some remarks:

Tobias Schwinger wrote:
> #include <boost/detail/lightweight_test.hpp> #include <map>
>
> class foo : public intrusive::slist_node_mgmt_data<foo> // Note: Base
> class does not insert any names { int val_data; public:
>
> foo(int data) : val_data(data) { }
>
> int data() const { return this->val_data; }
>
> // Note: No "member hook" };
IMHO 'ptr_next' is still injected in the name space of foo, since
visiblitiy and accessibility are orthogonal concepts.

> // Management facility
> std::map<bar*,intrusive::slist_node_mgmt_data<bar> > bar_management;
>
> intrusive::slist_node_mgmt_data<bar>& get_mgmt(bar& that) { return
> bar_management[& that]; }
get_mgmt should be a functor. It's extremely difficult to pass
contextual information to a free standing function. Your example shows
that right off by simply operating on a global variable.

The question is if we can or should (ab)use the traits class for this or
if we introduce another template parameter like this:

//--------------------------------------

struct default_mgmt
{
   template< typename Element, class Traits >
   slist_node_mgmt_data<Element,Traits>&operator()
     (slist_node_mgmt_data<Element,Traits>& that)
   {
       return that;
   }
}

// single-linked list (incomplete for illustration)
template< typename T, class Mgmt = default_mgmt,
           class Traits = slist_node_traits<T> >
class slist : boost::noncopyable
{
   typedef Traits traits;
   Mgmt get_mgmt;
public:
   slist(const Mgmt& m) : get_mgmt(m) {}

   void push_front(reference x)
   {
     get_mgmt(x).ptr_next = this->ptr_first;
     this->ptr_first = & x;
   }
};

// Ok, let's try non-intrusive Intrusive ;-)

typedef std::map<bar*,intrusive::slist_node_mgmt_data<bar> > bar_chainer;

struct bar_mgmt
{
   bar_chainer& bar_management_;
   bar_mgmt(bar_chainer& b) : bar_management_(b) {}

   slist_node_mgmt_data<bar>& operator()(bar& that)
   {
       return bar_management_[&that];
   }
};

void bar_test()
{
   // now a local variable is feasible:
   std::map<bar*,intrusive::slist_node_mgmt_data<bar> > bar_management;

   intrusive::slist<bar, bar_mgmt> my_list(bar_mgmt(bar_management));
   // aso.
}

//--------------------------------------

Something along those lines. Of course the user is now responsible for
the proper lifetime management of bar_management. But I don't consider
this to be an big issue as it is a typically problem of functors
containing references.

Best regards
Olaf Krzikalla


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk