From a60ea9d4742cad6daafad9a041c72f1f212f3d70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sat, 21 Jun 2008 09:04:21 +0000 Subject: [PATCH] gcc 4.3 fixes for normal and -std=c++0x modes [SVN r46571] --- include/boost/intrusive/any_hook.hpp | 320 ++++++++++++++++++ .../boost/intrusive/avltree_algorithms.hpp | 3 +- .../intrusive/circular_list_algorithms.hpp | 1 + .../intrusive/circular_slist_algorithms.hpp | 1 + .../detail/any_node_and_algorithms.hpp | 292 ++++++++++++++++ .../detail/common_slist_algorithms.hpp | 3 +- .../boost/intrusive/detail/generic_hook.hpp | 53 +-- .../boost/intrusive/detail/hashtable_node.hpp | 12 +- include/boost/intrusive/detail/list_node.hpp | 1 - .../intrusive/detail/parent_from_member.hpp | 21 +- include/boost/intrusive/detail/slist_node.hpp | 1 - .../intrusive/detail/tree_algorithms.hpp | 7 +- include/boost/intrusive/detail/utilities.hpp | 19 ++ include/boost/intrusive/hashtable.hpp | 199 +++++++---- include/boost/intrusive/intrusive_fwd.hpp | 17 + .../intrusive/linear_slist_algorithms.hpp | 1 + include/boost/intrusive/options.hpp | 94 +++-- include/boost/intrusive/rbtree_algorithms.hpp | 2 +- include/boost/intrusive/sgtree_algorithms.hpp | 2 +- .../boost/intrusive/splaytree_algorithms.hpp | 2 +- include/boost/intrusive/unordered_set.hpp | 18 +- .../boost/intrusive/unordered_set_hook.hpp | 29 +- 22 files changed, 923 insertions(+), 175 deletions(-) create mode 100644 include/boost/intrusive/any_hook.hpp create mode 100644 include/boost/intrusive/detail/any_node_and_algorithms.hpp diff --git a/include/boost/intrusive/any_hook.hpp b/include/boost/intrusive/any_hook.hpp new file mode 100644 index 0000000..148d41d --- /dev/null +++ b/include/boost/intrusive/any_hook.hpp @@ -0,0 +1,320 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-2008 +// +// 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_ANY_HOOK_HPP +#define BOOST_INTRUSIVE_ANY_HOOK_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace intrusive { + +/// @cond +template +struct get_any_node_algo +{ + typedef any_algorithms type; +}; +/// @endcond + +//! Helper metafunction to define a \c \c any_base_hook that yields to the same +//! type when the same options (either explicitly or implicitly) are used. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +struct make_any_base_hook +{ + /// @cond + typedef typename pack_options + < hook_defaults, O1, O2, O3>::type packed_options; + + typedef detail::generic_hook + < get_any_node_algo + , typename packed_options::tag + , packed_options::link_mode + , detail::AnyBaseHook + > implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + +//! Derive a class from this hook in order to store objects of that class +//! in an intrusive container. +//! +//! The hook admits the following options: \c tag<>, \c void_pointer<> and +//! \c link_mode<>. +//! +//! \c tag<> defines a tag to identify the node. +//! The same tag value can be used in different classes, but if a class is +//! derived from more than one \c any_base_hook, then each \c any_base_hook needs its +//! unique tag. +//! +//! \c link_mode<> will specify the linking mode of the hook (\c normal_link, \c safe_link). +//! +//! \c void_pointer<> is the pointer type that will be used internally in the hook +//! and the the container configured to use this hook. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +class any_base_hook + : public make_any_base_hook::type +{ + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + public: + //! Effects: If link_mode is or \c safe_link + //! initializes the node to an unlinked state. + //! + //! Throws: Nothing. + any_base_hook(); + + //! Effects: If link_mode is or \c safe_link + //! initializes the node to an unlinked state. The argument is ignored. + //! + //! Throws: Nothing. + //! + //! Rationale: Providing a copy-constructor + //! makes classes using the hook STL-compliant without forcing the + //! user to do some additional work. \c swap can be used to emulate + //! move-semantics. + any_base_hook(const any_base_hook& ); + + //! Effects: Empty function. The argument is ignored. + //! + //! Throws: Nothing. + //! + //! Rationale: Providing an assignment operator + //! makes classes using the hook STL-compliant without forcing the + //! user to do some additional work. \c swap can be used to emulate + //! move-semantics. + any_base_hook& operator=(const any_base_hook& ); + + //! Effects: If link_mode is \c normal_link, the destructor does + //! nothing (ie. no code is generated). If link_mode is \c safe_link and the + //! object is stored in a container an assertion is raised. + //! + //! Throws: Nothing. + ~any_base_hook(); + + //! Precondition: link_mode must be \c safe_link. + //! + //! Returns: true, if the node belongs to a container, false + //! otherwise. This function can be used to test whether \c container::iterator_to + //! will return a valid iterator. + //! + //! Complexity: Constant + bool is_linked() const; + #endif +}; + +//! Helper metafunction to define a \c \c any_member_hook that yields to the same +//! type when the same options (either explicitly or implicitly) are used. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +struct make_any_member_hook +{ + /// @cond + typedef typename pack_options + < hook_defaults, O1, O2, O3>::type packed_options; + + typedef detail::generic_hook + < get_any_node_algo + , member_tag + , packed_options::link_mode + , detail::NoBaseHook + > implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + +//! Store this hook in a class to be inserted +//! in an intrusive container. +//! +//! The hook admits the following options: \c void_pointer<> and +//! \c link_mode<>. +//! +//! \c link_mode<> will specify the linking mode of the hook (\c normal_link or \c safe_link). +//! +//! \c void_pointer<> is the pointer type that will be used internally in the hook +//! and the the container configured to use this hook. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +class any_member_hook + : public make_any_member_hook::type +{ + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + public: + //! Effects: If link_mode is or \c safe_link + //! initializes the node to an unlinked state. + //! + //! Throws: Nothing. + any_member_hook(); + + //! Effects: If link_mode is or \c safe_link + //! initializes the node to an unlinked state. The argument is ignored. + //! + //! Throws: Nothing. + //! + //! Rationale: Providing a copy-constructor + //! makes classes using the hook STL-compliant without forcing the + //! user to do some additional work. \c swap can be used to emulate + //! move-semantics. + any_member_hook(const any_member_hook& ); + + //! Effects: Empty function. The argument is ignored. + //! + //! Throws: Nothing. + //! + //! Rationale: Providing an assignment operator + //! makes classes using the hook STL-compliant without forcing the + //! user to do some additional work. \c swap can be used to emulate + //! move-semantics. + any_member_hook& operator=(const any_member_hook& ); + + //! Effects: If link_mode is \c normal_link, the destructor does + //! nothing (ie. no code is generated). If link_mode is \c safe_link and the + //! object is stored in a container an assertion is raised. + //! + //! Throws: Nothing. + ~any_member_hook(); + + //! Precondition: link_mode must be \c safe_link. + //! + //! Returns: true, if the node belongs to a container, false + //! otherwise. This function can be used to test whether \c container::iterator_to + //! will return a valid iterator. + //! + //! Complexity: Constant + bool is_linked() const; + #endif +}; + +/// @cond + +namespace detail{ + +template +struct any_to_get_base_pointer_type +{ + typedef typename pointer_to_other + ::type type; +}; + +template +struct any_to_get_member_pointer_type +{ + typedef typename pointer_to_other + ::type type; +}; + +//!This option setter specifies that the container +//!must use the specified base hook +template class NodeTraits> +struct any_to_some_hook +{ + typedef typename BaseHook::template pack::value_traits old_value_traits; + template + struct pack : public Base + { + struct value_traits : public old_value_traits + { + static const bool is_any_hook = true; + typedef typename detail::eval_if_c + < detail::internal_base_hook_bool_is_true::value + , any_to_get_base_pointer_type + , any_to_get_member_pointer_type + >::type void_pointer; + typedef NodeTraits node_traits; + }; + }; +}; + +} //namespace detail{ + +/// @endcond + +//!This option setter specifies that +//!any hook should behave as an slist hook +template +struct any_to_slist_hook +/// @cond + : public detail::any_to_some_hook +/// @endcond +{}; + +//!This option setter specifies that +//!any hook should behave as an list hook +template +struct any_to_list_hook +/// @cond + : public detail::any_to_some_hook +/// @endcond +{}; + +//!This option setter specifies that +//!any hook should behave as a set hook +template +struct any_to_set_hook +/// @cond + : public detail::any_to_some_hook +/// @endcond +{}; + +//!This option setter specifies that +//!any hook should behave as a set hook +template +struct any_to_avl_set_hook +/// @cond + : public detail::any_to_some_hook +/// @endcond +{}; + +//!This option setter specifies that any +//!hook should behave as a set hook +template +struct any_to_bs_set_hook +/// @cond + : public detail::any_to_some_hook +/// @endcond +{}; + +//!This option setter specifies that any hook +//!should behave as an unordered set hook +template +struct any_to_unordered_set_hook +/// @cond + : public detail::any_to_some_hook +/// @endcond +{}; + + +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_ANY_HOOK_HPP diff --git a/include/boost/intrusive/avltree_algorithms.hpp b/include/boost/intrusive/avltree_algorithms.hpp index 145e0fb..dc4eed4 100644 --- a/include/boost/intrusive/avltree_algorithms.hpp +++ b/include/boost/intrusive/avltree_algorithms.hpp @@ -68,6 +68,7 @@ template class avltree_algorithms { public: + typedef typename NodeTraits::node node; typedef NodeTraits node_traits; typedef typename NodeTraits::node_ptr node_ptr; typedef typename NodeTraits::const_node_ptr const_node_ptr; @@ -75,8 +76,6 @@ class avltree_algorithms /// @cond private: - - typedef typename NodeTraits::node node; typedef detail::tree_algorithms tree_algorithms; template diff --git a/include/boost/intrusive/circular_list_algorithms.hpp b/include/boost/intrusive/circular_list_algorithms.hpp index 537b151..d48fffc 100644 --- a/include/boost/intrusive/circular_list_algorithms.hpp +++ b/include/boost/intrusive/circular_list_algorithms.hpp @@ -50,6 +50,7 @@ template class circular_list_algorithms { public: + typedef typename NodeTraits::node node; typedef typename NodeTraits::node_ptr node_ptr; typedef typename NodeTraits::const_node_ptr const_node_ptr; typedef NodeTraits node_traits; diff --git a/include/boost/intrusive/circular_slist_algorithms.hpp b/include/boost/intrusive/circular_slist_algorithms.hpp index 2a257e4..f74a641 100644 --- a/include/boost/intrusive/circular_slist_algorithms.hpp +++ b/include/boost/intrusive/circular_slist_algorithms.hpp @@ -54,6 +54,7 @@ class circular_slist_algorithms typedef detail::common_slist_algorithms base_t; /// @endcond public: + typedef typename NodeTraits::node node; typedef typename NodeTraits::node_ptr node_ptr; typedef typename NodeTraits::const_node_ptr const_node_ptr; typedef NodeTraits node_traits; diff --git a/include/boost/intrusive/detail/any_node_and_algorithms.hpp b/include/boost/intrusive/detail/any_node_and_algorithms.hpp new file mode 100644 index 0000000..6b75f57 --- /dev/null +++ b/include/boost/intrusive/detail/any_node_and_algorithms.hpp @@ -0,0 +1,292 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-2008 +// +// 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_ANY_NODE_HPP +#define BOOST_INTRUSIVE_ANY_NODE_HPP + +#include +#include +#include +#include +#include + +namespace boost { +namespace intrusive { + +template +struct any_node +{ + typedef typename boost::pointer_to_other + ::type node_ptr; + node_ptr node_ptr_1; + node_ptr node_ptr_2; + node_ptr node_ptr_3; + std::size_t size_t_1; +}; + +template +struct any_list_node_traits +{ + typedef any_node node; + typedef typename boost::pointer_to_other + ::type node_ptr; + typedef typename boost::pointer_to_other + ::type const_node_ptr; + + static node_ptr get_next(const_node_ptr n) + { return n->node_ptr_1; } + + static void set_next(node_ptr n, node_ptr next) + { n->node_ptr_1 = next; } + + static node_ptr get_previous(const_node_ptr n) + { return n->node_ptr_2; } + + static void set_previous(node_ptr n, node_ptr prev) + { n->node_ptr_2 = prev; } +}; + + +template +struct any_slist_node_traits +{ + typedef any_node node; + typedef typename boost::pointer_to_other + ::type node_ptr; + typedef typename boost::pointer_to_other + ::type const_node_ptr; + + static node_ptr get_next(const_node_ptr n) + { return n->node_ptr_1; } + + static void set_next(node_ptr n, node_ptr next) + { n->node_ptr_1 = next; } +}; + + +template +struct any_unordered_node_traits + : public any_slist_node_traits +{ + typedef any_slist_node_traits reduced_slist_node_traits; + typedef typename reduced_slist_node_traits::node node; + typedef typename reduced_slist_node_traits::node_ptr node_ptr; + typedef typename reduced_slist_node_traits::const_node_ptr const_node_ptr; + + static const bool store_hash = true; + static const bool optimize_multikey = true; + + static node_ptr get_next(const_node_ptr n) + { return node_ptr(&static_cast(*n->node_ptr_1)); } + + static void set_next(node_ptr n, node_ptr next) + { n->node_ptr_1 = next; } + + static node_ptr get_prev_in_group(const_node_ptr n) + { return n->node_ptr_2; } + + static void set_prev_in_group(node_ptr n, node_ptr prev) + { n->node_ptr_2 = prev; } + + static std::size_t get_hash(const_node_ptr n) + { return n->size_t_1; } + + static void set_hash(node_ptr n, std::size_t h) + { n->size_t_1 = h; } +}; + + +template +struct any_rbtree_node_traits +{ + typedef any_node node; + + typedef typename boost::pointer_to_other + ::type node_ptr; + typedef typename boost::pointer_to_other + ::type const_node_ptr; + + typedef std::size_t color; + + static node_ptr get_parent(const_node_ptr n) + { return n->node_ptr_1; } + + static void set_parent(node_ptr n, node_ptr p) + { n->node_ptr_1 = p; } + + static node_ptr get_left(const_node_ptr n) + { return n->node_ptr_2; } + + static void set_left(node_ptr n, node_ptr l) + { n->node_ptr_2 = l; } + + static node_ptr get_right(const_node_ptr n) + { return n->node_ptr_3; } + + static void set_right(node_ptr n, node_ptr r) + { n->node_ptr_3 = r; } + + static color get_color(const_node_ptr n) + { return n->size_t_1; } + + static void set_color(node_ptr n, color c) + { n->size_t_1 = c; } + + static color black() + { return 0u; } + + static color red() + { return 1u; } +}; + + +template +struct any_avltree_node_traits +{ + typedef any_node node; + + typedef typename boost::pointer_to_other + ::type node_ptr; + typedef typename boost::pointer_to_other + ::type const_node_ptr; + typedef std::size_t balance; + + static node_ptr get_parent(const_node_ptr n) + { return n->node_ptr_1; } + + static void set_parent(node_ptr n, node_ptr p) + { n->node_ptr_1 = p; } + + static node_ptr get_left(const_node_ptr n) + { return n->node_ptr_2; } + + static void set_left(node_ptr n, node_ptr l) + { n->node_ptr_2 = l; } + + static node_ptr get_right(const_node_ptr n) + { return n->node_ptr_3; } + + static void set_right(node_ptr n, node_ptr r) + { n->node_ptr_3 = r; } + + static balance get_balance(const_node_ptr n) + { return n->size_t_1; } + + static void set_balance(node_ptr n, balance b) + { n->size_t_1 = b; } + + static balance negative() + { return 0u; } + + static balance zero() + { return 1u; } + + static balance positive() + { return 2u; } +}; + + +template +struct any_tree_node_traits +{ + typedef any_node node; + + typedef typename boost::pointer_to_other + ::type node_ptr; + typedef typename boost::pointer_to_other + ::type const_node_ptr; + + static node_ptr get_parent(const_node_ptr n) + { return n->node_ptr_1; } + + static void set_parent(node_ptr n, node_ptr p) + { n->node_ptr_1 = p; } + + static node_ptr get_left(const_node_ptr n) + { return n->node_ptr_2; } + + static void set_left(node_ptr n, node_ptr l) + { n->node_ptr_2 = l; } + + static node_ptr get_right(const_node_ptr n) + { return n->node_ptr_3; } + + static void set_right(node_ptr n, node_ptr r) + { n->node_ptr_3 = r; } +}; + +template +class any_node_traits +{ + public: + typedef any_node node; + typedef typename boost::pointer_to_other + ::type node_ptr; + typedef typename boost::pointer_to_other + ::type const_node_ptr; +}; + +template +class any_algorithms +{ + public: + typedef any_node node; + typedef typename boost::pointer_to_other + ::type node_ptr; + typedef typename boost::pointer_to_other + ::type const_node_ptr; + typedef any_node_traits node_traits; + + //! Requires: node must not be part of any tree. + //! + //! Effects: After the function unique(node) == true. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Nodes: If node is inserted in a tree, this function corrupts the tree. + static void init(node_ptr node) + { node->node_ptr_1 = 0; }; + + //! Effects: Returns true if node is in the same state as if called init(node) + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + static bool inited(const_node_ptr node) + { return !node->node_ptr_1; }; + + static bool unique(const_node_ptr node) + { return 0 == node->node_ptr_1; } + + static void unlink(node_ptr) + { + //Auto-unlink hooks and unlink() call for safe hooks are not + //available for any hooks!!! + any_algorithms::unlink_not_available_for_any_hooks(); + } + + static void swap_nodes(node_ptr l, node_ptr r) + { + //Any nodes have no swap_nodes capability because they don't know + //what algorithm they must use from unlink them from the container + any_algorithms::swap_nodes_not_available_for_any_hooks(); + } +}; + +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_ANY_NODE_HPP diff --git a/include/boost/intrusive/detail/common_slist_algorithms.hpp b/include/boost/intrusive/detail/common_slist_algorithms.hpp index cc37a74..ada51a9 100644 --- a/include/boost/intrusive/detail/common_slist_algorithms.hpp +++ b/include/boost/intrusive/detail/common_slist_algorithms.hpp @@ -26,6 +26,7 @@ template class common_slist_algorithms { public: + typedef typename NodeTraits::node node; typedef typename NodeTraits::node_ptr node_ptr; typedef typename NodeTraits::const_node_ptr const_node_ptr; typedef NodeTraits node_traits; @@ -53,7 +54,7 @@ class common_slist_algorithms { node_ptr next = NodeTraits::get_next(this_node); return !next || next == this_node; - } + } static bool inited(const_node_ptr this_node) { return !NodeTraits::get_next(this_node); } diff --git a/include/boost/intrusive/detail/generic_hook.hpp b/include/boost/intrusive/detail/generic_hook.hpp index 87dafe2..837f928 100644 --- a/include/boost/intrusive/detail/generic_hook.hpp +++ b/include/boost/intrusive/detail/generic_hook.hpp @@ -18,6 +18,7 @@ #include #include #include +#include #include namespace boost { @@ -35,6 +36,7 @@ enum , SplaySetBaseHook , AvlSetBaseHook , BsSetBaseHook +, AnyBaseHook }; struct no_default_definer{}; @@ -70,6 +72,10 @@ template struct default_definer { typedef Hook default_bs_set_hook; }; +template +struct default_definer +{ typedef Hook default_any_hook; }; + template struct make_default_definer { @@ -90,11 +96,11 @@ struct make_node_holder typedef typename detail::if_c ::value , detail::node_holder - < typename GetNodeAlgorithms::type::node_traits::node + < typename GetNodeAlgorithms::type::node , Tag , LinkMode , HookType> - , typename GetNodeAlgorithms::type::node_traits::node + , typename GetNodeAlgorithms::type::node >::type type; }; @@ -122,38 +128,38 @@ class generic_hook , public make_node_holder::type /// @endcond { - public: /// @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_algorithms; - typedef typename node_algorithms::node_traits node_traits; - typedef typename node_traits::node node; - typedef typename node_traits::node_ptr node_ptr; - typedef typename node_traits::const_node_ptr const_node_ptr; + typedef Tag tag; + typedef typename GetNodeAlgorithms::type::node_traits node_traits; static const bool is_base_hook = !detail::is_same::value; - enum { safemode_or_autounlink = - (int)link_mode == (int)auto_unlink || - (int)link_mode == (int)safe_link }; + 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){ - boost_intrusive_tags::node_algorithms::init - (static_cast(this)); + node_algorithms::init(static_cast(this)); } } generic_hook(const generic_hook& ) { if(boost_intrusive_tags::safemode_or_autounlink){ - boost_intrusive_tags::node_algorithms::init - (static_cast(this)); + node_algorithms::init(static_cast(this)); } } @@ -168,26 +174,23 @@ class generic_hook void swap_nodes(generic_hook &other) { - boost_intrusive_tags::node_algorithms::swap_nodes - ( static_cast(this) - , static_cast(&other)); + node_algorithms::swap_nodes + ( static_cast(this), static_cast(&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 !boost_intrusive_tags::node_algorithms::unique - (static_cast(this)); + return !node_algorithms::unique + (static_cast(this)); } void unlink() { BOOST_STATIC_ASSERT(( (int)boost_intrusive_tags::link_mode == (int)auto_unlink )); - boost_intrusive_tags::node_algorithms::unlink - (static_cast(this)); - boost_intrusive_tags::node_algorithms::init - (static_cast(this)); + node_algorithms::unlink(static_cast(this)); + node_algorithms::init(static_cast(this)); } }; diff --git a/include/boost/intrusive/detail/hashtable_node.hpp b/include/boost/intrusive/detail/hashtable_node.hpp index 66bec59..44a5f5a 100644 --- a/include/boost/intrusive/detail/hashtable_node.hpp +++ b/include/boost/intrusive/detail/hashtable_node.hpp @@ -104,13 +104,13 @@ class hashtable_iterator ::type > { - typedef typename Container::real_value_traits real_value_traits; - typedef typename Container::siterator siterator; - typedef typename Container::const_siterator const_siterator; - typedef typename Container::bucket_type bucket_type; + typedef typename Container::real_value_traits real_value_traits; + typedef typename Container::siterator siterator; + typedef typename Container::const_siterator const_siterator; + typedef typename Container::bucket_type bucket_type; typedef typename boost::pointer_to_other - < typename Container::pointer, const Container>::type const_cont_ptr; - typedef typename Container::size_type size_type; + < typename Container::pointer, const Container>::type const_cont_ptr; + typedef typename Container::size_type size_type; static typename Container::node_ptr downcast_bucket(typename bucket_type::node_ptr p) { return typename Container::node_ptr(&static_cast(*p)); } diff --git a/include/boost/intrusive/detail/list_node.hpp b/include/boost/intrusive/detail/list_node.hpp index a4d4505..371224e 100644 --- a/include/boost/intrusive/detail/list_node.hpp +++ b/include/boost/intrusive/detail/list_node.hpp @@ -18,7 +18,6 @@ #include #include #include -#include namespace boost { namespace intrusive { diff --git a/include/boost/intrusive/detail/parent_from_member.hpp b/include/boost/intrusive/detail/parent_from_member.hpp index c3becf1..d5fc96a 100644 --- a/include/boost/intrusive/detail/parent_from_member.hpp +++ b/include/boost/intrusive/detail/parent_from_member.hpp @@ -13,12 +13,11 @@ #define BOOST_INTRUSIVE_PARENT_FROM_MEMBER_HPP #include -#include #include #if defined(BOOST_MSVC) || (defined (BOOST_WINDOWS) && defined(BOOST_INTEL)) -#define BOOST_INTRUSIVE_OFFSET_FROM_PTR2MEMBER_MSVC_COMPLIANT -#include +#define BOOST_INTRUSIVE_MSVC_COMPLIANT_PTR_TO_MEMBER +#include #endif namespace boost { @@ -26,16 +25,18 @@ namespace intrusive { namespace detail { template -inline std::size_t offset_from_pointer_to_member(const Member Parent::* ptr_to_member) +inline std::ptrdiff_t offset_from_pointer_to_member(const Member Parent::* ptr_to_member) { //The implementation of a pointer to member is compiler dependent. - #if defined(BOOST_INTRUSIVE_OFFSET_FROM_PTR2MEMBER_MSVC_COMPLIANT) - //This works with gcc, msvc, ac++, ibmcpp + #if defined(BOOST_INTRUSIVE_MSVC_COMPLIANT_PTR_TO_MEMBER) + //msvc compliant compilers use their the first 32 bits as offset (even in 64 bit mode) return *(const boost::int32_t*)(void*)&ptr_to_member; - #elif defined(__GNUC__) || defined(__HP_aCC) || defined(BOOST_INTEL) || defined (__IBMCPP__) || defined (__DECCXX) + //This works with gcc, msvc, ac++, ibmcpp + #elif defined(__GNUC__) || defined(__HP_aCC) || defined(BOOST_INTEL) || \ + defined(__IBMCPP__) || defined(__DECCXX) const Parent * const parent = 0; const char *const member = reinterpret_cast(&(parent->*ptr_to_member)); - return std::size_t(member - reinterpret_cast(parent)); + return std::ptrdiff_t(member - reinterpret_cast(parent)); #else //This is the traditional C-front approach: __MWERKS__, __DMC__, __SUNPRO_CC return (*(const std::ptrdiff_t*)(void*)&ptr_to_member) - 1; @@ -60,8 +61,8 @@ inline const Parent *parent_from_member(const Member *member, const Member Paren } //namespace intrusive { } //namespace boost { -#ifdef BOOST_INTRUSIVE_OFFSET_FROM_PTR2MEMBER_MSVC_COMPLIANT -#undef BOOST_INTRUSIVE_OFFSET_FROM_PTR2MEMBER_MSVC_COMPLIANT +#ifdef BOOST_INTRUSIVE_MSVC_COMPLIANT_PTR_TO_MEMBER +#undef BOOST_INTRUSIVE_MSVC_COMPLIANT_PTR_TO_MEMBER #endif #include diff --git a/include/boost/intrusive/detail/slist_node.hpp b/include/boost/intrusive/detail/slist_node.hpp index fb516ec..8195e54 100644 --- a/include/boost/intrusive/detail/slist_node.hpp +++ b/include/boost/intrusive/detail/slist_node.hpp @@ -18,7 +18,6 @@ #include #include #include -#include namespace boost { namespace intrusive { diff --git a/include/boost/intrusive/detail/tree_algorithms.hpp b/include/boost/intrusive/detail/tree_algorithms.hpp index 3cf9786..65e673f 100644 --- a/include/boost/intrusive/detail/tree_algorithms.hpp +++ b/include/boost/intrusive/detail/tree_algorithms.hpp @@ -94,13 +94,8 @@ namespace detail { template class tree_algorithms { - /// @cond - private: - - typedef typename NodeTraits::node node; - /// @endcond - public: + typedef typename NodeTraits::node node; typedef NodeTraits node_traits; typedef typename NodeTraits::node_ptr node_ptr; typedef typename NodeTraits::const_node_ptr const_node_ptr; diff --git a/include/boost/intrusive/detail/utilities.hpp b/include/boost/intrusive/detail/utilities.hpp index 19b6628..743f329 100644 --- a/include/boost/intrusive/detail/utilities.hpp +++ b/include/boost/intrusive/detail/utilities.hpp @@ -25,6 +25,7 @@ #include #include #include +#include namespace boost { namespace intrusive { @@ -55,6 +56,24 @@ struct internal_base_hook_bool_is_true static const bool value = internal_base_hook_bool::value > sizeof(one)*2; }; +template +struct internal_any_hook_bool +{ + template + struct two_or_three {one _[2 + Add];}; + template static one test(...); + template static two_or_three + test (detail::bool_* = 0); + static const std::size_t value = sizeof(test(0)); +}; + +template +struct internal_any_hook_bool_is_true +{ + static const bool value = internal_any_hook_bool::value > sizeof(one)*2; +}; + + template struct external_value_traits_bool { diff --git a/include/boost/intrusive/hashtable.hpp b/include/boost/intrusive/hashtable.hpp index 8ae0968..2d51e79 100644 --- a/include/boost/intrusive/hashtable.hpp +++ b/include/boost/intrusive/hashtable.hpp @@ -83,9 +83,8 @@ struct get_slist_impl }; template -struct unordered_bucket_impl +struct real_from_supposed_value_traits { - /// @cond typedef typename detail::eval_if_c < detail::external_value_traits_is_true ::value @@ -93,15 +92,33 @@ struct unordered_bucket_impl , detail::identity - >::type real_value_traits; + >::type type; +}; +template +struct get_slist_impl_from_supposed_value_traits +{ + typedef typename + real_from_supposed_value_traits + < SupposedValueTraits>::type real_value_traits; typedef typename detail::get_node_traits ::type node_traits; typedef typename get_slist_impl ::type - >::type slist_impl; + >::type type; +}; + + +template +struct unordered_bucket_impl +{ + /// @cond + typedef typename + get_slist_impl_from_supposed_value_traits + ::type slist_impl; typedef detail::bucket_impl implementation_defined; + /// @endcond typedef implementation_defined type; }; @@ -109,15 +126,6 @@ template struct unordered_bucket_ptr_impl { /// @cond - - typedef typename detail::eval_if_c - < detail::external_value_traits_is_true - ::value - , detail::eval_value_traits - - , detail::identity - - >::type real_value_traits; typedef typename detail::get_node_traits ::type::node_ptr node_ptr; typedef typename unordered_bucket_impl @@ -128,36 +136,6 @@ struct unordered_bucket_ptr_impl typedef implementation_defined type; }; -} //namespace detail { - -/// @endcond - -template -struct unordered_bucket -{ - /// @cond - typedef typename ValueTraitsOrHookOption:: - template pack::value_traits supposed_value_traits; - /// @endcond - typedef typename detail::unordered_bucket_impl - ::type type; -}; - -template -struct unordered_bucket_ptr -{ - /// @cond - typedef typename ValueTraitsOrHookOption:: - template pack::value_traits supposed_value_traits; - /// @endcond - typedef typename detail::unordered_bucket_ptr_impl - ::type type; -}; - -/// @cond - -namespace detail{ - template struct store_hash_bool { @@ -275,8 +253,6 @@ struct insert_commit_data_impl std::size_t hash; }; -} //namespace detail { - template struct internal_default_uset_hook { @@ -285,6 +261,49 @@ struct internal_default_uset_hook static const bool value = sizeof(test(0)) == sizeof(detail::two); }; +} //namespace detail { + +//!This metafunction will obtain the type of a bucket +//!from the value_traits or hook option to be used with +//!a hash container. +template +struct unordered_bucket + : public detail::unordered_bucket_impl + ::value_traits + > +{}; + +//!This metafunction will obtain the type of a bucket pointer +//!from the value_traits or hook option to be used with +//!a hash container. +template +struct unordered_bucket_ptr + : public detail::unordered_bucket_ptr_impl + ::value_traits + > +{}; + +//!This metafunction will obtain the type of the default bucket traits +//!(when the user does not specify the bucket_traits<> option) from the +//!value_traits or hook option to be used with +//!a hash container. +template +struct unordered_default_bucket_traits +{ + /// @cond + typedef typename ValueTraitsOrHookOption:: + template pack::value_traits supposed_value_traits; + typedef typename detail:: + get_slist_impl_from_supposed_value_traits + ::type slist_impl; + typedef detail::bucket_traits_impl + implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + template struct get_default_uset_hook { @@ -300,6 +319,7 @@ template < class ValueTraits , class BucketTraits , bool Power2Buckets , bool CacheBegin + , bool CompareHash > struct usetopt { @@ -312,6 +332,7 @@ struct usetopt static const bool power_2_buckets = Power2Buckets; static const bool unique_keys = UniqueKeys; static const bool cache_begin = CacheBegin; + static const bool compare_hash = CompareHash; }; struct default_bucket_traits; @@ -322,7 +343,7 @@ struct uset_defaults < none , base_hook < typename detail::eval_if_c - < internal_default_uset_hook::value + < detail::internal_default_uset_hook::value , get_default_uset_hook , detail::identity >::type @@ -334,6 +355,7 @@ struct uset_defaults , bucket_traits , power_2_buckets , cache_begin + , compare_hash >::type {}; @@ -441,17 +463,21 @@ class hashtable_impl = detail::optimize_multikey_is_true::value && !unique_keys; static const bool power_2_buckets = Config::power_2_buckets; static const bool cache_begin = Config::cache_begin; + static const bool compare_hash = Config::compare_hash; /// @cond private: + //Configuration error: compare_hash<> can't be specified without store_hash<> + //See documentation for more explanations + BOOST_STATIC_ASSERT((!compare_hash || store_hash)); + typedef typename slist_impl::node_ptr slist_node_ptr; typedef typename boost::pointer_to_other ::type void_pointer; //We'll define group traits, but these won't be instantiated if //optimize_multikey is not true - typedef unordered_group_node_traits group_traits; + typedef unordered_group_adapter group_traits; typedef circular_slist_algorithms group_algorithms; - typedef detail::bool_ store_hash_t; typedef detail::bool_ optimize_multikey_t; typedef detail::bool_ cache_begin_t; @@ -831,7 +857,11 @@ class hashtable_impl if(!found_equal){ it = b.before_begin(); } - this->priv_insert_in_group(found_equal ? dcast_bucket_ptr(it.pointed_node()) : node_ptr(0), n, optimize_multikey_t()); + if(optimize_multikey){ + node_ptr first_in_group = found_equal ? + dcast_bucket_ptr(it.pointed_node()) : node_ptr(0); + this->priv_insert_in_group(first_in_group, n, optimize_multikey_t()); + } priv_insertion_update_cache(bucket_num); this->priv_size_traits().increment(); return iterator(b.insert_after(it, *n), this); @@ -1136,10 +1166,10 @@ class hashtable_impl ,KeyValueEqual equal_func, Disposer disposer) { size_type bucket_num; - std::size_t hash; + std::size_t h; siterator prev; siterator it = - this->priv_find(key, hash_func, equal_func, bucket_num, hash, prev); + this->priv_find(key, hash_func, equal_func, bucket_num, h, prev); bool success = it != priv_invalid_local_it(); size_type count(0); if(!success){ @@ -1156,7 +1186,14 @@ class hashtable_impl bucket_type &b = this->priv_buckets()[bucket_num]; for(siterator end = b.end(); it != end; ++count, ++it){ slist_node_ptr n(it.pointed_node()); - if(!equal_func(key, priv_value_from_slist_node(n))){ + const value_type &v = priv_value_from_slist_node(n); + if(compare_hash){ + std::size_t vh = this->priv_stored_hash(v, store_hash_t()); + if(h != vh || !equal_func(key, v)){ + break; + } + } + else if(!equal_func(key, v)){ break; } this->priv_size_traits().decrement(); @@ -1657,7 +1694,7 @@ class hashtable_impl BOOST_INTRUSIVE_INVARIANT_ASSERT (!power_2_buckets || (0 == (new_buckets_len & (new_buckets_len-1u)))); - size_type n = this->priv_get_cache() - this->priv_buckets(); + size_type n = priv_get_cache_bucket_num(); const bool same_buffer = old_buckets == new_buckets; //If the new bucket length is a common factor //of the old one we can avoid hash calculations. @@ -1665,8 +1702,10 @@ class hashtable_impl (power_2_buckets ||(old_buckets_len % new_buckets_len) == 0); //If we are shrinking the same bucket array and it's //is a fast shrink, just rehash the last nodes - if(same_buffer && fast_shrink){ + size_type new_first_bucket_num = new_buckets_len; + if(same_buffer && fast_shrink && (n < new_buckets_len)){ n = new_buckets_len; + new_first_bucket_num = priv_get_cache_bucket_num(); } //Anti-exception stuff: they destroy the elements if something goes wrong @@ -1696,6 +1735,8 @@ class hashtable_impl const value_type &v = priv_value_from_slist_node(i.pointed_node()); const std::size_t hash_value = this->priv_stored_hash(v, store_hash_t()); const size_type new_n = priv_hash_to_bucket(hash_value, new_buckets_len); + if(cache_begin && new_n < new_first_bucket_num) + new_first_bucket_num = new_n; siterator last = bucket_type::s_iterator_to (*priv_get_last_in_group(dcast_bucket_ptr(i.pointed_node()))); if(same_buffer && new_n == n){ @@ -1710,6 +1751,8 @@ class hashtable_impl } else{ const size_type new_n = priv_hash_to_bucket(n, new_buckets_len); + if(cache_begin && new_n < new_first_bucket_num) + new_first_bucket_num = new_n; bucket_type &new_b = new_buckets[new_n]; if(!old_bucket.empty()){ new_b.splice_after( new_b.before_begin() @@ -1723,8 +1766,8 @@ class hashtable_impl this->priv_size_traits().set_size(size_backup); this->priv_real_bucket_traits() = new_bucket_traits; priv_initialize_cache(); - priv_insertion_update_cache(size_type(0u)); - priv_erasure_update_cache(); + priv_insertion_update_cache(new_first_bucket_num); + //priv_erasure_update_cache(); rollback1.release(); rollback2.release(); } @@ -1912,16 +1955,16 @@ class hashtable_impl static node_ptr dcast_bucket_ptr(typename slist_impl::node_ptr p) { return node_ptr(&static_cast(*p)); } - std::size_t priv_stored_hash(const value_type &v, detail::true_) + std::size_t priv_stored_hash(const value_type &v, detail::true_) const { return node_traits::get_hash(this->get_real_value_traits().to_node_ptr(v)); } - std::size_t priv_stored_hash(const value_type &v, detail::false_) + std::size_t priv_stored_hash(const value_type &v, detail::false_) const { return priv_hasher()(v); } - std::size_t priv_stored_hash(slist_node_ptr n, detail::true_) + std::size_t priv_stored_hash(slist_node_ptr n, detail::true_) const { return node_traits::get_hash(dcast_bucket_ptr(n)); } - std::size_t priv_stored_hash(slist_node_ptr, detail::false_) + std::size_t priv_stored_hash(slist_node_ptr, detail::false_) const { //This code should never be reached! BOOST_INTRUSIVE_INVARIANT_ASSERT(0); @@ -2414,7 +2457,13 @@ class hashtable_impl while(it != b.end()){ const value_type &v = priv_value_from_slist_node(it.pointed_node()); - if(equal_func(key, v)){ + if(compare_hash){ + std::size_t vh = this->priv_stored_hash(v, store_hash_t()); + if(h == vh && equal_func(key, v)){ + return it; + } + } + else if(equal_func(key, v)){ return it; } if(optimize_multikey){ @@ -2470,7 +2519,15 @@ class hashtable_impl ++it; while(it != b.end()){ const value_type &v = priv_value_from_slist_node(it.pointed_node()); - if(!equal_func(key, v)){ + if(compare_hash){ + std::size_t hv = this->priv_stored_hash(v, store_hash_t()); + if(hv != h || !equal_func(key, v)){ + to_return.second = it; + bucket_number_second = bucket_number_first; + return to_return; + } + } + else if(!equal_func(key, v)){ to_return.second = it; bucket_number_second = bucket_number_first; return to_return; @@ -2505,11 +2562,12 @@ template < class T , class O3 = none, class O4 = none , class O5 = none, class O6 = none , class O7 = none, class O8 = none + , class O9 = none > struct make_hashtable_opt { typedef typename pack_options - < uset_defaults, O1, O2, O3, O4, O5, O6, O7, O8>::type packed_options; + < uset_defaults, O1, O2, O3, O4, O5, O6, O7, O8, O9>::type packed_options; //Real value traits must be calculated from options typedef typename detail::get_value_traits @@ -2529,10 +2587,7 @@ struct make_hashtable_opt typedef typename detail::get_slist_impl ::type - >::type slist_impl; - - typedef typename detail::reduced_slist_node_traits - ::type node_traits; + >::type slist_impl; typedef typename detail::if_c< detail::is_same @@ -2553,6 +2608,7 @@ struct make_hashtable_opt , real_bucket_traits , packed_options::power_2_buckets , packed_options::cache_begin + , packed_options::compare_hash > type; }; /// @endcond @@ -2566,6 +2622,7 @@ template #endif struct make_hashtable @@ -2573,7 +2630,7 @@ struct make_hashtable /// @cond typedef hashtable_impl < typename make_hashtable_opt - ::type + ::type > implementation_defined; /// @endcond @@ -2581,12 +2638,12 @@ struct make_hashtable }; #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED -template +template class hashtable - : public make_hashtable::type + : public make_hashtable::type { typedef typename make_hashtable - ::type Base; + ::type Base; public: typedef typename Base::value_traits value_traits; diff --git a/include/boost/intrusive/intrusive_fwd.hpp b/include/boost/intrusive/intrusive_fwd.hpp index c260187..0642fff 100644 --- a/include/boost/intrusive/intrusive_fwd.hpp +++ b/include/boost/intrusive/intrusive_fwd.hpp @@ -294,6 +294,7 @@ template , class O6 = none , class O7 = none , class O8 = none + , class O9 = none > class hashtable; @@ -307,6 +308,7 @@ template , class O6 = none , class O7 = none , class O8 = none + , class O9 = none > class unordered_set; @@ -320,6 +322,7 @@ template , class O6 = none , class O7 = none , class O8 = none + , class O9 = none > class unordered_multiset; @@ -339,6 +342,20 @@ template > class unordered_set_member_hook; +template + < class O1 = none + , class O2 = none + , class O3 = none + > +class any_base_hook; + +template + < class O1 = none + , class O2 = none + , class O3 = none + > +class any_member_hook; + } //namespace intrusive { } //namespace boost { diff --git a/include/boost/intrusive/linear_slist_algorithms.hpp b/include/boost/intrusive/linear_slist_algorithms.hpp index 9f1f599..b52a7ba 100644 --- a/include/boost/intrusive/linear_slist_algorithms.hpp +++ b/include/boost/intrusive/linear_slist_algorithms.hpp @@ -53,6 +53,7 @@ class linear_slist_algorithms typedef detail::common_slist_algorithms base_t; /// @endcond public: + typedef typename NodeTraits::node node; typedef typename NodeTraits::node_ptr node_ptr; typedef typename NodeTraits::const_node_ptr const_node_ptr; typedef NodeTraits node_traits; diff --git a/include/boost/intrusive/options.hpp b/include/boost/intrusive/options.hpp index 2e55c58..ab9535a 100644 --- a/include/boost/intrusive/options.hpp +++ b/include/boost/intrusive/options.hpp @@ -49,15 +49,56 @@ struct eval_bucket_traits typedef typename BucketTraits::bucket_traits type; }; +template +struct concrete_hook_base_value_traits +{ + typedef typename BaseHook::boost_intrusive_tags tags; + typedef detail::base_hook_traits + < T + , typename tags::node_traits + , tags::link_mode + , typename tags::tag + , tags::hook_type> type; +}; + +template +struct concrete_hook_base_node_traits +{ typedef typename BaseHook::boost_intrusive_tags::node_traits type; }; + +template +struct any_hook_base_value_traits +{ + typedef typename BaseHook::boost_intrusive_tags tags; + typedef detail::base_hook_traits + < T + , typename BaseHook::node_traits + , tags::link_mode + , typename tags::tag + , tags::hook_type> type; +}; + +template +struct any_hook_base_node_traits +{ typedef typename BaseHook::node_traits type; }; + template struct get_base_value_traits { - typedef detail::base_hook_traits - < T - , typename BaseHook::boost_intrusive_tags::node_traits - , BaseHook::boost_intrusive_tags::link_mode - , typename BaseHook::boost_intrusive_tags::tag - , BaseHook::boost_intrusive_tags::hook_type> type; + typedef typename detail::eval_if_c + < internal_any_hook_bool_is_true::value + , any_hook_base_value_traits + , concrete_hook_base_value_traits + >::type type; +}; + +template +struct get_base_node_traits +{ + typedef typename detail::eval_if_c + < internal_any_hook_bool_is_true::value + , any_hook_base_node_traits + , concrete_hook_base_node_traits + >::type type; }; template @@ -66,6 +107,12 @@ struct get_member_value_traits typedef typename MemberHook::member_value_traits type; }; +template +struct get_member_node_traits +{ + typedef typename MemberHook::member_value_traits::node_traits type; +}; + template struct get_value_traits { @@ -86,25 +133,12 @@ struct get_value_traits >::type type; }; -template -struct get_base_node_traits -{ - typedef typename BaseHook::boost_intrusive_tags::node_traits type; -}; - -template -struct get_member_node_traits -{ - typedef typename MemberHook::member_value_traits::node_traits type; -}; - template struct get_explicit_node_traits { typedef typename ValueTraits::node_traits type; }; - template struct get_node_traits { @@ -125,7 +159,6 @@ struct get_node_traits >::type type; }; - } //namespace detail{ @@ -258,7 +291,6 @@ template< typename Parent struct member_hook { /// @cond - typedef char Parent::* GenericPtrToMember; typedef detail::member_hook_traits < Parent , MemberHook @@ -272,6 +304,7 @@ struct member_hook /// @endcond }; + //!This option setter specifies that the container //!must use the specified base hook template @@ -457,6 +490,25 @@ struct cache_begin /// @endcond }; + +//!This option setter specifies if the container will compare the hash value +//!before comparing objects. This option can't be specified if store_hash<> +//!is not true. +//!This is specially helpful when we have containers with a high load factor. +//!and the comparison function is much more expensive that comparing already +//!stored hash values. +template +struct compare_hash +{ +/// @cond + template + struct pack : Base + { + static const bool compare_hash = Enabled; + }; +/// @endcond +}; + /// @cond template diff --git a/include/boost/intrusive/rbtree_algorithms.hpp b/include/boost/intrusive/rbtree_algorithms.hpp index 8699d4c..c408193 100644 --- a/include/boost/intrusive/rbtree_algorithms.hpp +++ b/include/boost/intrusive/rbtree_algorithms.hpp @@ -116,6 +116,7 @@ class rbtree_algorithms { public: typedef NodeTraits node_traits; + typedef typename NodeTraits::node node; typedef typename NodeTraits::node_ptr node_ptr; typedef typename NodeTraits::const_node_ptr const_node_ptr; typedef typename NodeTraits::color color; @@ -123,7 +124,6 @@ class rbtree_algorithms /// @cond private: - typedef typename NodeTraits::node node; typedef detail::tree_algorithms tree_algorithms; template diff --git a/include/boost/intrusive/sgtree_algorithms.hpp b/include/boost/intrusive/sgtree_algorithms.hpp index d37f5b3..18c0884 100644 --- a/include/boost/intrusive/sgtree_algorithms.hpp +++ b/include/boost/intrusive/sgtree_algorithms.hpp @@ -58,6 +58,7 @@ template class sgtree_algorithms { public: + typedef typename NodeTraits::node node; typedef NodeTraits node_traits; typedef typename NodeTraits::node_ptr node_ptr; typedef typename NodeTraits::const_node_ptr const_node_ptr; @@ -65,7 +66,6 @@ class sgtree_algorithms /// @cond private: - typedef typename NodeTraits::node node; typedef detail::tree_algorithms tree_algorithms; static node_ptr uncast(const_node_ptr ptr) diff --git a/include/boost/intrusive/splaytree_algorithms.hpp b/include/boost/intrusive/splaytree_algorithms.hpp index f42cd3c..409449f 100644 --- a/include/boost/intrusive/splaytree_algorithms.hpp +++ b/include/boost/intrusive/splaytree_algorithms.hpp @@ -130,11 +130,11 @@ class splaytree_algorithms { /// @cond private: - typedef typename NodeTraits::node node; typedef detail::tree_algorithms tree_algorithms; /// @endcond public: + typedef typename NodeTraits::node node; typedef NodeTraits node_traits; typedef typename NodeTraits::node_ptr node_ptr; typedef typename NodeTraits::const_node_ptr const_node_ptr; diff --git a/include/boost/intrusive/unordered_set.hpp b/include/boost/intrusive/unordered_set.hpp index 342e2a6..6ec56fc 100644 --- a/include/boost/intrusive/unordered_set.hpp +++ b/include/boost/intrusive/unordered_set.hpp @@ -961,6 +961,7 @@ template #endif struct make_unordered_set @@ -968,19 +969,19 @@ struct make_unordered_set /// @cond typedef unordered_set_impl < typename make_hashtable_opt - ::type + ::type > implementation_defined; /// @endcond typedef implementation_defined type; }; #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED -template +template class unordered_set - : public make_unordered_set::type + : public make_unordered_set::type { typedef typename make_unordered_set - ::type Base; + ::type Base; //Assert if passed value traits are compatible with the type BOOST_STATIC_ASSERT((detail::is_same::value)); @@ -1894,6 +1895,7 @@ template #endif struct make_unordered_multiset @@ -1901,19 +1903,19 @@ struct make_unordered_multiset /// @cond typedef unordered_multiset_impl < typename make_hashtable_opt - ::type + ::type > implementation_defined; /// @endcond typedef implementation_defined type; }; #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED -template +template class unordered_multiset - : public make_unordered_multiset::type + : public make_unordered_multiset::type { typedef typename make_unordered_multiset - ::type Base; + ::type Base; //Assert if passed value traits are compatible with the type BOOST_STATIC_ASSERT((detail::is_same::value)); diff --git a/include/boost/intrusive/unordered_set_hook.hpp b/include/boost/intrusive/unordered_set_hook.hpp index 4920534..7f6f5bd 100644 --- a/include/boost/intrusive/unordered_set_hook.hpp +++ b/include/boost/intrusive/unordered_set_hook.hpp @@ -35,7 +35,6 @@ struct unordered_node < VoidPointer , unordered_node >::type node_ptr; -// node_ptr next_; node_ptr prev_in_group_; std::size_t hash_; }; @@ -48,7 +47,6 @@ struct unordered_node < VoidPointer , unordered_node >::type node_ptr; -// node_ptr next_; node_ptr prev_in_group_; }; @@ -60,7 +58,6 @@ struct unordered_node < VoidPointer , unordered_node >::type node_ptr; -// node_ptr next_; std::size_t hash_; }; @@ -97,34 +94,26 @@ struct unordered_node_traits { n->hash_ = h; } }; -template -struct unordered_group_node_traits +template +struct unordered_group_adapter { - typedef Node node; - typedef typename boost::pointer_to_other - ::type node_ptr; - typedef typename boost::pointer_to_other - ::type const_node_ptr; + typedef typename NodeTraits::node node; + typedef typename NodeTraits::node_ptr node_ptr; + typedef typename NodeTraits::const_node_ptr const_node_ptr; static node_ptr get_next(const_node_ptr n) - { return n->prev_in_group_; } + { return NodeTraits::get_prev_in_group(n); } static void set_next(node_ptr n, node_ptr next) - { n->prev_in_group_ = next; } + { NodeTraits::set_prev_in_group(n, next); } }; template struct unordered_algorithms : public circular_slist_algorithms { - typedef circular_slist_algorithms base_type; - typedef unordered_group_node_traits - < typename boost::pointer_to_other - < typename NodeTraits::node_ptr - , void - >::type - , typename NodeTraits::node - > group_traits; + typedef circular_slist_algorithms base_type; + typedef unordered_group_adapter group_traits; typedef circular_slist_algorithms group_algorithms; static void init(typename base_type::node_ptr n)