Программист может обнаружить, что базовые или членские крючки недостаточно гибки в некоторых ситуациях. В некоторых приложениях было бы оптимально поместить крючок глубоко внутри члена класса или просто вне класса. Boost.Intrusive имеет простой вариант разрешения таких случаев: function_hook
.
Эта опция похожа на member_hook
или base_hook
, но программист может указать объект функции, который сообщает контейнеру, как получить крюк от значения и наоборот. Программист должен определить следующий объект функции:
struct Functor
{
typedef hook_type;
typedef hook_ptr;
typedef const_hook_ptr;
typedef value_type;
typedef pointer;
typedef const_pointer;
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;
struct InnerNode
{
int dummy;
list_member_hook<> hook;
} inner;
};
struct Functor
{
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;
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
);
}
};
typedef list< MyClass, function_hook< Functor> > List;
int main()
{
MyClass n;
List l;
l.insert(l.begin(), n);
assert(l.size() == 1);
return 0;
}