intrusive/test/function_hook_test.cpp

151 lines
5.6 KiB
C++

/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2010-2013
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/intrusive/parent_from_member.hpp>
#include <boost/intrusive/list.hpp>
#include <boost/intrusive/slist.hpp>
#include <boost/intrusive/set.hpp>
#include <boost/intrusive/unordered_set.hpp>
#include <boost/functional/hash.hpp>
using namespace boost::intrusive;
struct MyClass
{
MyClass() : order(0) {}
int order;
//This internal type has two hooks
struct InnerNode : public list_base_hook<>, public slist_base_hook<>
, public set_base_hook<>, public unordered_set_base_hook<>
{
list_member_hook<> listhook;
slist_member_hook<> slisthook;
set_member_hook<> sethook;
unordered_set_member_hook<> usethook;
} inner;
friend bool operator < (const MyClass &l, const MyClass &r)
{ return l.order < r.order; }
friend bool operator == (const MyClass &l, const MyClass &r)
{ return l.order == r.order; }
friend std::size_t hash_value(const MyClass &value)
{ return std::size_t(value.order); }
};
//This functor converts between MyClass and the InnerNode member hook
#define InnerMemberHook(TAG, HOOKTYPE, MEMBERNAME)\
struct InnerMemberHookFunctor##TAG \
{\
typedef HOOKTYPE 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.MEMBERNAME; }\
static const_hook_ptr to_hook_ptr(const value_type &value)\
{ return &value.inner.MEMBERNAME; }\
static pointer to_value_ptr(hook_ptr n)\
{\
return get_parent_from_member<MyClass>\
(get_parent_from_member<MyClass::InnerNode>(n, &MyClass::InnerNode::MEMBERNAME)\
,&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::MEMBERNAME)\
,&MyClass::inner\
);\
}\
};\
//
//This functor converts between MyClass and the InnerNode base hook
#define InnerBaseHook(TAG, HOOKTYPE)\
struct InnerBaseHookFunctor##TAG \
{\
typedef HOOKTYPE 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; }\
static const_hook_ptr to_hook_ptr(const value_type &value)\
{ return &value.inner; }\
static pointer to_value_ptr(hook_ptr n)\
{\
return get_parent_from_member<MyClass>(static_cast<MyClass::InnerNode*>(n),&MyClass::inner);\
}\
static const_pointer to_value_ptr(const_hook_ptr n)\
{\
return get_parent_from_member<MyClass>(static_cast<const MyClass::InnerNode*>(n),&MyClass::inner);\
}\
};\
//
//List
InnerMemberHook(List, list_member_hook<>, listhook)
InnerBaseHook(List, list_base_hook<>)
//Slist
InnerMemberHook(Slist, slist_member_hook<>, slisthook)
InnerBaseHook(Slist, slist_base_hook<>)
//Set
InnerMemberHook(Set, set_member_hook<>, sethook)
InnerBaseHook(Set, set_base_hook<>)
//Unordered Set
InnerMemberHook(USet, unordered_set_member_hook<>, usethook)
InnerBaseHook(USet, unordered_set_base_hook<>)
//Define containers
typedef list < MyClass, function_hook< InnerMemberHookFunctorList> > CustomListMember;
typedef list < MyClass, function_hook< InnerBaseHookFunctorList > > CustomListBase;
typedef slist< MyClass, function_hook< InnerMemberHookFunctorSlist> > CustomSlistMember;
typedef slist< MyClass, function_hook< InnerBaseHookFunctorSlist > > CustomSlistBase;
typedef set < MyClass, function_hook< InnerMemberHookFunctorSet> > CustomSetMember;
typedef set < MyClass, function_hook< InnerBaseHookFunctorSet > > CustomSetBase;
typedef unordered_set< MyClass, function_hook< InnerMemberHookFunctorUSet> > CustomUSetMember;
typedef unordered_set< MyClass, function_hook< InnerBaseHookFunctorUSet > > CustomUSetBase;
int main()
{
MyClass n;
CustomListBase listbase;
CustomListMember listmember;
CustomSlistBase slistbase;
CustomSlistMember slistmember;
CustomSetBase setbase;
CustomSetMember setmember;
CustomUSetBase::bucket_type buckets_uset[1];
CustomUSetBase usetbase(CustomUSetBase::bucket_traits(buckets_uset, 1));
CustomUSetBase::bucket_type buckets_umultiset[1];
CustomUSetMember usetmember(CustomUSetMember::bucket_traits(buckets_umultiset, 1));
listbase.insert(listbase.begin(), n);
listmember.insert(listmember.begin(), n);
slistbase.insert(slistbase.begin(), n);
slistmember.insert(slistmember.begin(), n);
setbase.insert(n);
setmember.insert(n);
usetbase.insert(n);
usetmember.insert(n);
return 0;
}