Boost C++ 库

...世界上最受推崇、设计最精巧的 C++ 库项目之一。 Herb SutterAndrei AlexandrescuC++ Coding Standards

使用函数钩子 - Boost C++ 函数库
PrevUpHomeNext

在某些情况下,程序员可能会发现基类或成员钩子不够灵活。在某些应用程序中,将钩子放在类成员的深处或类外部会是最佳选择。 Boost.Intrusive 提供了一个简单的选项来支持这种情况:function_hook

此选项类似于 member_hookbase_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;
}

PrevUpHomeNext