在某些情况下,程序员可能会发现基类或成员钩子不够灵活。在某些应用程序中,将钩子放在类成员的深处或类外部会是最佳选择。 Boost.Intrusive 提供了一个简单的选项来支持这种情况:function_hook
。
此选项类似于 member_hook
或 base_hook
,但程序员可以指定一个函数对象,该对象告诉容器如何从值中获取钩子,反之亦然。程序员只需定义以下函数对象:
//This functor converts between value_type and a hook_type struct Functor { //Required types typedef /*impl-defined*/ hook_type; typedef /*impl-defined*/ hook_ptr; typedef /*impl-defined*/ const_hook_ptr; typedef /*impl-defined*/ value_type; typedef /*impl-defined*/ pointer; typedef /*impl-defined*/ const_pointer; //Required static functions static hook_ptr to_hook_ptr (value_type &value); static const_hook_ptr to_hook_ptr(const value_type &value); static pointer to_value_ptr(hook_ptr n); static const_pointer to_value_ptr(const_hook_ptr n); };
从值到钩子的转换通常很简单,因为在实践中大多数钩子都是类数据成员的成员或基类。反向操作有点复杂,但 Boost.Intrusive 通过函数 get_parent_from_member
提供了一些帮助,该函数允许轻松地将数据成员的地址转换为包含该成员的父对象的地址。让我们来看一个关于 function_hook
的小例子:
#include <boost/intrusive/list.hpp> #include <boost/intrusive/parent_from_member.hpp> using namespace boost::intrusive; struct MyClass { int dummy; //This internal type has a member hook struct InnerNode { int dummy; list_member_hook<> hook; } inner; }; //This functor converts between MyClass and InnerNode's member hook struct Functor { //Required types typedef list_member_hook<> hook_type; typedef hook_type* hook_ptr; typedef const hook_type* const_hook_ptr; typedef MyClass value_type; typedef value_type* pointer; typedef const value_type* const_pointer; //Required static functions static hook_ptr to_hook_ptr (value_type &value) { return &value.inner.hook; } static const_hook_ptr to_hook_ptr(const value_type &value) { return &value.inner.hook; } static pointer to_value_ptr(hook_ptr n) { return get_parent_from_member<MyClass> (get_parent_from_member<MyClass::InnerNode>(n, &MyClass::InnerNode::hook) ,&MyClass::inner ); } static const_pointer to_value_ptr(const_hook_ptr n) { return get_parent_from_member<MyClass> (get_parent_from_member<MyClass::InnerNode>(n, &MyClass::InnerNode::hook) ,&MyClass::inner ); } }; //Define a list that will use the hook accessed through the function object typedef list< MyClass, function_hook< Functor> > List; int main() { MyClass n; List l; //Insert the node in both lists l.insert(l.begin(), n); assert(l.size() == 1); return 0; }