
Hi Ion and Olaf, I recently started using Boost.Intrusive and it really works like a charm. However, I've been wondering whether it would be possible to make the "hook interface" easier to use and less demanding in terms of names that are injected into client code. So I started experimenting a bit and the attachment is what I came up with. I believe that scheme might actually work (not sure, though)... Regards, Tobias #include <boost/noncopyable.hpp> namespace intrusive { // traits for customization template< typename T > struct slist_node_traits { typedef T* pointer_type; typedef T& reference; // ... }; // management data for one node template< typename T, class Traits = slist_node_traits<T> > class slist_node_mgmt_data { template< typename U, class Tr > friend class slist; typename Traits::pointer_type ptr_next; public: slist_node_mgmt_data() { } }; // ADL extension point to allow Boost.Intrusive to work non-intrusively // by e.g. using an external map<element,management data> template< typename Element, class Traits > slist_node_mgmt_data<Element,Traits>& get_mgmt( slist_node_mgmt_data<Element,Traits>& that) { return that; } // single-linked list (incomplete for illustration) template< typename T, class Traits = slist_node_traits<T> > class slist : boost::noncopyable { typedef Traits traits; public: typedef typename traits::pointer_type pointer_type; typedef typename traits::reference reference; pointer_type ptr_first; public: void push_front(reference x) { get_mgmt(x).ptr_next = this->ptr_first; this->ptr_first = & x; } void pop_front() { this->ptr_first = get_mgmt(* this->ptr_first).ptr_next; } reference front() { return *this->ptr_first; } // ... }; } #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" }; void foo_test() { intrusive::slist<foo> my_list; foo foo1(1); my_list.push_front(foo1); foo foo2(2); my_list.push_front(foo2); BOOST_TEST( my_list.front().data() == 2 ); my_list.pop_front(); BOOST_TEST( my_list.front().data() == 1 ); my_list.pop_front(); } // Ok, let's try non-intrusive Intrusive ;-) class bar // Note: No base class { int val_data; public: bar(int data) : val_data(data) { } int data() const { return this->val_data; } // Note: No "member hook" }; // 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]; } void bar_test() { intrusive::slist<bar> my_list; bar bar1(1); my_list.push_front(bar1); bar bar2(2); my_list.push_front(bar2); BOOST_TEST( my_list.front().data() == 2 ); my_list.pop_front(); BOOST_TEST( my_list.front().data() == 1 ); my_list.pop_front(); } // Run the tests... int main() { foo_test(); bar_test(); return boost::report_errors(); }