...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
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 container might be currently
inserted. 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_member_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; }