Any Hooks: A single hook for any Intrusive container

| Home | Libraries | People | FAQ | More

## Any Hooks: A single hook for any Intrusive container

Sometimes, a class programmer wants to place a class in several intrusive containers but no at the same time. In this case, the programmer might decide to insert two hooks in the same class.

    class MyClass
       : public list_base_hook<>, public slist_base_hook<> //...
    {};

However, there is a more size-efficient alternative in Boost.Intrusive: "any" hooks (`any_base_hook` and `any_member_hook`. These hooks can be used to store a type in several containers offered by Boost.Intrusive minimizing the size of the class.

These hooks support these options:

- `tag<class Tag>` (for base hooks only): This argument serves as a tag, so you can derive from more than one slist hook. Default: `tag<default_tag>`.
- `link_mode<link_mode_type LinkMode>`: The linking policy. `link_mode<auto_unlink>` is not supported and `link_mode<safe_mode>` might offer weaker error detection in any hooks than in other hooks. Default: `link_mode<safe_link>`.
- `void_pointer<class VoidPointer>`: The pointer type to be used internally in the hook and propagated to the container. Default: `void_pointer<void*>`.

`auto_unlink` can't be supported because the hook does not know in which type of might be inserted container. Additionally, these hooks don't support `unlink()` and `swap_nodes()` operations for the same reason.

Here is an example that creates a class with two any hooks, and uses one to insert the class in a `slist` and the other one in a `list`.

    #include <vector>
    #include <boost/intrusive/any_hook.hpp>
    #include <boost/intrusive/slist.hpp>
    #include <boost/intrusive/list.hpp>

    using namespace boost::intrusive;

    class MyClass : public any_base_hook<> //Base hook
    {
       int int_;

       public:
       any_member_hook<> member_hook_;  //Member hook

       MyClass(int i = 0) : int_(i)
       {}
    };

    int main()
    {
       //Define a base hook option that converts any_base_hook to a slist hook
       typedef any_to_slist_hook < base_hook< any_base_hook<> > >     BaseSlistOption;
       typedef slist<MyClass, BaseSlistOption>                        BaseSList;

       //Define a member hook option that converts any_base_hook to a list hook
       typedef any_to_list_hook< member_hook
             < MyClass, any_member_hook<>, &MyClass::member_hook_> >  MemberListOption;
       typedef list<MyClass, MemberListOption>                        MemberList;

       //Create several MyClass objects, each one with a different value
       std::vector<MyClass> values;
       for(int i = 0; i < 100; ++i){ values.push_back(MyClass(i)); }

       BaseSList base_slist;   MemberList member_list;

       //Now insert them in reverse order in the slist and in order in the list
       for(std::vector<MyClass>::iterator it(values.begin()), itend(values.end()); it != itend; ++it)
          base_slist.push_front(*it), member_list.push_back(*it);

       //Now test lists
       BaseSList::iterator bit(base_slist.begin()), bitend(base_slist.end());
       MemberList::reverse_iterator mrit(member_list.rbegin()), mritend(member_list.rend());
       std::vector<MyClass>::reverse_iterator rit(values.rbegin()), ritend(values.rend());

       //Test the objects inserted in the base hook list
       for(; rit != ritend; ++rit, ++bit, ++mrit)
          if(&*bit != &*rit || &*mrit != &*rit)  return 1;
       return 0;
    }