| ///////////////////////////////////////////////////////////////////////////// |
| // |
| // (C) Copyright Ion Gaztanaga 2007-2009 |
| // |
| // 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. |
| // |
| ///////////////////////////////////////////////////////////////////////////// |
| |
| #ifndef BOOST_INTRUSIVE_GENERIC_HOOK_HPP |
| #define BOOST_INTRUSIVE_GENERIC_HOOK_HPP |
| |
| #include <boost/intrusive/detail/config_begin.hpp> |
| #include <boost/intrusive/intrusive_fwd.hpp> |
| #include <boost/intrusive/detail/pointer_to_other.hpp> |
| #include <boost/intrusive/link_mode.hpp> |
| #include <boost/intrusive/detail/utilities.hpp> |
| #include <boost/intrusive/detail/mpl.hpp> |
| #include <boost/static_assert.hpp> |
| |
| namespace boost { |
| namespace intrusive { |
| namespace detail { |
| |
| /// @cond |
| |
| enum |
| { NoBaseHook |
| , ListBaseHook |
| , SlistBaseHook |
| , SetBaseHook |
| , UsetBaseHook |
| , SplaySetBaseHook |
| , AvlSetBaseHook |
| , BsSetBaseHook |
| , AnyBaseHook |
| }; |
| |
| struct no_default_definer{}; |
| |
| template <class Hook, unsigned int> |
| struct default_definer; |
| |
| template <class Hook> |
| struct default_definer<Hook, ListBaseHook> |
| { typedef Hook default_list_hook; }; |
| |
| template <class Hook> |
| struct default_definer<Hook, SlistBaseHook> |
| { typedef Hook default_slist_hook; }; |
| |
| template <class Hook> |
| struct default_definer<Hook, SetBaseHook> |
| { typedef Hook default_set_hook; }; |
| |
| template <class Hook> |
| struct default_definer<Hook, UsetBaseHook> |
| { typedef Hook default_uset_hook; }; |
| |
| template <class Hook> |
| struct default_definer<Hook, SplaySetBaseHook> |
| { typedef Hook default_splay_set_hook; }; |
| |
| template <class Hook> |
| struct default_definer<Hook, AvlSetBaseHook> |
| { typedef Hook default_avl_set_hook; }; |
| |
| template <class Hook> |
| struct default_definer<Hook, BsSetBaseHook> |
| { typedef Hook default_bs_set_hook; }; |
| |
| template <class Hook> |
| struct default_definer<Hook, AnyBaseHook> |
| { typedef Hook default_any_hook; }; |
| |
| template <class Hook, unsigned int BaseHookType> |
| struct make_default_definer |
| { |
| typedef typename detail::if_c |
| < BaseHookType != 0 |
| , default_definer<Hook, BaseHookType> |
| , no_default_definer>::type type; |
| }; |
| |
| template |
| < class GetNodeAlgorithms |
| , class Tag |
| , link_mode_type LinkMode |
| , int HookType |
| > |
| struct make_node_holder |
| { |
| typedef typename detail::if_c |
| <!detail::is_same<Tag, member_tag>::value |
| , detail::node_holder |
| < typename GetNodeAlgorithms::type::node |
| , Tag |
| , LinkMode |
| , HookType> |
| , typename GetNodeAlgorithms::type::node |
| >::type type; |
| }; |
| |
| /// @endcond |
| |
| template |
| < class GetNodeAlgorithms |
| , class Tag |
| , link_mode_type LinkMode |
| , int HookType |
| > |
| class generic_hook |
| /// @cond |
| |
| //If the hook is a base hook, derive generic hook from detail::node_holder |
| //so that a unique base class is created to convert from the node |
| //to the type. This mechanism will be used by base_hook_traits. |
| // |
| //If the hook is a member hook, generic hook will directly derive |
| //from the hook. |
| : public make_default_definer |
| < generic_hook<GetNodeAlgorithms, Tag, LinkMode, HookType> |
| , detail::is_same<Tag, default_tag>::value*HookType |
| >::type |
| , public make_node_holder<GetNodeAlgorithms, Tag, LinkMode, HookType>::type |
| /// @endcond |
| { |
| /// @cond |
| typedef typename GetNodeAlgorithms::type node_algorithms; |
| typedef typename node_algorithms::node node; |
| typedef typename node_algorithms::node_ptr node_ptr; |
| typedef typename node_algorithms::const_node_ptr const_node_ptr; |
| |
| public: |
| struct boost_intrusive_tags |
| { |
| static const int hook_type = HookType; |
| static const link_mode_type link_mode = LinkMode; |
| typedef Tag tag; |
| typedef typename GetNodeAlgorithms::type::node_traits node_traits; |
| static const bool is_base_hook = !detail::is_same<Tag, member_tag>::value; |
| static const bool safemode_or_autounlink = |
| (int)link_mode == (int)auto_unlink || (int)link_mode == (int)safe_link; |
| }; |
| |
| public: |
| /// @endcond |
| |
| generic_hook() |
| { |
| if(boost_intrusive_tags::safemode_or_autounlink){ |
| node_algorithms::init(static_cast<node*>(this)); |
| } |
| } |
| |
| generic_hook(const generic_hook& ) |
| { |
| if(boost_intrusive_tags::safemode_or_autounlink){ |
| node_algorithms::init(static_cast<node*>(this)); |
| } |
| } |
| |
| generic_hook& operator=(const generic_hook& ) |
| { return *this; } |
| |
| ~generic_hook() |
| { |
| destructor_impl |
| (*this, detail::link_dispatch<boost_intrusive_tags::link_mode>()); |
| } |
| |
| void swap_nodes(generic_hook &other) |
| { |
| node_algorithms::swap_nodes |
| ( static_cast<node*>(this), static_cast<node*>(&other)); |
| } |
| |
| bool is_linked() const |
| { |
| //is_linked() can be only used in safe-mode or auto-unlink |
| BOOST_STATIC_ASSERT(( boost_intrusive_tags::safemode_or_autounlink )); |
| return !node_algorithms::unique |
| (static_cast<const node*>(this)); |
| } |
| |
| void unlink() |
| { |
| BOOST_STATIC_ASSERT(( (int)boost_intrusive_tags::link_mode == (int)auto_unlink )); |
| node_algorithms::unlink(static_cast<node*>(this)); |
| node_algorithms::init(static_cast<node*>(this)); |
| } |
| }; |
| |
| } //namespace detail |
| } //namespace intrusive |
| } //namespace boost |
| |
| #include <boost/intrusive/detail/config_end.hpp> |
| |
| #endif //BOOST_INTRUSIVE_GENERIC_HOOK_HPP |