有时,类程序员希望将一个类放置在多个侵入式容器中,但不同时放置。在这种情况下,程序员可能会决定在同一个类中插入两个钩子。
class MyClass : public list_base_hook<>, public slist_base_hook<> //... {};
然而,在 Boost.Intrusive 中有一个更节省空间的替代方案:“任意”钩子(any_base_hook
和 any_member_hook
)。这些钩子可用于将一个类型存储在 Boost.Intrusive 提供的多个容器中,从而最大限度地减小类的大小。
这些钩子支持以下选项
tag<class Tag>
(仅适用于基类钩子):此参数用作标记,因此您可以从多个 slist 钩子派生。默认值:tag<default_tag>
。link_mode<link_mode_type LinkMode>
:链接策略。link_mode<auto_unlink>
不受支持,并且 link_mode<safe_mode>
在任意钩子中可能比在其他钩子中提供更弱的错误检测。默认值:link_mode<safe_link>
。void_pointer<class VoidPointer>
:要在钩子内部使用并传播到容器的指针类型。默认值:void_pointer<void*>
。
不支持 auto_unlink
,因为钩子不知道它当前可能插入到哪种类型的容器中。此外,由于相同的原因,这些钩子不支持 unlink()
和 swap_nodes()
操作。
以下示例创建一个具有两个任意钩子的类,并使用其中一个将该类插入到 slist
中,将另一个插入到 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()); MemberList::reverse_iterator mrit(member_list.rbegin()); 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; }