From 2ffe6b2f8298d485b60b6d8eb4feb8111d6ff488 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Thu, 30 Jan 2014 14:22:04 +0100 Subject: [PATCH] Fixed ABI regression introduced in Boost 1.55 --- doc/intrusive.qbk | 2 + example/doc_external_value_traits.cpp | 129 ---- include/boost/intrusive/avltree.hpp | 3 +- include/boost/intrusive/bstree.hpp | 460 +++++++------- include/boost/intrusive/bstree_algorithms.hpp | 13 + .../boost/intrusive/detail/hashtable_node.hpp | 32 +- include/boost/intrusive/detail/utilities.hpp | 6 +- include/boost/intrusive/hashtable.hpp | 584 +++++++++--------- include/boost/intrusive/list.hpp | 121 ++-- include/boost/intrusive/options.hpp | 21 - include/boost/intrusive/priority_compare.hpp | 6 +- include/boost/intrusive/rbtree.hpp | 3 +- include/boost/intrusive/sgtree.hpp | 52 +- include/boost/intrusive/slist.hpp | 121 ++-- include/boost/intrusive/splaytree.hpp | 10 +- include/boost/intrusive/treap.hpp | 92 ++- include/boost/intrusive/treap_set.hpp | 1 + include/boost/intrusive/unordered_set.hpp | 12 +- proj/vc7ide/Intrusive.sln | 16 +- .../vc7ide/_intrusivelib/_intrusivelib.vcproj | 3 - .../container_size_test.vcproj} | 21 +- test/container_size_test.cpp | 187 ++++++ test/external_value_traits_test.cpp | 241 -------- 23 files changed, 971 insertions(+), 1165 deletions(-) delete mode 100644 example/doc_external_value_traits.cpp rename proj/vc7ide/{external_value_traits/external_value_traits.vcproj => container_size_test/container_size_test.vcproj} (82%) create mode 100644 test/container_size_test.cpp delete mode 100644 test/external_value_traits_test.cpp diff --git a/doc/intrusive.qbk b/doc/intrusive.qbk index adc047b..f1dba96 100644 --- a/doc/intrusive.qbk +++ b/doc/intrusive.qbk @@ -3788,6 +3788,8 @@ to be inserted in intrusive containers are allocated using `std::vector` or `std * Improved Doxygen generated reference and updated and fixed forward-declaration header. +* [*ABI breaking]: Fixed ABI regression introduced in Boost 1.55 version, mainly noticeable on MSVC compilers. + * [*Source breaking]: Removed previously deprecated `xxx_dont_splay` functions from splay containers, `splay_set_base_hook` and `splay_set_member_hook`from splay containers and `bool splay = true` extra parameter is `splaytree_algorithms` functions. diff --git a/example/doc_external_value_traits.cpp b/example/doc_external_value_traits.cpp deleted file mode 100644 index c8ec1ce..0000000 --- a/example/doc_external_value_traits.cpp +++ /dev/null @@ -1,129 +0,0 @@ -///////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2007-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. -// -///////////////////////////////////////////////////////////////////////////// -//[doc_external_value_traits -#include -#include - -using namespace boost::intrusive; - -//This type is not modifiable so we can't store hooks or custom nodes -typedef int identifier_t; - -//This value traits will associate elements from an array of identifiers with -//elements of an array of nodes. The element i of the value array will use the -//node i of the node array: -class external_traits -{ - //Non-copyable - external_traits(const external_traits &); - external_traits& operator=(const external_traits &); - - public: - typedef list_node_traits node_traits; - typedef node_traits::node node; - typedef node * node_ptr; - typedef const node * const_node_ptr; - typedef identifier_t value_type; - typedef identifier_t * pointer; - typedef const identifier_t * const_pointer; - static const link_mode_type link_mode = normal_link; - - external_traits(pointer ids, std::size_t NumElements) - : ids_(ids), nodes_(NumElements) - {} - - ///Note: non static functions! - node_ptr to_node_ptr (value_type &value) - { return &this->nodes_[0] + (&value - this->ids_); } - const_node_ptr to_node_ptr (const value_type &value) const - { return &this->nodes_[0] + (&value - this->ids_); } - pointer to_value_ptr(node_ptr n) - { return this->ids_ + (n - &this->nodes_[0]); } - const_pointer to_value_ptr(const_node_ptr n) const - { return this->ids_ + (n - &this->nodes_[0]); } - - private: - pointer ids_; - //This is an array of nodes that is necessary to form the linked list - std::vector::node> nodes_; -}; - -//This is the value traits class that will be stored in the container -//and that will lead to the external traits using the address -//of the container. -struct internal_traits -{ - static const bool external_value_traits = true; - typedef external_traits value_traits; - - template - value_traits &get_value_traits(Container &cont); - - template - const value_traits &get_value_traits(const Container &cont) const; -}; - -//The intrusive list that will use external value traits -typedef list > List; - -class data_holder - : public List -{ - public: - data_holder(identifier_t *ids, std::size_t NumElements) - : List() - , external_traits_(ids, NumElements) - {} - external_traits external_traits_; -}; - -template -internal_traits::value_traits &internal_traits::get_value_traits(Container &cont) -{ return static_cast(cont).external_traits_; } - -template -const internal_traits::value_traits &internal_traits::get_value_traits(const Container &cont) const -{ return static_cast(cont).external_traits_; } - -int main() -{ - const int NumElements = 100; - - //This is an array of ids that we want to "store" - identifier_t ids [NumElements]; - - //Initialize id objects, each one with a different number - for(int i = 0; i != NumElements; ++i) ids[i] = i; - - //The data holding the list and the external traits - data_holder data(ids, NumElements); - - //This list will store ids without modifying identifier_t instances - //Stateful value traits must be explicitly passed in the constructor. - List &my_list = data; - - //Insert ids in reverse order in the list - for(identifier_t * it(&ids[0]), *itend(&ids[NumElements]); it != itend; ++it) - my_list.push_front(*it); - - //Now test lists - List::const_iterator list_it (my_list.cbegin()); - identifier_t *it_val(&ids[NumElements]-1), *it_rbeg_val(&ids[0] -1); - - //Test the objects inserted in the base hook list - for(; it_val != it_rbeg_val; --it_val, ++list_it){ - if(&*list_it != &*it_val) return 1; - } - - return 0; -} -//] diff --git a/include/boost/intrusive/avltree.hpp b/include/boost/intrusive/avltree.hpp index e87de01..7a53b39 100644 --- a/include/boost/intrusive/avltree.hpp +++ b/include/boost/intrusive/avltree.hpp @@ -487,14 +487,13 @@ class avltree public: typedef typename Base::value_compare value_compare; typedef typename Base::value_traits value_traits; - typedef typename Base::real_value_traits real_value_traits; typedef typename Base::iterator iterator; typedef typename Base::const_iterator const_iterator; typedef typename Base::reverse_iterator reverse_iterator; typedef typename Base::const_reverse_iterator const_reverse_iterator; //Assert if passed value traits are compatible with the type - BOOST_STATIC_ASSERT((detail::is_same::value)); + BOOST_STATIC_ASSERT((detail::is_same::value)); explicit avltree( const value_compare &cmp = value_compare() , const value_traits &v_traits = value_traits()) diff --git a/include/boost/intrusive/bstree.hpp b/include/boost/intrusive/bstree.hpp index 19b50de..c0cf6b3 100644 --- a/include/boost/intrusive/bstree.hpp +++ b/include/boost/intrusive/bstree.hpp @@ -34,6 +34,7 @@ #include #include #include +#include #include namespace boost { @@ -53,91 +54,93 @@ struct bstree_defaults template struct bstbase3 - : public detail::get_real_value_traits::type::node_traits::node - , public ValueTraits { typedef ValueTraits value_traits; - typedef typename detail::get_real_value_traits::type real_value_traits; - typedef typename real_value_traits::node_traits node_traits; + typedef typename value_traits::node_traits node_traits; typedef typename node_traits::node node_type; typedef typename get_algo::type node_algorithms; typedef typename node_traits::node_ptr node_ptr; typedef typename node_traits::const_node_ptr const_node_ptr; - bstbase3(const ValueTraits &vtraits) - : ValueTraits(vtraits) - {} + struct holder_t : public ValueTraits + { + explicit holder_t(const ValueTraits &vtraits) + : ValueTraits(vtraits) + {} + node_type root; + } holder; - static const bool external_value_traits = - detail::external_value_traits_bool_is_true::value; + static bstbase3 &get_tree_base_from_root(node_type &root) + { + holder_t *holder = get_parent_from_member(&root, &holder_t::root); + bstbase3 *base = get_parent_from_member (holder, &bstbase3::holder); + return *base; + } + + bstbase3(const ValueTraits &vtraits) + : holder(vtraits) + { + node_algorithms::init_header(this->header_ptr()); + } node_ptr header_ptr() - { return pointer_traits::pointer_to(static_cast(*this)); } + { return pointer_traits::pointer_to(this->holder.root); } const_node_ptr header_ptr() const - { return pointer_traits::pointer_to(static_cast(*this)); } + { return pointer_traits::pointer_to(this->holder.root); } - const value_traits &val_traits() const - { return *this; } + const value_traits &get_value_traits() const + { return this->holder; } - value_traits &val_traits() - { return *this; } + value_traits &get_value_traits() + { return this->holder; } - const real_value_traits &get_real_value_traits(detail::bool_) const - { return *this; } + typedef typename pointer_traits::template + rebind_pointer::type const_value_traits_ptr; - const real_value_traits &get_real_value_traits(detail::bool_) const - { return this->val_traits().get_value_traits(*this); } + const_value_traits_ptr value_traits_ptr() const + { return pointer_traits::pointer_to(this->get_value_traits()); } - real_value_traits &get_real_value_traits(detail::bool_) - { return *this; } - - real_value_traits &get_real_value_traits(detail::bool_) - { return this->val_traits().get_value_traits(*this); } - - const real_value_traits &get_real_value_traits() const - { return this->get_real_value_traits(detail::bool_()); } - - real_value_traits &get_real_value_traits() - { return this->get_real_value_traits(detail::bool_()); } - - typedef typename pointer_traits::template rebind_pointer::type const_real_value_traits_ptr; - - const_real_value_traits_ptr real_value_traits_ptr() const - { return pointer_traits::pointer_to(this->get_real_value_traits()); } - - - typedef tree_iterator iterator; - typedef tree_iterator const_iterator; + typedef tree_iterator iterator; + typedef tree_iterator const_iterator; typedef boost::intrusive::detail::reverse_iterator reverse_iterator; typedef boost::intrusive::detail::reverse_iterator const_reverse_iterator; - typedef BOOST_INTRUSIVE_IMPDEF(typename real_value_traits::pointer) pointer; - typedef BOOST_INTRUSIVE_IMPDEF(typename real_value_traits::const_pointer) const_pointer; + typedef BOOST_INTRUSIVE_IMPDEF(typename value_traits::pointer) pointer; + typedef BOOST_INTRUSIVE_IMPDEF(typename value_traits::const_pointer) const_pointer; typedef BOOST_INTRUSIVE_IMPDEF(typename pointer_traits::element_type) value_type; typedef BOOST_INTRUSIVE_IMPDEF(value_type) key_type; typedef BOOST_INTRUSIVE_IMPDEF(typename pointer_traits::reference) reference; typedef BOOST_INTRUSIVE_IMPDEF(typename pointer_traits::reference) const_reference; typedef BOOST_INTRUSIVE_IMPDEF(typename pointer_traits::difference_type) difference_type; - static const bool safemode_or_autounlink = is_safe_autounlink::value; - static const bool stateful_value_traits = detail::is_stateful_value_traits::value; + static const bool safemode_or_autounlink = is_safe_autounlink::value; + static const bool stateful_value_traits = detail::is_stateful_value_traits::value; iterator begin() - { return iterator (node_traits::get_left(this->header_ptr()), this->real_value_traits_ptr()); } + { return iterator(node_algorithms::begin_node(this->header_ptr()), this->value_traits_ptr()); } const_iterator begin() const { return cbegin(); } const_iterator cbegin() const - { return const_iterator (node_traits::get_left(this->header_ptr()), this->real_value_traits_ptr()); } + { return const_iterator(node_algorithms::begin_node(this->header_ptr()), this->value_traits_ptr()); } iterator end() - { return iterator (this->header_ptr(), this->real_value_traits_ptr()); } + { return iterator(node_algorithms::end_node(this->header_ptr()), this->value_traits_ptr()); } const_iterator end() const { return cend(); } const_iterator cend() const - { return const_iterator (detail::uncast(this->header_ptr()), this->real_value_traits_ptr()); } + { return const_iterator(node_algorithms::end_node(this->header_ptr()), this->value_traits_ptr()); } + + iterator root() + { return iterator(node_algorithms::root_node(this->header_ptr()), this->value_traits_ptr()); } + + const_iterator root() const + { return croot(); } + + const_iterator croot() const + { return const_iterator(node_algorithms::root_node(this->header_ptr()), this->value_traits_ptr()); } reverse_iterator rbegin() { return reverse_iterator(end()); } @@ -159,9 +162,9 @@ struct bstbase3 void replace_node(iterator replace_this, reference with_this) { - node_algorithms::replace_node( get_real_value_traits().to_node_ptr(*replace_this) + node_algorithms::replace_node( get_value_traits().to_node_ptr(*replace_this) , this->header_ptr() - , get_real_value_traits().to_node_ptr(with_this)); + , get_value_traits().to_node_ptr(with_this)); if(safemode_or_autounlink) node_algorithms::init(replace_this.pointed_node()); } @@ -170,25 +173,25 @@ struct bstbase3 { node_algorithms::rebalance(this->header_ptr()); } iterator rebalance_subtree(iterator root) - { return iterator(node_algorithms::rebalance_subtree(root.pointed_node()), this->real_value_traits_ptr()); } + { return iterator(node_algorithms::rebalance_subtree(root.pointed_node()), this->value_traits_ptr()); } static iterator s_iterator_to(reference value) { BOOST_STATIC_ASSERT((!stateful_value_traits)); - return iterator (value_traits::to_node_ptr(value), const_real_value_traits_ptr()); + return iterator (value_traits::to_node_ptr(value), const_value_traits_ptr()); } static const_iterator s_iterator_to(const_reference value) { BOOST_STATIC_ASSERT((!stateful_value_traits)); - return const_iterator (value_traits::to_node_ptr(const_cast (value)), const_real_value_traits_ptr()); + return const_iterator (value_traits::to_node_ptr(const_cast (value)), const_value_traits_ptr()); } iterator iterator_to(reference value) - { return iterator (value_traits::to_node_ptr(value), this->real_value_traits_ptr()); } + { return iterator (value_traits::to_node_ptr(value), this->value_traits_ptr()); } const_iterator iterator_to(const_reference value) const - { return const_iterator (value_traits::to_node_ptr(const_cast (value)), this->real_value_traits_ptr()); } + { return const_iterator (value_traits::to_node_ptr(const_cast (value)), this->value_traits_ptr()); } static void init_node(reference value) { node_algorithms::init(value_traits::to_node_ptr(value)); } @@ -197,16 +200,17 @@ struct bstbase3 template struct bstbase2 - : public bstbase3 - , public detail::ebo_functor_holder::type::value_type + //Put the (possibly empty) functor in the first position to get EBO in MSVC + : public detail::ebo_functor_holder::type> + , public bstbase3 { typedef bstbase3 treeheader_t; - typedef typename treeheader_t::real_value_traits real_value_traits; + typedef typename treeheader_t::value_traits value_traits; typedef typename treeheader_t::node_algorithms node_algorithms; typedef typename get_less - < VoidOrKeyComp, typename real_value_traits::value_type>::type value_compare; + < VoidOrKeyComp, typename value_traits::value_type>::type value_compare; typedef BOOST_INTRUSIVE_IMPDEF(value_compare) key_compare; typedef typename treeheader_t::iterator iterator; typedef typename treeheader_t::const_iterator const_iterator; @@ -214,7 +218,7 @@ struct bstbase2 typedef typename treeheader_t::const_node_ptr const_node_ptr; bstbase2(const value_compare &comp, const ValueTraits &vtraits) - : treeheader_t(vtraits), detail::ebo_functor_holder(comp) + : detail::ebo_functor_holder(comp), treeheader_t(vtraits) {} const value_compare &comp() const @@ -223,8 +227,8 @@ struct bstbase2 value_compare &comp() { return this->get(); } - typedef BOOST_INTRUSIVE_IMPDEF(typename real_value_traits::pointer) pointer; - typedef BOOST_INTRUSIVE_IMPDEF(typename real_value_traits::const_pointer) const_pointer; + typedef BOOST_INTRUSIVE_IMPDEF(typename value_traits::pointer) pointer; + typedef BOOST_INTRUSIVE_IMPDEF(typename value_traits::const_pointer) const_pointer; typedef BOOST_INTRUSIVE_IMPDEF(typename pointer_traits::element_type) value_type; typedef BOOST_INTRUSIVE_IMPDEF(value_type) key_type; typedef BOOST_INTRUSIVE_IMPDEF(typename pointer_traits::reference) reference; @@ -248,19 +252,19 @@ struct bstbase2 template iterator lower_bound(const KeyType &key, KeyValueCompare comp) { - detail::key_nodeptr_comp - key_node_comp(comp, &this->get_real_value_traits()); + detail::key_nodeptr_comp + key_node_comp(comp, &this->get_value_traits()); return iterator(node_algorithms::lower_bound - (this->header_ptr(), key, key_node_comp), this->real_value_traits_ptr()); + (this->header_ptr(), key, key_node_comp), this->value_traits_ptr()); } template const_iterator lower_bound(const KeyType &key, KeyValueCompare comp) const { - detail::key_nodeptr_comp - key_node_comp(comp, &this->get_real_value_traits()); + detail::key_nodeptr_comp + key_node_comp(comp, &this->get_value_traits()); return const_iterator(node_algorithms::lower_bound - (this->header_ptr(), key, key_node_comp), this->real_value_traits_ptr()); + (this->header_ptr(), key, key_node_comp), this->value_traits_ptr()); } //upper_bound @@ -270,10 +274,10 @@ struct bstbase2 template iterator upper_bound(const KeyType &key, KeyValueCompare comp) { - detail::key_nodeptr_comp - key_node_comp(comp, &this->get_real_value_traits()); + detail::key_nodeptr_comp + key_node_comp(comp, &this->get_value_traits()); return iterator(node_algorithms::upper_bound - (this->header_ptr(), key, key_node_comp), this->real_value_traits_ptr()); + (this->header_ptr(), key, key_node_comp), this->value_traits_ptr()); } const_iterator upper_bound(const_reference value) const @@ -282,10 +286,10 @@ struct bstbase2 template const_iterator upper_bound(const KeyType &key, KeyValueCompare comp) const { - detail::key_nodeptr_comp - key_node_comp(comp, &this->get_real_value_traits()); + detail::key_nodeptr_comp + key_node_comp(comp, &this->get_value_traits()); return const_iterator(node_algorithms::upper_bound - (this->header_ptr(), key, key_node_comp), this->real_value_traits_ptr()); + (this->header_ptr(), key, key_node_comp), this->value_traits_ptr()); } //find @@ -295,10 +299,10 @@ struct bstbase2 template iterator find(const KeyType &key, KeyValueCompare comp) { - detail::key_nodeptr_comp - key_node_comp(comp, &this->get_real_value_traits()); + detail::key_nodeptr_comp + key_node_comp(comp, &this->get_value_traits()); return iterator - (node_algorithms::find(this->header_ptr(), key, key_node_comp), this->real_value_traits_ptr()); + (node_algorithms::find(this->header_ptr(), key, key_node_comp), this->value_traits_ptr()); } const_iterator find(const_reference value) const @@ -307,10 +311,10 @@ struct bstbase2 template const_iterator find(const KeyType &key, KeyValueCompare comp) const { - detail::key_nodeptr_comp - key_node_comp(comp, &this->get_real_value_traits()); + detail::key_nodeptr_comp + key_node_comp(comp, &this->get_value_traits()); return const_iterator - (node_algorithms::find(this->header_ptr(), key, key_node_comp), this->real_value_traits_ptr()); + (node_algorithms::find(this->header_ptr(), key, key_node_comp), this->value_traits_ptr()); } //equal_range @@ -320,12 +324,12 @@ struct bstbase2 template std::pair equal_range(const KeyType &key, KeyValueCompare comp) { - detail::key_nodeptr_comp - key_node_comp(comp, &this->get_real_value_traits()); + detail::key_nodeptr_comp + key_node_comp(comp, &this->get_value_traits()); std::pair ret (node_algorithms::equal_range(this->header_ptr(), key, key_node_comp)); - return std::pair( iterator(ret.first, this->real_value_traits_ptr()) - , iterator(ret.second, this->real_value_traits_ptr())); + return std::pair( iterator(ret.first, this->value_traits_ptr()) + , iterator(ret.second, this->value_traits_ptr())); } std::pair @@ -336,12 +340,12 @@ struct bstbase2 std::pair equal_range(const KeyType &key, KeyValueCompare comp) const { - detail::key_nodeptr_comp - key_node_comp(comp, &this->get_real_value_traits()); + detail::key_nodeptr_comp + key_node_comp(comp, &this->get_value_traits()); std::pair ret (node_algorithms::equal_range(this->header_ptr(), key, key_node_comp)); - return std::pair( const_iterator(ret.first, this->real_value_traits_ptr()) - , const_iterator(ret.second, this->real_value_traits_ptr())); + return std::pair( const_iterator(ret.first, this->value_traits_ptr()) + , const_iterator(ret.second, this->value_traits_ptr())); } //lower_bound_range @@ -351,12 +355,12 @@ struct bstbase2 template std::pair lower_bound_range(const KeyType &key, KeyValueCompare comp) { - detail::key_nodeptr_comp - key_node_comp(comp, &this->get_real_value_traits()); + detail::key_nodeptr_comp + key_node_comp(comp, &this->get_value_traits()); std::pair ret (node_algorithms::lower_bound_range(this->header_ptr(), key, key_node_comp)); - return std::pair( iterator(ret.first, this->real_value_traits_ptr()) - , iterator(ret.second, this->real_value_traits_ptr())); + return std::pair( iterator(ret.first, this->value_traits_ptr()) + , iterator(ret.second, this->value_traits_ptr())); } std::pair @@ -367,12 +371,12 @@ struct bstbase2 std::pair lower_bound_range(const KeyType &key, KeyValueCompare comp) const { - detail::key_nodeptr_comp - key_node_comp(comp, &this->get_real_value_traits()); + detail::key_nodeptr_comp + key_node_comp(comp, &this->get_value_traits()); std::pair ret (node_algorithms::lower_bound_range(this->header_ptr(), key, key_node_comp)); - return std::pair( const_iterator(ret.first, this->real_value_traits_ptr()) - , const_iterator(ret.second, this->real_value_traits_ptr())); + return std::pair( const_iterator(ret.first, this->value_traits_ptr()) + , const_iterator(ret.second, this->value_traits_ptr())); } //bounded_range @@ -384,13 +388,13 @@ struct bstbase2 std::pair bounded_range (const KeyType &lower_key, const KeyType &upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) { - detail::key_nodeptr_comp - key_node_comp(comp, &this->get_real_value_traits()); + detail::key_nodeptr_comp + key_node_comp(comp, &this->get_value_traits()); std::pair ret (node_algorithms::bounded_range (this->header_ptr(), lower_key, upper_key, key_node_comp, left_closed, right_closed)); - return std::pair( iterator(ret.first, this->real_value_traits_ptr()) - , iterator(ret.second, this->real_value_traits_ptr())); + return std::pair( iterator(ret.first, this->value_traits_ptr()) + , iterator(ret.second, this->value_traits_ptr())); } std::pair bounded_range @@ -401,13 +405,13 @@ struct bstbase2 std::pair bounded_range (const KeyType &lower_key, const KeyType &upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const { - detail::key_nodeptr_comp - key_node_comp(comp, &this->get_real_value_traits()); + detail::key_nodeptr_comp + key_node_comp(comp, &this->get_value_traits()); std::pair ret (node_algorithms::bounded_range (this->header_ptr(), lower_key, upper_key, key_node_comp, left_closed, right_closed)); - return std::pair( const_iterator(ret.first, this->real_value_traits_ptr()) - , const_iterator(ret.second, this->real_value_traits_ptr())); + return std::pair( const_iterator(ret.first, this->value_traits_ptr()) + , const_iterator(ret.second, this->value_traits_ptr())); } //insert_unique_check @@ -415,12 +419,12 @@ struct bstbase2 std::pair insert_unique_check (const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data) { - detail::key_nodeptr_comp - ocomp(key_value_comp, &this->get_real_value_traits()); + detail::key_nodeptr_comp + ocomp(key_value_comp, &this->get_value_traits()); std::pair ret = (node_algorithms::insert_unique_check (this->header_ptr(), key, ocomp, commit_data)); - return std::pair(iterator(ret.first, this->real_value_traits_ptr()), ret.second); + return std::pair(iterator(ret.first, this->value_traits_ptr()), ret.second); } template @@ -428,76 +432,102 @@ struct bstbase2 (const_iterator hint, const KeyType &key ,KeyValueCompare key_value_comp, insert_commit_data &commit_data) { - detail::key_nodeptr_comp - ocomp(key_value_comp, &this->get_real_value_traits()); + detail::key_nodeptr_comp + ocomp(key_value_comp, &this->get_value_traits()); std::pair ret = (node_algorithms::insert_unique_check (this->header_ptr(), hint.pointed_node(), key, ocomp, commit_data)); - return std::pair(iterator(ret.first, this->real_value_traits_ptr()), ret.second); + return std::pair(iterator(ret.first, this->value_traits_ptr()), ret.second); } }; +//Due to MSVC's EBO implementation, to save space and maintain the ABI, we must put the non-empty size member +//in the first position, but if size is not going to be stored then we'll use an specialization +//that doesn't inherit from size_holder template -struct bstbase +struct bstbase_hack : public detail::size_holder , public bstbase2 < ValueTraits, VoidOrKeyComp, AlgoType> { - typedef typename detail::get_real_value_traits::type real_value_traits; typedef bstbase2< ValueTraits, VoidOrKeyComp, AlgoType> base_type; typedef typename base_type::value_compare value_compare; - typedef BOOST_INTRUSIVE_IMPDEF(value_compare) key_compare; + typedef SizeType size_type; + typedef typename base_type::node_traits node_traits; + typedef typename get_algo + ::type algo_type; + + bstbase_hack(const value_compare & comp, const ValueTraits &vtraits) + : base_type(comp, vtraits) + { + this->sz_traits().set_size(size_type(0)); + } + + typedef detail::size_holder size_traits; + + size_traits &sz_traits() + { return static_cast(*this); } + + const size_traits &sz_traits() const + { return static_cast(*this); } +}; + +//Specialization for ConstantTimeSize == false +template +struct bstbase_hack + : public bstbase2 < ValueTraits, VoidOrKeyComp, AlgoType> +{ + typedef bstbase2< ValueTraits, VoidOrKeyComp, AlgoType> base_type; + typedef typename base_type::value_compare value_compare; + bstbase_hack(const value_compare & comp, const ValueTraits &vtraits) + : base_type(comp, vtraits) + {} + + typedef detail::size_holder size_traits; + + size_traits &sz_traits() + { return s_size_traits; } + + const size_traits &sz_traits() const + { return s_size_traits; } + + static size_traits s_size_traits; +}; + +template +detail::size_holder bstbase_hack::s_size_traits; + +//This class will +template +struct bstbase + : public bstbase_hack< ValueTraits, VoidOrKeyComp, ConstantTimeSize, SizeType, AlgoType> +{ + typedef bstbase_hack< ValueTraits, VoidOrKeyComp, ConstantTimeSize, SizeType, AlgoType> base_type; + typedef ValueTraits value_traits; + typedef typename base_type::value_compare value_compare; + typedef value_compare key_compare; typedef typename base_type::const_reference const_reference; typedef typename base_type::reference reference; typedef typename base_type::iterator iterator; typedef typename base_type::const_iterator const_iterator; typedef typename base_type::node_traits node_traits; typedef typename get_algo - ::type algo_type; + ::type node_algorithms; typedef SizeType size_type; bstbase(const value_compare & comp, const ValueTraits &vtraits) : base_type(comp, vtraits) {} - public: - typedef detail::size_holder size_traits; - - size_traits &sz_traits() - { return *this; } - - const size_traits &sz_traits() const - { return *this; } - - bool empty() const + //Detach all inserted nodes. This will add exception safety to bstree_impl + //constructors inserting elements. + ~bstbase() { - if(ConstantTimeSize){ - return !this->sz_traits().get_size(); + if(is_safe_autounlink::value){ + node_algorithms::clear_and_dispose + ( this->header_ptr() + , detail::node_disposer + (detail::null_disposer(), &this->get_value_traits())); } - else{ - return algo_type::unique(this->header_ptr()); - } - } - - size_type count(const_reference value) const - { return size_type(this->count(value, this->comp())); } - - template - size_type count(const KeyType &key, KeyValueCompare comp) const - { - std::pair ret = this->equal_range(key, comp); - return size_type(std::distance(ret.first, ret.second)); - } - - //Add non-const overloads to theoretically const members - //as some algorithms have different behavior when non-const versions are used (like splay trees). - size_type count(const_reference value) - { return size_type(this->count(value, this->comp())); } - - template - size_type count(const KeyType &key, KeyValueCompare comp) - { - std::pair ret = this->equal_range(key, comp); - return size_type(std::distance(ret.first, ret.second)); } }; @@ -526,25 +556,18 @@ template - , private detail::clear_on_destructor_base - < bstree_impl - , is_safe_autounlink::type::link_mode>::value - > { template friend class detail::clear_on_destructor_base; public: - typedef ValueTraits value_traits; /// @cond - static const bool external_value_traits = - detail::external_value_traits_bool_is_true::value; - typedef typename detail::get_real_value_traits::type real_value_traits; - typedef bstbase data_type; - typedef tree_iterator iterator_type; - typedef tree_iterator const_iterator_type; + typedef bstbase data_type; + typedef tree_iterator iterator_type; + typedef tree_iterator const_iterator_type; /// @endcond - typedef BOOST_INTRUSIVE_IMPDEF(typename real_value_traits::pointer) pointer; - typedef BOOST_INTRUSIVE_IMPDEF(typename real_value_traits::const_pointer) const_pointer; + typedef BOOST_INTRUSIVE_IMPDEF(ValueTraits) value_traits; + typedef BOOST_INTRUSIVE_IMPDEF(typename value_traits::pointer) pointer; + typedef BOOST_INTRUSIVE_IMPDEF(typename value_traits::const_pointer) const_pointer; typedef BOOST_INTRUSIVE_IMPDEF(typename pointer_traits::element_type) value_type; typedef BOOST_INTRUSIVE_IMPDEF(value_type) key_type; typedef BOOST_INTRUSIVE_IMPDEF(typename pointer_traits::reference) reference; @@ -557,7 +580,7 @@ class bstree_impl typedef BOOST_INTRUSIVE_IMPDEF(const_iterator_type) const_iterator; typedef BOOST_INTRUSIVE_IMPDEF(boost::intrusive::detail::reverse_iterator) reverse_iterator; typedef BOOST_INTRUSIVE_IMPDEF(boost::intrusive::detail::reverse_iterator) const_reverse_iterator; - typedef BOOST_INTRUSIVE_IMPDEF(typename real_value_traits::node_traits) node_traits; + typedef BOOST_INTRUSIVE_IMPDEF(typename value_traits::node_traits) node_traits; typedef BOOST_INTRUSIVE_IMPDEF(typename node_traits::node) node; typedef BOOST_INTRUSIVE_IMPDEF(typename node_traits::node_ptr) node_ptr; typedef BOOST_INTRUSIVE_IMPDEF(typename node_traits::const_node_ptr) const_node_ptr; @@ -567,17 +590,17 @@ class bstree_impl typedef BOOST_INTRUSIVE_IMPDEF(algo_type) node_algorithms; static const bool constant_time_size = ConstantTimeSize; - static const bool stateful_value_traits = detail::is_stateful_value_traits::value; + static const bool stateful_value_traits = detail::is_stateful_value_traits::value; /// @cond private: //noncopyable BOOST_MOVABLE_BUT_NOT_COPYABLE(bstree_impl) - static const bool safemode_or_autounlink = is_safe_autounlink::value; + static const bool safemode_or_autounlink = is_safe_autounlink::value; //Constant-time size is incompatible with auto-unlink hooks! - BOOST_STATIC_ASSERT(!(constant_time_size && ((int)real_value_traits::link_mode == (int)auto_unlink))); + BOOST_STATIC_ASSERT(!(constant_time_size && ((int)value_traits::link_mode == (int)auto_unlink))); protected: @@ -599,10 +622,7 @@ class bstree_impl explicit bstree_impl( const value_compare &cmp = value_compare() , const value_traits &v_traits = value_traits()) : data_type(cmp, v_traits) - { - node_algorithms::init_header(this->header_ptr()); - this->sz_traits().set_size(size_type(0)); - } + {} //! Requires: Dereferencing iterator must yield an lvalue of type value_type. //! cmp must be a comparison function that induces a strict weak ordering. @@ -622,8 +642,6 @@ class bstree_impl , const value_traits &v_traits = value_traits()) : data_type(cmp, v_traits) { - node_algorithms::init_header(this->header_ptr()); - this->sz_traits().set_size(size_type(0)); if(unique) this->insert_unique(b, e); else @@ -633,10 +651,8 @@ class bstree_impl //! Effects: to-do //! bstree_impl(BOOST_RV_REF(bstree_impl) x) - : data_type(::boost::move(x.comp()), ::boost::move(x.val_traits())) + : data_type(::boost::move(x.comp()), ::boost::move(x.get_value_traits())) { - node_algorithms::init_header(this->header_ptr()); - this->sz_traits().set_size(size_type(0)); this->swap(x); } @@ -758,8 +774,8 @@ class bstree_impl //! Complexity: Constant. static bstree_impl &container_from_end_iterator(iterator end_iterator) { - return *static_cast - (boost::intrusive::detail::to_raw_pointer(end_iterator.pointed_node())); + return static_cast + (data_type::get_tree_base_from_root(*boost::intrusive::detail::to_raw_pointer(end_iterator.pointed_node()))); } //! Precondition: end_iterator must be a valid end const_iterator @@ -772,8 +788,8 @@ class bstree_impl //! Complexity: Constant. static const bstree_impl &container_from_end_iterator(const_iterator end_iterator) { - return *static_cast - (boost::intrusive::detail::to_raw_pointer(end_iterator.pointed_node())); + return static_cast + (data_type::get_tree_base_from_root(*boost::intrusive::detail::to_raw_pointer(end_iterator.pointed_node()))); } //! Precondition: it must be a valid iterator @@ -814,14 +830,22 @@ class bstree_impl //! Throws: If value_compare copy-constructor throws. value_compare value_comp() const; + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! Effects: Returns true if the container is empty. //! //! Complexity: Constant. //! //! Throws: Nothing. - bool empty() const; - - #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + bool empty() const + { + if(ConstantTimeSize){ + return !this->data_type::sz_traits().get_size(); + } + else{ + return algo_type::unique(this->header_ptr()); + } + } //! Effects: Returns the number of elements stored in the container. //! @@ -881,8 +905,8 @@ class bstree_impl node_algorithms::clone (const_node_ptr(src.header_ptr()) ,node_ptr(this->header_ptr()) - ,detail::node_cloner (cloner, &this->get_real_value_traits()) - ,detail::node_disposer(disposer, &this->get_real_value_traits())); + ,detail::node_cloner (cloner, &this->get_value_traits()) + ,detail::node_disposer(disposer, &this->get_value_traits())); this->sz_traits().set_size(src.sz_traits().get_size()); this->comp() = src.comp(); rollback.release(); @@ -902,13 +926,13 @@ class bstree_impl //! No copy-constructors are called. iterator insert_equal(reference value) { - detail::key_nodeptr_comp - key_node_comp(this->comp(), &this->get_real_value_traits()); - node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + detail::key_nodeptr_comp + key_node_comp(this->comp(), &this->get_value_traits()); + node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); iterator ret(node_algorithms::insert_equal_upper_bound - (this->header_ptr(), to_insert, key_node_comp), this->real_value_traits_ptr()); + (this->header_ptr(), to_insert, key_node_comp), this->value_traits_ptr()); this->sz_traits().increment(); return ret; } @@ -929,13 +953,13 @@ class bstree_impl //! No copy-constructors are called. iterator insert_equal(const_iterator hint, reference value) { - detail::key_nodeptr_comp - key_node_comp(this->comp(), &this->get_real_value_traits()); - node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + detail::key_nodeptr_comp + key_node_comp(this->comp(), &this->get_value_traits()); + node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); iterator ret(node_algorithms::insert_equal - (this->header_ptr(), hint.pointed_node(), to_insert, key_node_comp), this->real_value_traits_ptr()); + (this->header_ptr(), hint.pointed_node(), to_insert, key_node_comp), this->value_traits_ptr()); this->sz_traits().increment(); return ret; } @@ -1127,13 +1151,13 @@ class bstree_impl //! erased between the "insert_check" and "insert_commit" calls. iterator insert_unique_commit(reference value, const insert_commit_data &commit_data) { - node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); node_algorithms::insert_unique_commit (this->header_ptr(), to_insert, commit_data); this->sz_traits().increment(); - return iterator(to_insert, this->real_value_traits_ptr()); + return iterator(to_insert, this->value_traits_ptr()); } //! Requires: value must be an lvalue, "pos" must be @@ -1152,12 +1176,12 @@ class bstree_impl //! by advanced users. iterator insert_before(const_iterator pos, reference value) { - node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); this->sz_traits().increment(); return iterator(node_algorithms::insert_before - (this->header_ptr(), pos.pointed_node(), to_insert), this->real_value_traits_ptr()); + (this->header_ptr(), pos.pointed_node(), to_insert), this->value_traits_ptr()); } //! Requires: value must be an lvalue, and it must be no less @@ -1176,7 +1200,7 @@ class bstree_impl //! by advanced users. void push_back(reference value) { - node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); this->sz_traits().increment(); @@ -1199,7 +1223,7 @@ class bstree_impl //! by advanced users. void push_front(reference value) { - node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); this->sz_traits().increment(); @@ -1293,7 +1317,7 @@ class bstree_impl { node_ptr to_erase(i.pointed_node()); iterator ret(this->erase(i)); - disposer(this->get_real_value_traits().to_value_ptr(to_erase)); + disposer(this->get_value_traits().to_value_ptr(to_erase)); return ret; } @@ -1401,20 +1425,19 @@ class bstree_impl void clear_and_dispose(Disposer disposer) { node_algorithms::clear_and_dispose(this->header_ptr() - , detail::node_disposer(disposer, &this->get_real_value_traits())); + , detail::node_disposer(disposer, &this->get_value_traits())); node_algorithms::init_header(this->header_ptr()); this->sz_traits().set_size(0); } - #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) - //! Effects: Returns the number of contained elements with the given value //! //! Complexity: Logarithmic to the number of elements contained plus lineal //! to number of objects with the given value. //! //! Throws: If `value_compare` throws. - size_type count(const_reference value) const; + size_type count(const_reference value) const + { return size_type(this->count(value, this->comp())); } //! Effects: Returns the number of contained elements with the given key //! @@ -1423,7 +1446,27 @@ class bstree_impl //! //! Throws: If `comp` throws. template - size_type count(const KeyType &key, KeyValueCompare comp) const; + size_type count(const KeyType &key, KeyValueCompare comp) const + { + std::pair ret = this->equal_range(key, comp); + return size_type(std::distance(ret.first, ret.second)); + } + + #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + + //Add non-const overloads to theoretically const members + //as some algorithms have different behavior when non-const versions are used (like splay trees). + size_type count(const_reference value) + { return size_type(this->count(value, this->comp())); } + + template + size_type count(const KeyType &key, KeyValueCompare comp) + { + std::pair ret = this->equal_range(key, comp); + return size_type(std::distance(ret.first, ret.second)); + } + + #else //defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Effects: Returns an iterator to the first element whose //! key is not less than k or end() if that element does not exist. @@ -1741,7 +1784,7 @@ class bstree_impl this->sz_traits().decrement(); if(safemode_or_autounlink)//If this is commented does not work with normal_link node_algorithms::init(to_be_disposed); - return this->get_real_value_traits().to_value_ptr(to_be_disposed); + return this->get_value_traits().to_value_ptr(to_be_disposed); } #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) @@ -2016,12 +2059,11 @@ class bstree public: typedef typename Base::value_compare value_compare; typedef typename Base::value_traits value_traits; - typedef typename Base::real_value_traits real_value_traits; typedef typename Base::iterator iterator; typedef typename Base::const_iterator const_iterator; //Assert if passed value traits are compatible with the type - BOOST_STATIC_ASSERT((detail::is_same::value)); + BOOST_STATIC_ASSERT((detail::is_same::value)); bstree( const value_compare &cmp = value_compare() , const value_traits &v_traits = value_traits()) diff --git a/include/boost/intrusive/bstree_algorithms.hpp b/include/boost/intrusive/bstree_algorithms.hpp index d7f785f..e7f034b 100644 --- a/include/boost/intrusive/bstree_algorithms.hpp +++ b/include/boost/intrusive/bstree_algorithms.hpp @@ -173,6 +173,19 @@ class bstree_algorithms static node_ptr end_node(const const_node_ptr & header) { return detail::uncast(header); } + //! Requires: 'header' is the header node of a tree. + //! + //! Effects: Returns the root of the tree if any, header otherwise + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + static node_ptr root_node(const const_node_ptr & header) + { + node_ptr p = node_traits::get_parent(header); + return p ? p : detail::uncast(header); + } + //! Requires: 'node' is a node of the tree or a node initialized //! by init(...) or init_node. //! diff --git a/include/boost/intrusive/detail/hashtable_node.hpp b/include/boost/intrusive/detail/hashtable_node.hpp index d9a3c41..1972634 100644 --- a/include/boost/intrusive/detail/hashtable_node.hpp +++ b/include/boost/intrusive/detail/hashtable_node.hpp @@ -175,27 +175,27 @@ template class hashtable_iterator : public std::iterator < std::forward_iterator_tag - , typename BucketValueTraits::real_value_traits::value_type - , typename pointer_traits::difference_type + , typename BucketValueTraits::value_traits::value_type + , typename pointer_traits::difference_type , typename detail::add_const_if_c - ::type * + ::type * , typename detail::add_const_if_c - ::type & + ::type & > { - typedef typename BucketValueTraits::real_value_traits real_value_traits; - typedef typename BucketValueTraits::real_bucket_traits real_bucket_traits; - typedef typename real_value_traits::node_traits node_traits; + typedef typename BucketValueTraits::value_traits value_traits; + typedef typename BucketValueTraits::bucket_traits bucket_traits; + typedef typename value_traits::node_traits node_traits; typedef typename detail::get_slist_impl ::type + ::type >::type slist_impl; typedef typename slist_impl::iterator siterator; typedef typename slist_impl::const_iterator const_siterator; typedef detail::bucket_impl bucket_type; typedef typename pointer_traits - ::template rebind_pointer + ::template rebind_pointer < const BucketValueTraits >::type const_bucketvaltraits_ptr; typedef typename slist_impl::size_type size_type; @@ -207,7 +207,7 @@ class hashtable_iterator } public: - typedef typename real_value_traits::value_type value_type; + typedef typename value_traits::value_type value_type; typedef typename detail::add_const_if_c::type *pointer; typedef typename detail::add_const_if_c::type &reference; @@ -250,23 +250,23 @@ class hashtable_iterator pointer operator->() const { - return boost::intrusive::detail::to_raw_pointer(this->priv_real_value_traits().to_value_ptr + return boost::intrusive::detail::to_raw_pointer(this->priv_value_traits().to_value_ptr (downcast_bucket(slist_it_.pointed_node()))); } const const_bucketvaltraits_ptr &get_bucket_value_traits() const { return traitsptr_; } - const real_value_traits &priv_real_value_traits() const - { return traitsptr_->priv_real_value_traits(); } + const value_traits &priv_value_traits() const + { return traitsptr_->priv_value_traits(); } - const real_bucket_traits &priv_real_bucket_traits() const - { return traitsptr_->priv_real_bucket_traits(); } + const bucket_traits &priv_bucket_traits() const + { return traitsptr_->priv_bucket_traits(); } private: void increment() { - const real_bucket_traits &rbuck_traits = this->priv_real_bucket_traits(); + const bucket_traits &rbuck_traits = this->priv_bucket_traits(); bucket_type* const buckets = boost::intrusive::detail::to_raw_pointer(rbuck_traits.bucket_begin()); const size_type buckets_len = rbuck_traits.bucket_count(); diff --git a/include/boost/intrusive/detail/utilities.hpp b/include/boost/intrusive/detail/utilities.hpp index c52227c..dfb677c 100644 --- a/include/boost/intrusive/detail/utilities.hpp +++ b/include/boost/intrusive/detail/utilities.hpp @@ -89,8 +89,6 @@ struct TRAITS_PREFIX##_bool_is_true\ BOOST_INTRUSIVE_INTERNAL_STATIC_BOOL_IS_TRUE(internal_base_hook, hooktags::is_base_hook) BOOST_INTRUSIVE_INTERNAL_STATIC_BOOL_IS_TRUE(internal_any_hook, is_any_hook) -BOOST_INTRUSIVE_INTERNAL_STATIC_BOOL_IS_TRUE(external_value_traits, external_value_traits) -BOOST_INTRUSIVE_INTERNAL_STATIC_BOOL_IS_TRUE(external_bucket_traits, external_bucket_traits) BOOST_INTRUSIVE_INTERNAL_STATIC_BOOL_IS_TRUE(resizable, resizable) template @@ -163,8 +161,8 @@ struct size_holder SizeType size_; }; -template -struct size_holder +template +struct size_holder { static const bool constant_time_size = false; typedef SizeType size_type; diff --git a/include/boost/intrusive/hashtable.hpp b/include/boost/intrusive/hashtable.hpp index f4bfb85..c046095 100644 --- a/include/boost/intrusive/hashtable.hpp +++ b/include/boost/intrusive/hashtable.hpp @@ -58,10 +58,9 @@ namespace detail { template struct get_slist_impl_from_supposed_value_traits { - typedef typename detail::get_real_value_traits - ::type real_value_traits; + typedef SupposedValueTraits value_traits; typedef typename detail::get_node_traits - ::type node_traits; + ::type node_traits; typedef typename get_slist_impl ::type @@ -445,10 +444,10 @@ struct downcast_node_to_value_t { typedef detail::node_to_value base_t; typedef typename base_t::result_type result_type; - typedef RealValueTraits real_value_traits; + typedef RealValueTraits value_traits; typedef typename detail::get_slist_impl ::type + ::type >::type slist_impl; typedef typename detail::add_const_if_c ::type & first_argument_type; @@ -458,9 +457,9 @@ struct downcast_node_to_value_t typedef typename pointer_traits :: template rebind_pointer - ::type const_real_value_traits_ptr; + ::type const_value_traits_ptr; - downcast_node_to_value_t(const const_real_value_traits_ptr &ptr) + downcast_node_to_value_t(const const_value_traits_ptr &ptr) : base_t(ptr) {} @@ -497,30 +496,42 @@ static const std::size_t hashtable_data_bool_flags_mask = | hash_bool_flags::incremental_pos ); +//bucket_plus_vtraits stores ValueTraits + BucketTraits +//this data is needed by iterators to obtain the +//value from the iterator and detect the bucket template struct bucket_plus_vtraits : public ValueTraits { typedef BucketTraits bucket_traits; typedef ValueTraits value_traits; - static const bool external_value_traits = - detail::external_value_traits_bool_is_true::value; + static const bool safemode_or_autounlink = is_safe_autounlink::value; - static const bool external_bucket_traits = - detail::external_bucket_traits_bool_is_true::value; - - typedef typename detail::get_real_value_traits::type real_value_traits; - - static const bool safemode_or_autounlink = is_safe_autounlink::value; - - typedef typename detail::eval_if_c - < external_bucket_traits - , detail::eval_bucket_traits - , detail::identity - >::type real_bucket_traits; typedef typename detail::get_slist_impl_from_supposed_value_traits - ::type slist_impl; + ::type slist_impl; + typedef typename value_traits::node_traits node_traits; + typedef unordered_group_adapter group_traits; + typedef typename slist_impl::iterator siterator; + typedef typename slist_impl::size_type size_type; + typedef detail::bucket_impl bucket_type; + typedef detail::group_functions group_functions_t; + typedef typename slist_impl::node_algorithms node_algorithms; + typedef typename slist_impl::node_ptr slist_node_ptr; + typedef typename node_traits::node_ptr node_ptr; + typedef typename node_traits::node node; + typedef typename value_traits::value_type value_type; + typedef circular_slist_algorithms group_algorithms; + typedef typename pointer_traits + :: + template rebind_pointer + ::type const_value_traits_ptr; + typedef typename pointer_traits + :: + template rebind_pointer + ::type const_bucket_value_traits_ptr; + typedef typename detail::unordered_bucket_ptr_impl + ::type bucket_ptr; template bucket_plus_vtraits(const ValueTraits &val_traits, BOOST_FWD_REF(BucketTraitsType) b_traits) @@ -528,56 +539,10 @@ struct bucket_plus_vtraits : public ValueTraits {} bucket_plus_vtraits & operator =(const bucket_plus_vtraits &x) - { - bucket_traits_ = x.bucket_traits_; - return *this; - } + { bucket_traits_ = x.bucket_traits_; return *this; } - //real_value_traits - // - const real_value_traits &priv_real_value_traits(detail::false_) const - { return *this; } - - const real_value_traits &priv_real_value_traits(detail::true_) const - { return this->get_value_traits(*this); } - - real_value_traits &priv_real_value_traits(detail::false_) - { return *this; } - - real_value_traits &priv_real_value_traits(detail::true_) - { return this->get_value_traits(*this); } - - const real_value_traits &priv_real_value_traits() const - { return this->priv_real_value_traits(detail::bool_()); } - - real_value_traits &priv_real_value_traits() - { return this->priv_real_value_traits(detail::bool_()); } - - typedef typename pointer_traits:: - template rebind_pointer::type const_real_value_traits_ptr; - - const_real_value_traits_ptr real_value_traits_ptr() const - { return pointer_traits::pointer_to(this->priv_real_value_traits()); } - - //real_bucket_traits - // - const real_bucket_traits &priv_real_bucket_traits(detail::false_) const - { return this->bucket_traits_; } - - const real_bucket_traits &priv_real_bucket_traits(detail::true_) const - { return this->bucket_traits_.get_bucket_traits(*this); } - - real_bucket_traits &priv_real_bucket_traits(detail::false_) - { return bucket_traits_; } - - real_bucket_traits &priv_real_bucket_traits(detail::true_) - { return this->get_bucket_traits(*this); } - - const real_bucket_traits &priv_real_bucket_traits() const - { return this->priv_real_bucket_traits(detail::bool_()); } - - real_bucket_traits &priv_real_bucket_traits() - { return this->priv_real_bucket_traits(detail::bool_()); } + const_value_traits_ptr value_traits_ptr() const + { return pointer_traits::pointer_to(this->priv_value_traits()); } //bucket_value_traits // @@ -587,9 +552,6 @@ struct bucket_plus_vtraits : public ValueTraits bucket_plus_vtraits &get_bucket_value_traits() { return *this; } - typedef typename pointer_traits:: - template rebind_pointer::type const_bucket_value_traits_ptr; - const_bucket_value_traits_ptr bucket_value_traits_ptr() const { return pointer_traits::pointer_to(this->get_bucket_value_traits()); } @@ -609,45 +571,21 @@ struct bucket_plus_vtraits : public ValueTraits bucket_traits &priv_bucket_traits() { return this->bucket_traits_; } - //operations - typedef typename detail::unordered_bucket_ptr_impl::type bucket_ptr; - + //bucket operations bucket_ptr priv_bucket_pointer() const - { return this->priv_real_bucket_traits().bucket_begin(); } + { return this->priv_bucket_traits().bucket_begin(); } typename slist_impl::size_type priv_bucket_count() const - { return this->priv_real_bucket_traits().bucket_count(); } + { return this->priv_bucket_traits().bucket_count(); } bucket_ptr priv_invalid_bucket() const { - const real_bucket_traits &rbt = this->priv_real_bucket_traits(); + const bucket_traits &rbt = this->priv_bucket_traits(); return rbt.bucket_begin() + rbt.bucket_count(); } - - typedef typename real_value_traits::node_traits node_traits; - typedef unordered_group_adapter group_traits; - typedef typename slist_impl::iterator siterator; - typedef typename slist_impl::size_type size_type; - typedef detail::bucket_impl bucket_type; - typedef detail::group_functions group_functions_t; - typedef typename slist_impl::node_algorithms node_algorithms; - typedef typename slist_impl::node_ptr slist_node_ptr; - typedef typename node_traits::node_ptr node_ptr; - typedef typename node_traits::node node; - typedef typename real_value_traits::value_type value_type; - typedef circular_slist_algorithms group_algorithms; - - -/* siterator priv_invalid_local_it() const - { return this->priv_invalid_bucket()->end(); } -*/ - siterator priv_invalid_local_it() const - { - return this->priv_real_bucket_traits().bucket_begin()->before_begin(); - } + { return this->priv_bucket_traits().bucket_begin()->before_begin(); } - /// static siterator priv_get_last(bucket_type &b, detail::true_) //optimize multikey { //First find the last node of p's group. @@ -731,47 +669,44 @@ struct bucket_plus_vtraits : public ValueTraits static std::size_t priv_stored_hash(slist_node_ptr n, detail::true_) //store_hash { return node_traits::get_hash(detail::dcast_bucket_ptr(n)); } - static std::size_t priv_stored_hash(slist_node_ptr, detail::false_) //NO store_hash - { - //This code should never be reached! - BOOST_INTRUSIVE_INVARIANT_ASSERT(0); - return 0; - } + static std::size_t priv_stored_hash(slist_node_ptr, detail::false_) //NO store_hash (This should never be called) + { BOOST_INTRUSIVE_INVARIANT_ASSERT(0); return 0; } node &priv_value_to_node(value_type &v) - { return *this->priv_real_value_traits().to_node_ptr(v); } + { return *this->priv_value_traits().to_node_ptr(v); } const node &priv_value_to_node(const value_type &v) const - { return *this->priv_real_value_traits().to_node_ptr(v); } + { return *this->priv_value_traits().to_node_ptr(v); } value_type &priv_value_from_slist_node(slist_node_ptr n) - { return *this->priv_real_value_traits().to_value_ptr(detail::dcast_bucket_ptr(n)); } + { return *this->priv_value_traits().to_value_ptr(detail::dcast_bucket_ptr(n)); } const value_type &priv_value_from_slist_node(slist_node_ptr n) const - { return *this->priv_real_value_traits().to_value_ptr(detail::dcast_bucket_ptr(n)); } + { return *this->priv_value_traits().to_value_ptr(detail::dcast_bucket_ptr(n)); } bucket_traits bucket_traits_; }; +//bucket_hash_t +//Stores bucket_plus_vtraits plust the hash function template struct bucket_hash_t : public detail::ebo_functor_holder ::real_value_traits::value_type + , typename bucket_plus_vtraits::value_traits::value_type >::type > - , bucket_plus_vtraits { - typedef typename bucket_plus_vtraits::real_value_traits real_value_traits; - typedef typename real_value_traits::value_type value_type; - typedef typename real_value_traits::node_traits node_traits; - typedef typename get_hash< VoidOrKeyHash, value_type>::type hasher; + typedef typename bucket_plus_vtraits::value_traits value_traits; + typedef typename value_traits::value_type value_type; + typedef typename value_traits::node_traits node_traits; + typedef typename get_hash< VoidOrKeyHash, value_type>::type hasher; typedef BucketTraits bucket_traits; typedef bucket_plus_vtraits bucket_plus_vtraits_t; template bucket_hash_t(const ValueTraits &val_traits, BOOST_FWD_REF(BucketTraitsType) b_traits, const hasher & h) - : detail::ebo_functor_holder(h), bucket_plus_vtraits_t(val_traits, ::boost::forward(b_traits)) + : detail::ebo_functor_holder(h), internal(val_traits, ::boost::forward(b_traits)) {} const hasher &priv_hasher() const @@ -781,44 +716,47 @@ struct bucket_hash_t { return this->detail::ebo_functor_holder::get(); } std::size_t priv_stored_or_compute_hash(const value_type &v, detail::true_) const //For store_hash == true - { return node_traits::get_hash(this->priv_real_value_traits().to_node_ptr(v)); } + { return node_traits::get_hash(this->internal.priv_value_traits().to_node_ptr(v)); } std::size_t priv_stored_or_compute_hash(const value_type &v, detail::false_) const //For store_hash == false { return this->priv_hasher()(v); } + + bucket_plus_vtraits_t internal; //4 }; +//bucket_hash_equal_t +//Stores bucket_hash_t and the equality function when the first +//non-empty bucket shall not be cached. template struct bucket_hash_equal_t : public detail::ebo_functor_holder //equal ::real_value_traits::value_type + , typename bucket_plus_vtraits::value_traits::value_type >::type > - , bucket_hash_t { - typedef bucket_hash_t bucket_hash_type; - typedef typename bucket_plus_vtraits::real_value_traits real_value_traits; + typedef bucket_hash_t bucket_hash_type; + typedef bucket_plus_vtraits bucket_plus_vtraits_t; + typedef typename bucket_plus_vtraits_t::value_traits value_traits; typedef typename get_equal_to< VoidOrKeyEqual - , typename real_value_traits::value_type + , typename value_traits::value_type >::type value_equal; typedef typename bucket_hash_type::hasher hasher; typedef BucketTraits bucket_traits; - typedef bucket_hash_t buckethash_t; - typedef typename bucket_hash_type::real_bucket_traits real_bucket_traits; - typedef typename bucket_hash_type::slist_impl slist_impl; - typedef typename slist_impl::size_type size_type; - typedef typename slist_impl::iterator siterator; - typedef detail::bucket_impl bucket_type; - typedef typename detail::unordered_bucket_ptr_impl::type bucket_ptr; + typedef typename bucket_plus_vtraits_t::slist_impl slist_impl; + typedef typename slist_impl::size_type size_type; + typedef typename slist_impl::iterator siterator; + typedef detail::bucket_impl bucket_type; + typedef typename detail::unordered_bucket_ptr_impl::type bucket_ptr; template bucket_hash_equal_t(const ValueTraits &val_traits, BOOST_FWD_REF(BucketTraitsType) b_traits, const hasher & h, const value_equal &e) : detail::ebo_functor_holder(e) - , buckethash_t(val_traits, ::boost::forward(b_traits), h) + , internal(val_traits, ::boost::forward(b_traits), h) {} bucket_ptr priv_get_cache() - { return this->priv_bucket_pointer(); } + { return this->internal.internal.priv_bucket_pointer(); } void priv_set_cache(const bucket_ptr &) {} @@ -835,14 +773,14 @@ struct bucket_hash_equal_t siterator priv_begin() const { size_type n = 0; - size_type bucket_cnt = this->priv_bucket_count(); + size_type bucket_cnt = this->internal.internal.priv_bucket_count(); for (n = 0; n < bucket_cnt; ++n){ - bucket_type &b = this->priv_bucket_pointer()[n]; + bucket_type &b = this->internal.internal.priv_bucket_pointer()[n]; if(!b.empty()){ return b.begin(); } } - return this->priv_invalid_local_it(); + return this->internal.internal.priv_invalid_local_it(); } void priv_insertion_update_cache(size_type) @@ -859,34 +797,41 @@ struct bucket_hash_equal_t value_equal &priv_equal() { return this->detail::ebo_functor_holder::get(); } + + bucket_hash_t internal; //3 }; +//bucket_hash_equal_t +//Stores bucket_hash_t and the equality function when the first +//non-empty bucket shall be cached. template //cache_begin == true version struct bucket_hash_equal_t : public detail::ebo_functor_holder //equal - ::real_value_traits::value_type + ::value_traits::value_type >::type - > - , public bucket_hash_t + > { - typedef bucket_hash_t bucket_hash_type; - typedef typename get_equal_to< VoidOrKeyEqual - , typename bucket_plus_vtraits::real_value_traits::value_type - >::type value_equal; - typedef typename bucket_hash_type::hasher hasher; - typedef BucketTraits bucket_traits; - typedef typename bucket_hash_type::slist_impl::size_type size_type; - typedef typename bucket_hash_type::slist_impl::iterator siterator; + typedef bucket_plus_vtraits bucket_plus_vtraits_t; + typedef bucket_hash_t bucket_hash_type; + typedef typename bucket_plus_vtraits + ::value_traits value_traits; + typedef typename get_equal_to + < VoidOrKeyEqual + , typename value_traits::value_type>::type value_equal; + typedef typename bucket_hash_type::hasher hasher; + typedef BucketTraits bucket_traits; + typedef typename bucket_plus_vtraits_t::slist_impl::size_type size_type; + typedef typename bucket_plus_vtraits_t::slist_impl::iterator siterator; template bucket_hash_equal_t(const ValueTraits &val_traits, BOOST_FWD_REF(BucketTraitsType) b_traits, const hasher & h, const value_equal &e) : detail::ebo_functor_holder(e) - , bucket_hash_type(val_traits, ::boost::forward(b_traits), h) + , internal(val_traits, ::boost::forward(b_traits), h) {} typedef typename detail::unordered_bucket_ptr_impl - ::type bucket_ptr; + ::type bucket_ptr; bucket_ptr &priv_get_cache() { return cached_begin_; } @@ -898,10 +843,10 @@ struct bucket_hash_equal_tcached_begin_ - this->priv_bucket_pointer(); } + { return this->cached_begin_ - this->internal.internal.priv_bucket_pointer(); } void priv_initialize_cache() - { this->cached_begin_ = this->priv_invalid_bucket(); } + { this->cached_begin_ = this->internal.internal.priv_invalid_bucket(); } void priv_swap_cache(bucket_hash_equal_t &other) { @@ -910,8 +855,8 @@ struct bucket_hash_equal_tcached_begin_ == this->priv_invalid_bucket()){ - return this->priv_invalid_local_it(); + if(this->cached_begin_ == this->internal.internal.priv_invalid_bucket()){ + return this->internal.internal.priv_invalid_local_it(); } else{ return this->cached_begin_->begin(); @@ -920,7 +865,7 @@ struct bucket_hash_equal_tpriv_bucket_pointer() + insertion_bucket; + bucket_ptr p = this->internal.internal.priv_bucket_pointer() + insertion_bucket; if(p < this->cached_begin_){ this->cached_begin_ = p; } @@ -937,17 +882,17 @@ struct bucket_hash_equal_tpriv_get_cache_bucket_num() == first_bucket_num && - this->priv_bucket_pointer()[first_bucket_num].empty() ){ - this->priv_set_cache(this->priv_bucket_pointer() + last_bucket_num); + this->internal.internal.priv_bucket_pointer()[first_bucket_num].empty() ){ + this->priv_set_cache(this->internal.internal.priv_bucket_pointer() + last_bucket_num); this->priv_erasure_update_cache(); } } void priv_erasure_update_cache() { - if(this->cached_begin_ != this->priv_invalid_bucket()){ - size_type current_n = this->priv_get_cache() - this->priv_bucket_pointer(); - for( const size_type num_buckets = this->priv_bucket_count() + if(this->cached_begin_ != this->internal.internal.priv_invalid_bucket()){ + size_type current_n = this->priv_get_cache() - this->internal.internal.priv_bucket_pointer(); + for( const size_type num_buckets = this->internal.internal.priv_bucket_count() ; current_n < num_buckets ; ++current_n, ++this->priv_get_cache()){ if(!this->priv_get_cache()->empty()){ @@ -958,90 +903,78 @@ struct bucket_hash_equal_t internal; //2 }; +//hashdata_internal +//Stores bucket_hash_equal_t and split_traits template struct hashdata_internal : public detail::size_holder< 0 != (BoolFlags & hash_bool_flags::incremental_pos), SizeType, int> //split_traits - , public bucket_hash_equal_t - < VoidOrKeyHash, VoidOrKeyEqual, ValueTraits, BucketTraits - , 0 != (BoolFlags & hash_bool_flags::cache_begin_pos) - > { typedef bucket_hash_equal_t - < VoidOrKeyHash, VoidOrKeyEqual, ValueTraits, BucketTraits + < VoidOrKeyHash, VoidOrKeyEqual + , ValueTraits, BucketTraits , 0 != (BoolFlags & hash_bool_flags::cache_begin_pos) - > bucket_hash_equal_type; - - typedef typename bucket_hash_equal_type::value_equal value_equal; - typedef typename bucket_hash_equal_type::hasher hasher; - typedef bucket_plus_vtraits bucket_plus_vtraits_t; - typedef typename bucket_plus_vtraits_t::size_type size_type; - typedef typename bucket_plus_vtraits_t::bucket_ptr bucket_ptr; - static const bool optimize_multikey - = detail::optimize_multikey_is_true::value; - - typedef detail::bool_ optimize_multikey_t; + > internal_type; + typedef typename internal_type::value_equal value_equal; + typedef typename internal_type::hasher hasher; + typedef bucket_plus_vtraits bucket_plus_vtraits_t; + typedef typename bucket_plus_vtraits_t::size_type size_type; + typedef typename bucket_plus_vtraits_t::bucket_ptr bucket_ptr; + typedef detail::size_holder + <0 != (BoolFlags & hash_bool_flags::incremental_pos) + , SizeType, int> split_traits; + typedef typename bucket_plus_vtraits_t:: + value_traits::node_traits node_traits; + typedef detail::bool_::value> optimize_multikey_t; template - hashdata_internal(const ValueTraits &val_traits, BOOST_FWD_REF(BucketTraitsType) b_traits, const hasher & h, const value_equal &e) - : bucket_hash_equal_type(val_traits, ::boost::forward(b_traits), h, e) + hashdata_internal( const ValueTraits &val_traits, BOOST_FWD_REF(BucketTraitsType) b_traits + , const hasher & h, const value_equal &e) + : internal(val_traits, ::boost::forward(b_traits), h, e) {} - typedef detail::size_holder - <0 != (BoolFlags & hash_bool_flags::incremental_pos), SizeType, int> split_traits; - split_traits &priv_split_traits() { return *this; } const split_traits &priv_split_traits() const { return *this; } + + internal_type internal; //2 }; +//hashtable_data_t +//Stores hashdata_internal and size_traits template struct hashtable_data_t - : public detail::size_holder< 0 != (BoolFlags & hash_bool_flags::constant_time_size_pos), SizeType> //size_traits - , public hashdata_internal - < SizeType, BoolFlags & (hash_bool_flags::incremental_pos | hash_bool_flags::cache_begin_pos) - , VoidOrKeyHash, VoidOrKeyEqual, ValueTraits, BucketTraits> + : public detail::size_holder + < 0 != (BoolFlags & hash_bool_flags::constant_time_size_pos), SizeType> //size_traits { - static const std::size_t bool_flags = BoolFlags; typedef detail::size_holder < 0 != (BoolFlags & hash_bool_flags::constant_time_size_pos) - , SizeType> size_traits; - + , SizeType> size_traits; typedef hashdata_internal - < SizeType, BoolFlags & (hash_bool_flags::incremental_pos | hash_bool_flags::cache_begin_pos) - , VoidOrKeyHash, VoidOrKeyEqual, ValueTraits, BucketTraits> internal_type; - - typedef ValueTraits value_traits; - typedef typename internal_type::value_equal value_equal; - typedef typename internal_type::hasher hasher; - typedef BucketTraits bucket_traits; + < SizeType + , BoolFlags & (hash_bool_flags::incremental_pos | hash_bool_flags::cache_begin_pos) + , VoidOrKeyHash, VoidOrKeyEqual + , ValueTraits, BucketTraits> internal_type; + typedef ValueTraits value_traits; + typedef typename internal_type::value_equal value_equal; + typedef typename internal_type::hasher hasher; + typedef BucketTraits bucket_traits; typedef bucket_plus_vtraits - bucket_plus_vtraits_t; - - static const bool external_value_traits = - detail::external_value_traits_bool_is_true::value; - static const bool external_bucket_traits = bucket_plus_vtraits_t::external_bucket_traits; - - typedef typename bucket_plus_vtraits_t::real_value_traits real_value_traits; - typedef typename bucket_plus_vtraits_t::real_bucket_traits real_bucket_traits; - - size_traits &priv_size_traits() - { return *this; } - - const size_traits &priv_size_traits() const - { return *this; } + bucket_plus_vtraits_t; template hashtable_data_t( BOOST_FWD_REF(BucketTraitsType) b_traits, const hasher & h , const value_equal &e, const value_traits &val_traits) - : size_traits() - , internal_type(val_traits, ::boost::forward(b_traits), h, e) + : internal(val_traits, ::boost::forward(b_traits), h, e) {} + + internal_type internal; //1 }; /// @endcond @@ -1088,53 +1021,45 @@ template template #endif class hashtable_impl - : public hashtable_data_t - < SizeType - , BoolFlags & hashtable_data_bool_flags_mask - , VoidOrKeyHash, VoidOrKeyEqual, ValueTraits, BucketTraits> - , private detail::clear_on_destructor_base + : private detail::clear_on_destructor_base < hashtable_impl , true //To always clear the bucket array - //is_safe_autounlink::type::link_mode>::value + //is_safe_autounlink::type::link_mode>::value > { template friend class detail::clear_on_destructor_base; - public: - typedef ValueTraits value_traits; - typedef hashtable_data_t < SizeType , BoolFlags & hashtable_data_bool_flags_mask , VoidOrKeyHash, VoidOrKeyEqual, ValueTraits, BucketTraits> data_type; + data_type data; + + public: + typedef ValueTraits value_traits; /// @cond - static const bool external_value_traits = data_type::external_value_traits; - static const bool external_bucket_traits = data_type::external_bucket_traits; - typedef BucketTraits bucket_traits; - typedef typename data_type::real_bucket_traits real_bucket_traits; - typedef typename data_type::real_value_traits real_value_traits; - typedef typename detail::get_slist_impl ::type - >::type slist_impl; - typedef bucket_plus_vtraits bucket_plus_vtraits_t; - typedef typename bucket_plus_vtraits_t::const_real_value_traits_ptr const_real_value_traits_ptr; + ::type + >::type slist_impl; + typedef bucket_plus_vtraits bucket_plus_vtraits_t; + typedef typename bucket_plus_vtraits_t::const_value_traits_ptr const_value_traits_ptr; /// @endcond - typedef typename real_value_traits::pointer pointer; - typedef typename real_value_traits::const_pointer const_pointer; - typedef typename real_value_traits::value_type value_type; + typedef typename value_traits::pointer pointer; + typedef typename value_traits::const_pointer const_pointer; + typedef typename value_traits::value_type value_type; typedef typename pointer_traits::reference reference; typedef typename pointer_traits::reference const_reference; typedef typename pointer_traits::difference_type difference_type; typedef SizeType size_type; typedef value_type key_type; typedef typename data_type::value_equal key_equal; + typedef typename data_type::value_equal value_equal; typedef typename data_type::hasher hasher; typedef detail::bucket_impl bucket_type; typedef typename pointer_traits @@ -1144,7 +1069,7 @@ class hashtable_impl typedef typename slist_impl::const_iterator const_siterator; typedef hashtable_iterator iterator; typedef hashtable_iterator const_iterator; - typedef typename real_value_traits::node_traits node_traits; + typedef typename value_traits::node_traits node_traits; typedef typename node_traits::node node; typedef typename pointer_traits ::template rebind_pointer @@ -1154,7 +1079,7 @@ class hashtable_impl < const node >::type const_node_ptr; typedef typename slist_impl::node_algorithms node_algorithms; - static const bool stateful_value_traits = detail::is_stateful_value_traits::value; + static const bool stateful_value_traits = detail::is_stateful_value_traits::value; static const bool store_hash = detail::store_hash_is_true::value; static const bool unique_keys = 0 != (BoolFlags & hash_bool_flags::unique_keys_pos); @@ -1195,22 +1120,22 @@ class hashtable_impl //noncopyable, movable BOOST_MOVABLE_BUT_NOT_COPYABLE(hashtable_impl) - static const bool safemode_or_autounlink = is_safe_autounlink::value; + static const bool safemode_or_autounlink = is_safe_autounlink::value; //Constant-time size is incompatible with auto-unlink hooks! - BOOST_STATIC_ASSERT(!(constant_time_size && ((int)real_value_traits::link_mode == (int)auto_unlink))); + BOOST_STATIC_ASSERT(!(constant_time_size && ((int)value_traits::link_mode == (int)auto_unlink))); //Cache begin is incompatible with auto-unlink hooks! - BOOST_STATIC_ASSERT(!(cache_begin && ((int)real_value_traits::link_mode == (int)auto_unlink))); + BOOST_STATIC_ASSERT(!(cache_begin && ((int)value_traits::link_mode == (int)auto_unlink))); template - node_cast_adaptor< detail::node_disposer + node_cast_adaptor< detail::node_disposer , slist_node_ptr, node_ptr > make_node_disposer(const Disposer &disposer) const { return node_cast_adaptor - < detail::node_disposer + < detail::node_disposer , slist_node_ptr, node_ptr > - (disposer, &this->priv_real_value_traits()); + (disposer, &this->priv_value_traits()); } /// @endcond @@ -1221,13 +1146,13 @@ class hashtable_impl typedef detail::transform_iterator < typename slist_impl::iterator , downcast_node_to_value_t - < real_value_traits + < value_traits , false> > local_iterator; typedef detail::transform_iterator < typename slist_impl::iterator , downcast_node_to_value_t - < real_value_traits + < value_traits , true> > const_local_iterator; public: @@ -1249,7 +1174,7 @@ class hashtable_impl , const hasher & hash_func = hasher() , const key_equal &equal_func = key_equal() , const value_traits &v_traits = value_traits()) - : data_type(b_traits, hash_func, equal_func, v_traits) + : data(b_traits, hash_func, equal_func, v_traits) { this->priv_initialize_buckets(); this->priv_size_traits().set_size(size_type(0)); @@ -1264,7 +1189,7 @@ class hashtable_impl //! Effects: to-do //! hashtable_impl(BOOST_RV_REF(hashtable_impl) x) - : data_type( ::boost::move(x.priv_bucket_traits()) + : data( ::boost::move(x.priv_bucket_traits()) , ::boost::move(x.priv_hasher()) , ::boost::move(x.priv_equal()) , ::boost::move(x.priv_value_traits()) @@ -1431,7 +1356,7 @@ class hashtable_impl { using std::swap; //These can throw - swap(this->priv_equal(), other.priv_equal()); + swap(this->priv_equal(), other.priv_equal()); swap(this->priv_hasher(), other.priv_hasher()); //These can't throw swap(this->priv_bucket_traits(), other.priv_bucket_traits()); @@ -1488,11 +1413,11 @@ class hashtable_impl const bucket_ptr dst_buckets = this->priv_bucket_pointer(); size_type constructed; - typedef node_cast_adaptor< detail::node_disposer + typedef node_cast_adaptor< detail::node_disposer , slist_node_ptr, node_ptr > NodeDisposer; - typedef node_cast_adaptor< detail::node_cloner + typedef node_cast_adaptor< detail::node_cloner , slist_node_ptr, node_ptr > NodeCloner; - NodeDisposer node_disp(disposer, &this->priv_real_value_traits()); + NodeDisposer node_disp(disposer, &this->priv_value_traits()); detail::exception_array_disposer rollback(dst_buckets[0], node_disp, constructed); @@ -1501,7 +1426,7 @@ class hashtable_impl ; ++constructed){ dst_buckets[constructed].clone_from ( src_buckets[constructed] - , NodeCloner(cloner, &this->priv_real_value_traits()), node_disp); + , NodeCloner(cloner, &this->priv_value_traits()), node_disp); } if(src_bucket_count != dst_bucket_count){ //Now insert the remaining ones using the modulo trick @@ -1514,7 +1439,7 @@ class hashtable_impl for( siterator b(src_b.begin()), e(src_b.end()) ; b != e ; ++b){ - dst_b.push_front(*(NodeCloner(cloner, &this->priv_real_value_traits())(*b.pointed_node()))); + dst_b.push_front(*(NodeCloner(cloner, &this->priv_value_traits())(*b.pointed_node()))); } } } @@ -1529,7 +1454,7 @@ class hashtable_impl else if(store_hash){ //Unlike previous cloning algorithm, this can throw //if cloner, hasher or comparison functor throw - const_iterator b(src.begin()), e(src.end()); + const_iterator b(src.cbegin()), e(src.cend()); detail::exception_disposer rollback(*this, disposer); for(; b != e; ++b){ @@ -1541,7 +1466,7 @@ class hashtable_impl else{ //Unlike previous cloning algorithm, this can throw //if cloner, hasher or comparison functor throw - const_iterator b(src.begin()), e(src.end()); + const_iterator b(src.cbegin()), e(src.cend()); detail::exception_disposer rollback(*this, disposer); for(; b != e; ++b){ @@ -2153,7 +2078,8 @@ class hashtable_impl std::pair ret = this->priv_equal_range(key, hash_func, equal_func, bucket_n1, bucket_n2, cnt); return std::pair - (const_iterator(ret.first, &this->get_bucket_value_traits()), const_iterator(ret.second, &this->get_bucket_value_traits())); + ( const_iterator(ret.first, &this->get_bucket_value_traits()) + , const_iterator(ret.second, &this->get_bucket_value_traits())); } //! Requires: value must be an lvalue and shall be in a unordered_set of @@ -2167,7 +2093,8 @@ class hashtable_impl //! Throws: If the internal hash function throws. iterator iterator_to(reference value) { - return iterator(bucket_type::s_iterator_to(this->priv_value_to_node(value)), &this->get_bucket_value_traits()); + return iterator(bucket_type::s_iterator_to + (this->priv_value_to_node(value)), &this->get_bucket_value_traits()); } //! Requires: value must be an lvalue and shall be in a unordered_set of @@ -2201,7 +2128,7 @@ class hashtable_impl { BOOST_STATIC_ASSERT((!stateful_value_traits)); siterator sit = bucket_type::s_iterator_to(((hashtable_impl*)0)->priv_value_to_node(value)); - return local_iterator(sit, const_real_value_traits_ptr()); + return local_iterator(sit, const_value_traits_ptr()); } //! Requires: value must be an lvalue and shall be in a unordered_set of @@ -2220,7 +2147,7 @@ class hashtable_impl { BOOST_STATIC_ASSERT((!stateful_value_traits)); siterator sit = bucket_type::s_iterator_to(((hashtable_impl*)0)->priv_value_to_node(const_cast(value))); - return const_local_iterator(sit, const_real_value_traits_ptr()); + return const_local_iterator(sit, const_value_traits_ptr()); } //! Requires: value must be an lvalue and shall be in a unordered_set of @@ -2235,7 +2162,7 @@ class hashtable_impl local_iterator local_iterator_to(reference value) { siterator sit = bucket_type::s_iterator_to(this->priv_value_to_node(value)); - return local_iterator(sit, this->real_value_traits_ptr()); + return local_iterator(sit, this->value_traits_ptr()); } //! Requires: value must be an lvalue and shall be in a unordered_set of @@ -2251,7 +2178,7 @@ class hashtable_impl { siterator sit = bucket_type::s_iterator_to (const_cast(this->priv_value_to_node(value))); - return const_local_iterator(sit, this->real_value_traits_ptr()); + return const_local_iterator(sit, this->value_traits_ptr()); } //! Effects: Returns the number of buckets passed in the constructor @@ -2321,7 +2248,7 @@ class hashtable_impl //! Note: [this->begin(n), this->end(n)) is a valid range //! containing all of the elements in the nth bucket. local_iterator begin(size_type n) - { return local_iterator(this->priv_bucket_pointer()[n].begin(), this->real_value_traits_ptr()); } + { return local_iterator(this->priv_bucket_pointer()[n].begin(), this->value_traits_ptr()); } //! Requires: n is in the range [0, this->bucket_count()). //! @@ -2351,7 +2278,7 @@ class hashtable_impl const_local_iterator cbegin(size_type n) const { siterator sit = const_cast(this->priv_bucket_pointer()[n]).begin(); - return const_local_iterator(sit, this->real_value_traits_ptr()); + return const_local_iterator(sit, this->value_traits_ptr()); } //! Requires: n is in the range [0, this->bucket_count()). @@ -2366,7 +2293,7 @@ class hashtable_impl //! Note: [this->begin(n), this->end(n)) is a valid range //! containing all of the elements in the nth bucket. local_iterator end(size_type n) - { return local_iterator(this->priv_bucket_pointer()[n].end(), this->real_value_traits_ptr()); } + { return local_iterator(this->priv_bucket_pointer()[n].end(), this->value_traits_ptr()); } //! Requires: n is in the range [0, this->bucket_count()). //! @@ -2396,7 +2323,7 @@ class hashtable_impl const_local_iterator cend(size_type n) const { return const_local_iterator ( const_cast(this->priv_bucket_pointer()[n]).end() - , this->real_value_traits_ptr()); + , this->value_traits_ptr()); } //! Requires: new_bucket_traits can hold a pointer to a new bucket array @@ -2503,7 +2430,7 @@ class hashtable_impl this->priv_size_traits().set_size(size_backup); this->priv_split_traits().set_size(new_bucket_count); - this->priv_real_bucket_traits() = new_bucket_traits; + this->priv_bucket_traits() = new_bucket_traits; this->priv_initialize_cache(); this->priv_insertion_update_cache(new_first_bucket_num); rollback1.release(); @@ -2616,7 +2543,7 @@ class hashtable_impl const size_type ini_n = this->priv_get_cache_bucket_num(); const bucket_ptr old_buckets = this->priv_bucket_pointer(); - this->priv_real_bucket_traits() = new_bucket_traits; + this->priv_bucket_traits() = new_bucket_traits; if(new_bucket_traits.bucket_begin() != old_buckets){ for(size_type n = ini_n; n < split_idx; ++n){ bucket_type &new_bucket = new_bucket_traits.bucket_begin()[n]; @@ -2684,6 +2611,105 @@ class hashtable_impl /// @cond private: + size_traits &priv_size_traits() + { return this->data; } + + const size_traits &priv_size_traits() const + { return this->data; } + + bucket_ptr priv_bucket_pointer() const + { return this->data.internal.internal.internal.internal.priv_bucket_pointer(); } + + SizeType priv_bucket_count() const + { return this->data.internal.internal.internal.internal.priv_bucket_count(); } + + const bucket_plus_vtraits &get_bucket_value_traits() const + { return this->data.internal.internal.internal.internal.get_bucket_value_traits(); } + + bucket_plus_vtraits &get_bucket_value_traits() + { return this->data.internal.internal.internal.internal.get_bucket_value_traits(); } + + bucket_traits &priv_bucket_traits() + { return this->data.internal.internal.internal.internal.priv_bucket_traits(); } + + const bucket_traits &priv_bucket_traits() const + { return this->data.internal.internal.internal.internal.priv_bucket_traits(); } + + value_traits &priv_value_traits() + { return this->data.internal.internal.internal.internal.priv_value_traits(); } + + const value_traits &priv_value_traits() const + { return this->data.internal.internal.internal.internal.priv_value_traits(); } + + const_value_traits_ptr value_traits_ptr() const + { return this->data.internal.internal.internal.internal.value_traits_ptr(); } + + siterator priv_invalid_local_it() const + { return this->data.internal.internal.internal.internal.priv_invalid_local_it(); } + + split_traits &priv_split_traits() + { return this->data.internal.priv_split_traits(); } + + const split_traits &priv_split_traits() const + { return this->data.internal.priv_split_traits(); } + + bucket_ptr priv_get_cache() + { return this->data.internal.internal.priv_get_cache(); } + + void priv_initialize_cache() + { return this->data.internal.internal.priv_initialize_cache(); } + + siterator priv_begin() const + { return this->data.internal.internal.priv_begin(); } + + const value_equal &priv_equal() const + { return this->data.internal.internal.priv_equal(); } + + value_equal &priv_equal() + { return this->data.internal.internal.priv_equal(); } + + const hasher &priv_hasher() const + { return this->data.internal.internal.internal.priv_hasher(); } + + hasher &priv_hasher() + { return this->data.internal.internal.internal.priv_hasher(); } + + void priv_swap_cache(hashtable_impl &h) + { this->data.internal.internal.priv_swap_cache(h.data.internal.internal); } + + node &priv_value_to_node(value_type &v) + { return this->data.internal.internal.internal.internal.priv_value_to_node(v); } + + const node &priv_value_to_node(const value_type &v) const + { return this->data.internal.internal.internal.internal.priv_value_to_node(v); } + + SizeType priv_get_cache_bucket_num() + { return this->data.internal.internal.priv_get_cache_bucket_num(); } + + void priv_insertion_update_cache(SizeType n) + { return this->data.internal.internal.priv_insertion_update_cache(n); } + + template + std::size_t priv_stored_or_compute_hash(const value_type &v, detail::bool_ b) const + { return this->data.internal.internal.internal.priv_stored_or_compute_hash(v, b); } + + value_type &priv_value_from_slist_node(slist_node_ptr n) + { return this->data.internal.internal.internal.internal.priv_value_from_slist_node(n); } + + const value_type &priv_value_from_slist_node(slist_node_ptr n) const + { return this->data.internal.internal.internal.internal.priv_value_from_slist_node(n); } + + void priv_erasure_update_cache_range(SizeType first_bucket_num, SizeType last_bucket_num) + { return this->data.internal.internal.priv_erasure_update_cache_range(first_bucket_num, last_bucket_num); } + + void priv_erasure_update_cache() + { return this->data.internal.internal.priv_erasure_update_cache(); } + + static std::size_t priv_stored_hash(slist_node_ptr n, detail::true_ true_value) + { return bucket_plus_vtraits::priv_stored_hash(n, true_value); } + + static std::size_t priv_stored_hash(slist_node_ptr n, detail::false_ false_value) + { return bucket_plus_vtraits::priv_stored_hash(n, false_value); } void priv_clear_buckets(bucket_ptr buckets_ptr, size_type bucket_cnt) { @@ -2712,7 +2738,7 @@ class hashtable_impl std::size_t priv_hash_to_bucket(std::size_t hash_value) const { return detail::hash_to_bucket_split - (hash_value, this->priv_real_bucket_traits().bucket_count(), this->priv_split_traits().get_size()); + (hash_value, this->priv_bucket_traits().bucket_count(), this->priv_split_traits().get_size()); } template @@ -2790,7 +2816,7 @@ class hashtable_impl } std::size_t priv_get_bucket_num_hash_dispatch(siterator it, detail::false_) //NO store_hash - { return this->priv_get_bucket_num_no_hash_store(it, optimize_multikey_t()); } + { return this->data.internal.internal.internal.internal.priv_get_bucket_num_no_hash_store(it, optimize_multikey_t()); } static siterator priv_get_previous(bucket_type &b, siterator i) { return bucket_plus_vtraits_t::priv_get_previous(b, i, optimize_multikey_t()); } @@ -3005,21 +3031,18 @@ template < class T #else template #endif -struct make_real_bucket_traits +struct make_bucket_traits { //Real value traits must be calculated from options typedef typename detail::get_value_traits ::type value_traits; -/* - static const bool resizable_bucket_traits = - detail::resizable_bool_is_true::value;*/ - typedef typename detail::get_real_value_traits::type real_value_traits; + typedef typename PackedOptions::bucket_traits specified_bucket_traits; //Real bucket traits must be calculated from options and calculated value_traits typedef typename detail::get_slist_impl ::type + ::type >::type slist_impl; typedef typename @@ -3060,15 +3083,15 @@ struct make_hashtable typedef typename detail::get_value_traits ::type value_traits; - typedef typename make_real_bucket_traits - ::type real_bucket_traits; + typedef typename make_bucket_traits + ::type bucket_traits; typedef hashtable_impl < value_traits , typename packed_options::hash , typename packed_options::equal , typename packed_options::size_type - , real_bucket_traits + , bucket_traits , (std::size_t(false)*hash_bool_flags::unique_keys_pos) | (std::size_t(packed_options::constant_time_size)*hash_bool_flags::constant_time_size_pos) | (std::size_t(packed_options::power_2_buckets)*hash_bool_flags::power_2_buckets_pos) @@ -3108,7 +3131,6 @@ class hashtable public: typedef typename Base::value_traits value_traits; - typedef typename Base::real_value_traits real_value_traits; typedef typename Base::iterator iterator; typedef typename Base::const_iterator const_iterator; typedef typename Base::bucket_ptr bucket_ptr; @@ -3118,7 +3140,7 @@ class hashtable typedef typename Base::key_equal key_equal; //Assert if passed value traits are compatible with the type - BOOST_STATIC_ASSERT((detail::is_same::value)); + BOOST_STATIC_ASSERT((detail::is_same::value)); explicit hashtable ( const bucket_traits &b_traits , const hasher & hash_func = hasher() diff --git a/include/boost/intrusive/list.hpp b/include/boost/intrusive/list.hpp index ce2cda5..0048a91 100644 --- a/include/boost/intrusive/list.hpp +++ b/include/boost/intrusive/list.hpp @@ -65,37 +65,32 @@ template class list_impl : private detail::clear_on_destructor_base < list_impl - , is_safe_autounlink::type::link_mode>::value + , is_safe_autounlink::value > { template friend class detail::clear_on_destructor_base; //Public typedefs public: - typedef ValueTraits value_traits; - /// @cond - static const bool external_value_traits = - detail::external_value_traits_bool_is_true::value; - typedef typename detail::get_real_value_traits::type real_value_traits; - /// @endcond - typedef typename real_value_traits::pointer pointer; - typedef typename real_value_traits::const_pointer const_pointer; + typedef ValueTraits value_traits; + typedef typename value_traits::pointer pointer; + typedef typename value_traits::const_pointer const_pointer; typedef typename pointer_traits::element_type value_type; typedef typename pointer_traits::reference reference; typedef typename pointer_traits::reference const_reference; typedef typename pointer_traits::difference_type difference_type; typedef SizeType size_type; - typedef list_iterator iterator; - typedef list_iterator const_iterator; + typedef list_iterator iterator; + typedef list_iterator const_iterator; typedef boost::intrusive::detail::reverse_iterator reverse_iterator; typedef boost::intrusive::detail::reverse_iteratorconst_reverse_iterator; - typedef typename real_value_traits::node_traits node_traits; + typedef typename value_traits::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 circular_list_algorithms node_algorithms; static const bool constant_time_size = ConstantTimeSize; - static const bool stateful_value_traits = detail::is_stateful_value_traits::value; + static const bool stateful_value_traits = detail::is_stateful_value_traits::value; /// @cond @@ -105,11 +100,11 @@ class list_impl //noncopyable BOOST_MOVABLE_BUT_NOT_COPYABLE(list_impl) - static const bool safemode_or_autounlink = is_safe_autounlink::value; + static const bool safemode_or_autounlink = is_safe_autounlink::value; //Constant-time size is incompatible with auto-unlink hooks! BOOST_STATIC_ASSERT(!(constant_time_size && - ((int)real_value_traits::link_mode == (int)auto_unlink) + ((int)value_traits::link_mode == (int)auto_unlink) )); node_ptr get_root_node() @@ -139,54 +134,27 @@ class list_impl const size_traits &priv_size_traits() const { return data_.root_plus_size_; } - const real_value_traits &get_real_value_traits(detail::bool_) const - { return data_; } - - const real_value_traits &get_real_value_traits(detail::bool_) const - { return data_.get_value_traits(*this); } - - real_value_traits &get_real_value_traits(detail::bool_) - { return data_; } - - real_value_traits &get_real_value_traits(detail::bool_) - { return data_.get_value_traits(*this); } - const value_traits &priv_value_traits() const { return data_; } value_traits &priv_value_traits() { return data_; } - protected: - node &prot_root_node() - { return data_.root_plus_size_.root_; } + typedef typename pointer_traits::template + rebind_pointer::type const_value_traits_ptr; - node const &prot_root_node() const - { return data_.root_plus_size_.root_; } - - void prot_set_size(size_type s) - { data_.root_plus_size_.set_size(s); } + const_value_traits_ptr value_traits_ptr() const + { return pointer_traits::pointer_to(this->priv_value_traits()); } /// @endcond public: - const real_value_traits &get_real_value_traits() const - { return this->get_real_value_traits(detail::bool_()); } - - real_value_traits &get_real_value_traits() - { return this->get_real_value_traits(detail::bool_()); } - - typedef typename pointer_traits::template rebind_pointer::type const_real_value_traits_ptr; - - const_real_value_traits_ptr real_value_traits_ptr() const - { return pointer_traits::pointer_to(this->get_real_value_traits()); } - //! Effects: constructs an empty list. //! //! Complexity: Constant //! - //! Throws: If real_value_traits::node_traits::node + //! Throws: If value_traits::node_traits::node //! constructor throws (this does not happen with predefined Boost.Intrusive hooks). explicit list_impl(const value_traits &v_traits = value_traits()) : data_(v_traits) @@ -201,7 +169,7 @@ class list_impl //! //! Complexity: Linear in std::distance(b, e). No copy constructors are called. //! - //! Throws: If real_value_traits::node_traits::node + //! Throws: If value_traits::node_traits::node //! constructor throws (this does not happen with predefined Boost.Intrusive hooks). template list_impl(Iterator b, Iterator e, const value_traits &v_traits = value_traits()) @@ -253,7 +221,7 @@ class list_impl //! Note: Does not affect the validity of iterators and references. void push_back(reference value) { - node_ptr to_insert = get_real_value_traits().to_node_ptr(value); + node_ptr to_insert = priv_value_traits().to_node_ptr(value); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(to_insert)); node_algorithms::link_before(this->get_root_node(), to_insert); @@ -272,7 +240,7 @@ class list_impl //! Note: Does not affect the validity of iterators and references. void push_front(reference value) { - node_ptr to_insert = get_real_value_traits().to_node_ptr(value); + node_ptr to_insert = priv_value_traits().to_node_ptr(value); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(to_insert)); node_algorithms::link_before(node_traits::get_next(this->get_root_node()), to_insert); @@ -309,7 +277,7 @@ class list_impl this->priv_size_traits().decrement(); if(safemode_or_autounlink) node_algorithms::init(to_erase); - disposer(get_real_value_traits().to_value_ptr(to_erase)); + disposer(priv_value_traits().to_value_ptr(to_erase)); } //! Effects: Erases the first element of the list. @@ -342,7 +310,7 @@ class list_impl this->priv_size_traits().decrement(); if(safemode_or_autounlink) node_algorithms::init(to_erase); - disposer(get_real_value_traits().to_value_ptr(to_erase)); + disposer(priv_value_traits().to_value_ptr(to_erase)); } //! Effects: Returns a reference to the first element of the list. @@ -351,7 +319,7 @@ class list_impl //! //! Complexity: Constant. reference front() - { return *get_real_value_traits().to_value_ptr(node_traits::get_next(this->get_root_node())); } + { return *priv_value_traits().to_value_ptr(node_traits::get_next(this->get_root_node())); } //! Effects: Returns a const_reference to the first element of the list. //! @@ -359,7 +327,7 @@ class list_impl //! //! Complexity: Constant. const_reference front() const - { return *get_real_value_traits().to_value_ptr(detail::uncast(node_traits::get_next(this->get_root_node()))); } + { return *priv_value_traits().to_value_ptr(detail::uncast(node_traits::get_next(this->get_root_node()))); } //! Effects: Returns a reference to the last element of the list. //! @@ -367,7 +335,7 @@ class list_impl //! //! Complexity: Constant. reference back() - { return *get_real_value_traits().to_value_ptr(node_traits::get_previous(this->get_root_node())); } + { return *priv_value_traits().to_value_ptr(node_traits::get_previous(this->get_root_node())); } //! Effects: Returns a const_reference to the last element of the list. //! @@ -375,7 +343,7 @@ class list_impl //! //! Complexity: Constant. const_reference back() const - { return *get_real_value_traits().to_value_ptr(detail::uncast(node_traits::get_previous(this->get_root_node()))); } + { return *priv_value_traits().to_value_ptr(detail::uncast(node_traits::get_previous(this->get_root_node()))); } //! Effects: Returns an iterator to the first element contained in the list. //! @@ -383,7 +351,7 @@ class list_impl //! //! Complexity: Constant. iterator begin() - { return iterator(node_traits::get_next(this->get_root_node()), real_value_traits_ptr()); } + { return iterator(node_traits::get_next(this->get_root_node()), value_traits_ptr()); } //! Effects: Returns a const_iterator to the first element contained in the list. //! @@ -399,7 +367,7 @@ class list_impl //! //! Complexity: Constant. const_iterator cbegin() const - { return const_iterator(node_traits::get_next(this->get_root_node()), real_value_traits_ptr()); } + { return const_iterator(node_traits::get_next(this->get_root_node()), value_traits_ptr()); } //! Effects: Returns an iterator to the end of the list. //! @@ -407,7 +375,7 @@ class list_impl //! //! Complexity: Constant. iterator end() - { return iterator(this->get_root_node(), real_value_traits_ptr()); } + { return iterator(this->get_root_node(), value_traits_ptr()); } //! Effects: Returns a const_iterator to the end of the list. //! @@ -423,7 +391,7 @@ class list_impl //! //! Complexity: Constant. const_iterator cend() const - { return const_iterator(detail::uncast(this->get_root_node()), real_value_traits_ptr()); } + { return const_iterator(detail::uncast(this->get_root_node()), value_traits_ptr()); } //! Effects: Returns a reverse_iterator pointing to the beginning //! of the reversed list. @@ -663,7 +631,7 @@ class list_impl this->priv_size_traits().decrement(); if(safemode_or_autounlink) node_algorithms::init(to_erase); - disposer(this->get_real_value_traits().to_value_ptr(to_erase)); + disposer(this->priv_value_traits().to_value_ptr(to_erase)); return i.unconst(); } @@ -697,7 +665,7 @@ class list_impl bp = node_traits::get_next(bp); if(safemode_or_autounlink) node_algorithms::init(to_erase); - disposer(get_real_value_traits().to_value_ptr(to_erase)); + disposer(priv_value_traits().to_value_ptr(to_erase)); this->priv_size_traits().decrement(); } return e.unconst(); @@ -743,7 +711,7 @@ class list_impl ++it; if(safemode_or_autounlink) node_algorithms::init(to_erase); - disposer(get_real_value_traits().to_value_ptr(to_erase)); + disposer(priv_value_traits().to_value_ptr(to_erase)); } node_algorithms::init_header(this->get_root_node()); this->priv_size_traits().set_size(0); @@ -789,12 +757,12 @@ class list_impl //! Note: Does not affect the validity of iterators and references. iterator insert(const_iterator p, reference value) { - node_ptr to_insert = this->get_real_value_traits().to_node_ptr(value); + node_ptr to_insert = this->priv_value_traits().to_node_ptr(value); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(to_insert)); node_algorithms::link_before(p.pointed_node(), to_insert); this->priv_size_traits().increment(); - return iterator(to_insert, real_value_traits_ptr()); + return iterator(to_insert, value_traits_ptr()); } //! Requires: Dereferencing iterator must yield @@ -957,7 +925,7 @@ class list_impl //! Effects: This function sorts the list *this according to std::less. //! The sort is stable, that is, the relative order of equivalent elements is preserved. //! - //! Throws: If real_value_traits::node_traits::node + //! Throws: If value_traits::node_traits::node //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) //! or std::less throws. Basic guarantee. //! @@ -973,7 +941,7 @@ class list_impl //! Effects: This function sorts the list *this according to p. The sort is //! stable, that is, the relative order of equivalent elements is preserved. //! - //! Throws: If real_value_traits::node_traits::node + //! Throws: If value_traits::node_traits::node //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) //! or the predicate throws. Basic guarantee. //! @@ -1227,8 +1195,8 @@ class list_impl static iterator s_iterator_to(reference value) { BOOST_STATIC_ASSERT((!stateful_value_traits)); - BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(real_value_traits::to_node_ptr(value))); - return iterator(real_value_traits::to_node_ptr(value), const_real_value_traits_ptr()); + BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(value_traits::to_node_ptr(value))); + return iterator(value_traits::to_node_ptr(value), const_value_traits_ptr()); } //! Requires: value must be a const reference to a value inserted in a list. @@ -1245,8 +1213,8 @@ class list_impl static const_iterator s_iterator_to(const_reference value) { BOOST_STATIC_ASSERT((!stateful_value_traits)); - BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(real_value_traits::to_node_ptr(const_cast (value)))); - return const_iterator(real_value_traits::to_node_ptr(const_cast (value)), const_real_value_traits_ptr()); + BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(value_traits::to_node_ptr(const_cast (value)))); + return const_iterator(value_traits::to_node_ptr(const_cast (value)), const_value_traits_ptr()); } //! Requires: value must be a reference to a value inserted in a list. @@ -1260,8 +1228,8 @@ class list_impl //! Note: Iterators and references are not invalidated. iterator iterator_to(reference value) { - BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(real_value_traits::to_node_ptr(value))); - return iterator(real_value_traits::to_node_ptr(value), real_value_traits_ptr()); + BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(value_traits::to_node_ptr(value))); + return iterator(value_traits::to_node_ptr(value), value_traits_ptr()); } //! Requires: value must be a const reference to a value inserted in a list. @@ -1275,8 +1243,8 @@ class list_impl //! Note: Iterators and references are not invalidated. const_iterator iterator_to(const_reference value) const { - BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(real_value_traits::to_node_ptr(const_cast (value)))); - return const_iterator(real_value_traits::to_node_ptr(const_cast (value)), real_value_traits_ptr()); + BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(value_traits::to_node_ptr(const_cast (value)))); + return const_iterator(value_traits::to_node_ptr(const_cast (value)), value_traits_ptr()); } /// @cond @@ -1468,9 +1436,8 @@ class list Options... #endif >::type Base; - typedef typename Base::real_value_traits real_value_traits; //Assert if passed value traits are compatible with the type - BOOST_STATIC_ASSERT((detail::is_same::value)); + BOOST_STATIC_ASSERT((detail::is_same::value)); BOOST_MOVABLE_BUT_NOT_COPYABLE(list) public: diff --git a/include/boost/intrusive/options.hpp b/include/boost/intrusive/options.hpp index f6854e4..7652f9a 100644 --- a/include/boost/intrusive/options.hpp +++ b/include/boost/intrusive/options.hpp @@ -51,27 +51,6 @@ BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_bstree_hook); #undef BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION -template -struct eval_value_traits -{ - typedef typename ValueTraits::value_traits type; -}; - -template -struct get_real_value_traits - : public eval_if_c - < external_value_traits_bool_is_true::value - , eval_value_traits - , identity - > -{}; - -template -struct eval_bucket_traits -{ - typedef typename BucketTraits::bucket_traits type; -}; - template struct concrete_hook_base_value_traits { diff --git a/include/boost/intrusive/priority_compare.hpp b/include/boost/intrusive/priority_compare.hpp index 026af29..f6beee1 100644 --- a/include/boost/intrusive/priority_compare.hpp +++ b/include/boost/intrusive/priority_compare.hpp @@ -23,8 +23,12 @@ namespace intrusive { template struct priority_compare - : public std::binary_function { + //Compatibility with std::binary_function + typedef T first_argument_type; + typedef T second_argument_type; + typedef bool result_type; + bool operator()(const T &val, const T &val2) const { return priority_order(val, val2); diff --git a/include/boost/intrusive/rbtree.hpp b/include/boost/intrusive/rbtree.hpp index bff85de..c4ff5f4 100644 --- a/include/boost/intrusive/rbtree.hpp +++ b/include/boost/intrusive/rbtree.hpp @@ -483,14 +483,13 @@ class rbtree public: typedef typename Base::value_compare value_compare; typedef typename Base::value_traits value_traits; - typedef typename Base::real_value_traits real_value_traits; typedef typename Base::iterator iterator; typedef typename Base::const_iterator const_iterator; typedef typename Base::reverse_iterator reverse_iterator; typedef typename Base::const_reverse_iterator const_reverse_iterator; //Assert if passed value traits are compatible with the type - BOOST_STATIC_ASSERT((detail::is_same::value)); + BOOST_STATIC_ASSERT((detail::is_same::value)); explicit rbtree( const value_compare &cmp = value_compare() , const value_traits &v_traits = value_traits()) diff --git a/include/boost/intrusive/sgtree.hpp b/include/boost/intrusive/sgtree.hpp index b28b0ae..8cb2b5c 100644 --- a/include/boost/intrusive/sgtree.hpp +++ b/include/boost/intrusive/sgtree.hpp @@ -226,7 +226,6 @@ class sgtree_impl typedef bstree_impl< ValueTraits, VoidOrKeyComp, SizeType , true, SgTreeAlgorithms> tree_type; typedef tree_type implementation_defined; - typedef typename tree_type::real_value_traits real_value_traits; /// @endcond @@ -263,11 +262,11 @@ class sgtree_impl typedef typename alpha_traits::multiply_by_alpha_t multiply_by_alpha_t; BOOST_MOVABLE_BUT_NOT_COPYABLE(sgtree_impl) - BOOST_STATIC_ASSERT(((int)real_value_traits::link_mode != (int)auto_unlink)); + BOOST_STATIC_ASSERT(((int)value_traits::link_mode != (int)auto_unlink)); enum { safemode_or_autounlink = - (int)real_value_traits::link_mode == (int)auto_unlink || - (int)real_value_traits::link_mode == (int)safe_link }; + (int)value_traits::link_mode == (int)auto_unlink || + (int)value_traits::link_mode == (int)safe_link }; /// @endcond @@ -412,9 +411,9 @@ class sgtree_impl //! @copydoc ::boost::intrusive::bstree::insert_equal(reference) iterator insert_equal(reference value) { - detail::key_nodeptr_comp - key_node_comp(this->value_comp(), &this->get_real_value_traits()); - node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + detail::key_nodeptr_comp + key_node_comp(this->value_comp(), &this->get_value_traits()); + node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); std::size_t max_tree_size = (std::size_t)this->max_tree_size_; @@ -423,15 +422,15 @@ class sgtree_impl , (size_type)this->size(), this->get_h_alpha_func(), max_tree_size); this->tree_type::sz_traits().increment(); this->max_tree_size_ = (size_type)max_tree_size; - return iterator(p, this->real_value_traits_ptr()); + return iterator(p, this->value_traits_ptr()); } //! @copydoc ::boost::intrusive::bstree::insert_equal(const_iterator,reference) iterator insert_equal(const_iterator hint, reference value) { - detail::key_nodeptr_comp - key_node_comp(this->value_comp(), &this->get_real_value_traits()); - node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + detail::key_nodeptr_comp + key_node_comp(this->value_comp(), &this->get_value_traits()); + node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); std::size_t max_tree_size = (std::size_t)this->max_tree_size_; @@ -440,7 +439,7 @@ class sgtree_impl , (std::size_t)this->size(), this->get_h_alpha_func(), max_tree_size); this->tree_type::sz_traits().increment(); this->max_tree_size_ = (size_type)max_tree_size; - return iterator(p, this->real_value_traits_ptr()); + return iterator(p, this->value_traits_ptr()); } //! @copydoc ::boost::intrusive::bstree::insert_equal(Iterator,Iterator) @@ -477,12 +476,12 @@ class sgtree_impl std::pair insert_unique_check (const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data) { - detail::key_nodeptr_comp - comp(key_value_comp, &this->get_real_value_traits()); + detail::key_nodeptr_comp + comp(key_value_comp, &this->get_value_traits()); std::pair ret = (node_algorithms::insert_unique_check (this->tree_type::header_ptr(), key, comp, commit_data)); - return std::pair(iterator(ret.first, this->real_value_traits_ptr()), ret.second); + return std::pair(iterator(ret.first, this->value_traits_ptr()), ret.second); } //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const_iterator,const KeyType&,KeyValueCompare,insert_commit_data&) @@ -491,18 +490,18 @@ class sgtree_impl (const_iterator hint, const KeyType &key ,KeyValueCompare key_value_comp, insert_commit_data &commit_data) { - detail::key_nodeptr_comp - comp(key_value_comp, &this->get_real_value_traits()); + detail::key_nodeptr_comp + comp(key_value_comp, &this->get_value_traits()); std::pair ret = (node_algorithms::insert_unique_check (this->tree_type::header_ptr(), hint.pointed_node(), key, comp, commit_data)); - return std::pair(iterator(ret.first, this->real_value_traits_ptr()), ret.second); + return std::pair(iterator(ret.first, this->value_traits_ptr()), ret.second); } //! @copydoc ::boost::intrusive::bstree::insert_unique_commit iterator insert_unique_commit(reference value, const insert_commit_data &commit_data) { - node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); std::size_t max_tree_size = (std::size_t)this->max_tree_size_; @@ -511,7 +510,7 @@ class sgtree_impl , (std::size_t)this->size(), this->get_h_alpha_func(), max_tree_size); this->tree_type::sz_traits().increment(); this->max_tree_size_ = (size_type)max_tree_size; - return iterator(to_insert, this->real_value_traits_ptr()); + return iterator(to_insert, this->value_traits_ptr()); } //! @copydoc ::boost::intrusive::bstree::insert_unique(Iterator,Iterator) @@ -532,7 +531,7 @@ class sgtree_impl //! @copydoc ::boost::intrusive::bstree::insert_before iterator insert_before(const_iterator pos, reference value) { - node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); std::size_t max_tree_size = (std::size_t)this->max_tree_size_; @@ -541,13 +540,13 @@ class sgtree_impl , (size_type)this->size(), this->get_h_alpha_func(), max_tree_size); this->tree_type::sz_traits().increment(); this->max_tree_size_ = (size_type)max_tree_size; - return iterator(p, this->real_value_traits_ptr()); + return iterator(p, this->value_traits_ptr()); } //! @copydoc ::boost::intrusive::bstree::push_back void push_back(reference value) { - node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); std::size_t max_tree_size = (std::size_t)this->max_tree_size_; @@ -561,7 +560,7 @@ class sgtree_impl //! @copydoc ::boost::intrusive::bstree::push_front void push_front(reference value) { - node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); std::size_t max_tree_size = (std::size_t)this->max_tree_size_; @@ -620,7 +619,7 @@ class sgtree_impl { node_ptr to_erase(i.pointed_node()); iterator ret(this->erase(i)); - disposer(this->get_real_value_traits().to_value_ptr(to_erase)); + disposer(this->get_value_traits().to_value_ptr(to_erase)); return ret; } @@ -930,14 +929,13 @@ class sgtree public: typedef typename Base::value_compare value_compare; typedef typename Base::value_traits value_traits; - typedef typename Base::real_value_traits real_value_traits; typedef typename Base::iterator iterator; typedef typename Base::const_iterator const_iterator; typedef typename Base::reverse_iterator reverse_iterator; typedef typename Base::const_reverse_iterator const_reverse_iterator; //Assert if passed value traits are compatible with the type - BOOST_STATIC_ASSERT((detail::is_same::value)); + BOOST_STATIC_ASSERT((detail::is_same::value)); explicit sgtree( const value_compare &cmp = value_compare() , const value_traits &v_traits = value_traits()) diff --git a/include/boost/intrusive/slist.hpp b/include/boost/intrusive/slist.hpp index e1f6688..1f192af 100644 --- a/include/boost/intrusive/slist.hpp +++ b/include/boost/intrusive/slist.hpp @@ -101,34 +101,29 @@ template class slist_impl : private detail::clear_on_destructor_base < slist_impl - , is_safe_autounlink::type::link_mode>::value + , is_safe_autounlink::value > { template friend class detail::clear_on_destructor_base; //Public typedefs public: typedef ValueTraits value_traits; - /// @cond - static const bool external_value_traits = - detail::external_value_traits_bool_is_true::value; - typedef typename detail::get_real_value_traits::type real_value_traits; - /// @endcond - typedef typename real_value_traits::pointer pointer; - typedef typename real_value_traits::const_pointer const_pointer; + typedef typename value_traits::pointer pointer; + typedef typename value_traits::const_pointer const_pointer; typedef typename pointer_traits::element_type value_type; typedef typename pointer_traits::reference reference; typedef typename pointer_traits::reference const_reference; typedef typename pointer_traits::difference_type difference_type; typedef SizeType size_type; - typedef slist_iterator iterator; - typedef slist_iterator const_iterator; - typedef typename real_value_traits::node_traits node_traits; + typedef slist_iterator iterator; + typedef slist_iterator const_iterator; + typedef typename value_traits::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; static const bool constant_time_size = 0 != (BoolFlags & slist_bool_flags::constant_time_size_pos); - static const bool stateful_value_traits = detail::is_stateful_value_traits::value; + static const bool stateful_value_traits = detail::is_stateful_value_traits::value; static const bool linear = 0 != (BoolFlags & slist_bool_flags::linear_pos); static const bool cache_last = 0 != (BoolFlags & slist_bool_flags::cache_last_pos); @@ -145,14 +140,14 @@ class slist_impl //noncopyable BOOST_MOVABLE_BUT_NOT_COPYABLE(slist_impl) - static const bool safemode_or_autounlink = is_safe_autounlink::value; + static const bool safemode_or_autounlink = is_safe_autounlink::value; //Constant-time size is incompatible with auto-unlink hooks! - BOOST_STATIC_ASSERT(!(constant_time_size && ((int)real_value_traits::link_mode == (int)auto_unlink))); + BOOST_STATIC_ASSERT(!(constant_time_size && ((int)value_traits::link_mode == (int)auto_unlink))); //Linear singly linked lists are incompatible with auto-unlink hooks! - BOOST_STATIC_ASSERT(!(linear && ((int)real_value_traits::link_mode == (int)auto_unlink))); + BOOST_STATIC_ASSERT(!(linear && ((int)value_traits::link_mode == (int)auto_unlink))); //A list with cached last node is incompatible with auto-unlink hooks! - BOOST_STATIC_ASSERT(!(cache_last && ((int)real_value_traits::link_mode == (int)auto_unlink))); + BOOST_STATIC_ASSERT(!(cache_last && ((int)value_traits::link_mode == (int)auto_unlink))); node_ptr get_end_node() { return node_ptr(linear ? node_ptr() : this->get_root_node()); } @@ -230,18 +225,6 @@ class slist_impl const size_traits &priv_size_traits() const { return data_.root_plus_size_; } - const real_value_traits &get_real_value_traits(detail::bool_) const - { return data_; } - - const real_value_traits &get_real_value_traits(detail::bool_) const - { return data_.get_value_traits(*this); } - - real_value_traits &get_real_value_traits(detail::bool_) - { return data_; } - - real_value_traits &get_real_value_traits(detail::bool_) - { return data_.get_value_traits(*this); } - const value_traits &priv_value_traits() const { return data_; } @@ -258,20 +241,15 @@ class slist_impl void prot_set_size(size_type s) { data_.root_plus_size_.set_size(s); } - /// @endcond - public: - const real_value_traits &get_real_value_traits() const - { return this->get_real_value_traits(detail::bool_()); } + typedef typename pointer_traits::template + rebind_pointer::type const_value_traits_ptr; - real_value_traits &get_real_value_traits() - { return this->get_real_value_traits(detail::bool_()); } + const_value_traits_ptr value_traits_ptr() const + { return pointer_traits::pointer_to(this->priv_value_traits()); } - typedef typename pointer_traits::template rebind_pointer::type const_real_value_traits_ptr; - - const_real_value_traits_ptr real_value_traits_ptr() const - { return pointer_traits::pointer_to(this->get_real_value_traits()); } + /// @endcond public: @@ -403,7 +381,7 @@ class slist_impl ++it; if(safemode_or_autounlink) node_algorithms::init(to_erase); - disposer(get_real_value_traits().to_value_ptr(to_erase)); + disposer(priv_value_traits().to_value_ptr(to_erase)); } this->set_default_constructed_state(); } @@ -420,7 +398,7 @@ class slist_impl //! Note: Does not affect the validity of iterators and references. void push_front(reference value) { - node_ptr to_insert = get_real_value_traits().to_node_ptr(value); + node_ptr to_insert = priv_value_traits().to_node_ptr(value); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(to_insert)); if(cache_last){ @@ -446,7 +424,7 @@ class slist_impl void push_back(reference value) { BOOST_STATIC_ASSERT((cache_last)); - node_ptr n = get_real_value_traits().to_node_ptr(value); + node_ptr n = priv_value_traits().to_node_ptr(value); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(n)); node_algorithms::link_after(this->get_last_node(), n); @@ -485,7 +463,7 @@ class slist_impl this->priv_size_traits().decrement(); if(safemode_or_autounlink) node_algorithms::init(to_erase); - disposer(get_real_value_traits().to_value_ptr(to_erase)); + disposer(priv_value_traits().to_value_ptr(to_erase)); if(cache_last){ if(this->empty()){ this->set_last_node(this->get_root_node()); @@ -499,7 +477,7 @@ class slist_impl //! //! Complexity: Constant. reference front() - { return *this->get_real_value_traits().to_value_ptr(node_traits::get_next(this->get_root_node())); } + { return *this->priv_value_traits().to_value_ptr(node_traits::get_next(this->get_root_node())); } //! Effects: Returns a const_reference to the first element of the list. //! @@ -507,7 +485,7 @@ class slist_impl //! //! Complexity: Constant. const_reference front() const - { return *this->get_real_value_traits().to_value_ptr(detail::uncast(node_traits::get_next(this->get_root_node()))); } + { return *this->priv_value_traits().to_value_ptr(detail::uncast(node_traits::get_next(this->get_root_node()))); } //! Effects: Returns a reference to the last element of the list. //! @@ -520,7 +498,7 @@ class slist_impl reference back() { BOOST_STATIC_ASSERT((cache_last)); - return *this->get_real_value_traits().to_value_ptr(this->get_last_node()); + return *this->priv_value_traits().to_value_ptr(this->get_last_node()); } //! Effects: Returns a const_reference to the last element of the list. @@ -534,7 +512,7 @@ class slist_impl const_reference back() const { BOOST_STATIC_ASSERT((cache_last)); - return *this->get_real_value_traits().to_value_ptr(this->get_last_node()); + return *this->priv_value_traits().to_value_ptr(this->get_last_node()); } //! Effects: Returns an iterator to the first element contained in the list. @@ -543,7 +521,7 @@ class slist_impl //! //! Complexity: Constant. iterator begin() - { return iterator (node_traits::get_next(this->get_root_node()), this->real_value_traits_ptr()); } + { return iterator (node_traits::get_next(this->get_root_node()), this->value_traits_ptr()); } //! Effects: Returns a const_iterator to the first element contained in the list. //! @@ -551,7 +529,7 @@ class slist_impl //! //! Complexity: Constant. const_iterator begin() const - { return const_iterator (node_traits::get_next(this->get_root_node()), this->real_value_traits_ptr()); } + { return const_iterator (node_traits::get_next(this->get_root_node()), this->value_traits_ptr()); } //! Effects: Returns a const_iterator to the first element contained in the list. //! @@ -559,7 +537,7 @@ class slist_impl //! //! Complexity: Constant. const_iterator cbegin() const - { return const_iterator(node_traits::get_next(this->get_root_node()), this->real_value_traits_ptr()); } + { return const_iterator(node_traits::get_next(this->get_root_node()), this->value_traits_ptr()); } //! Effects: Returns an iterator to the end of the list. //! @@ -567,7 +545,7 @@ class slist_impl //! //! Complexity: Constant. iterator end() - { return iterator(this->get_end_node(), this->real_value_traits_ptr()); } + { return iterator(this->get_end_node(), this->value_traits_ptr()); } //! Effects: Returns a const_iterator to the end of the list. //! @@ -575,7 +553,7 @@ class slist_impl //! //! Complexity: Constant. const_iterator end() const - { return const_iterator(detail::uncast(this->get_end_node()), this->real_value_traits_ptr()); } + { return const_iterator(detail::uncast(this->get_end_node()), this->value_traits_ptr()); } //! Effects: Returns a const_iterator to the end of the list. //! @@ -592,7 +570,7 @@ class slist_impl //! //! Complexity: Constant. iterator before_begin() - { return iterator(this->get_root_node(), this->real_value_traits_ptr()); } + { return iterator(this->get_root_node(), this->value_traits_ptr()); } //! Effects: Returns an iterator that points to a position //! before the first element. Equivalent to "end()" @@ -601,7 +579,7 @@ class slist_impl //! //! Complexity: Constant. const_iterator before_begin() const - { return const_iterator(detail::uncast(this->get_root_node()), this->real_value_traits_ptr()); } + { return const_iterator(detail::uncast(this->get_root_node()), this->value_traits_ptr()); } //! Effects: Returns an iterator that points to a position //! before the first element. Equivalent to "end()" @@ -623,7 +601,7 @@ class slist_impl { //This function shall not be used if cache_last is not true BOOST_INTRUSIVE_INVARIANT_ASSERT(cache_last); - return iterator (this->get_last_node(), this->real_value_traits_ptr()); + return iterator (this->get_last_node(), this->value_traits_ptr()); } //! Effects: Returns a const_iterator to the last element contained in the list. @@ -637,7 +615,7 @@ class slist_impl { //This function shall not be used if cache_last is not true BOOST_INTRUSIVE_INVARIANT_ASSERT(cache_last); - return const_iterator (this->get_last_node(), this->real_value_traits_ptr()); + return const_iterator (this->get_last_node(), this->value_traits_ptr()); } //! Effects: Returns a const_iterator to the last element contained in the list. @@ -648,7 +626,7 @@ class slist_impl //! //! Note: This function is present only if cached_last<> option is true. const_iterator clast() const - { return const_iterator(this->get_last_node(), this->real_value_traits_ptr()); } + { return const_iterator(this->get_last_node(), this->value_traits_ptr()); } //! Precondition: end_iterator must be a valid end iterator //! of slist. @@ -788,7 +766,7 @@ class slist_impl //! Note: Does not affect the validity of iterators and references. iterator insert_after(const_iterator prev_p, reference value) { - node_ptr n = get_real_value_traits().to_node_ptr(value); + node_ptr n = priv_value_traits().to_node_ptr(value); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(n)); node_ptr prev_n(prev_p.pointed_node()); @@ -797,7 +775,7 @@ class slist_impl this->set_last_node(n); } this->priv_size_traits().increment(); - return iterator (n, this->real_value_traits_ptr()); + return iterator (n, this->value_traits_ptr()); } //! Requires: Dereferencing iterator must yield @@ -819,7 +797,7 @@ class slist_impl size_type count = 0; node_ptr prev_n(prev_p.pointed_node()); for (; f != l; ++f, ++count){ - const node_ptr n = get_real_value_traits().to_node_ptr(*f); + const node_ptr n = priv_value_traits().to_node_ptr(*f); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(n)); node_algorithms::link_after(prev_n, n); @@ -1026,7 +1004,7 @@ class slist_impl } if(safemode_or_autounlink) node_algorithms::init(to_erase); - disposer(get_real_value_traits().to_value_ptr(to_erase)); + disposer(priv_value_traits().to_value_ptr(to_erase)); this->priv_size_traits().decrement(); return it.unconst(); } @@ -1045,7 +1023,7 @@ class slist_impl node_algorithms::unlink_after(prev_n); if(safemode_or_autounlink) node_algorithms::init(to_erase); - disposer(real_value_traits::to_value_ptr(to_erase)); + disposer(value_traits::to_value_ptr(to_erase)); return it.unconst(); } @@ -1079,7 +1057,7 @@ class slist_impl fp = node_traits::get_next(fp); if(safemode_or_autounlink) node_algorithms::init(to_erase); - disposer(get_real_value_traits().to_value_ptr(to_erase)); + disposer(priv_value_traits().to_value_ptr(to_erase)); this->priv_size_traits().decrement(); } if(cache_last && (node_traits::get_next(bfp) == this->get_end_node())){ @@ -1692,7 +1670,7 @@ class slist_impl { BOOST_STATIC_ASSERT((!stateful_value_traits)); //BOOST_INTRUSIVE_INVARIANT_ASSERT (!node_algorithms::inited(value_traits::to_node_ptr(value))); - return iterator (value_traits::to_node_ptr(value), const_real_value_traits_ptr()); + return iterator (value_traits::to_node_ptr(value), const_value_traits_ptr()); } //! Requires: value must be a const reference to a value inserted in a list. @@ -1710,7 +1688,7 @@ class slist_impl { BOOST_STATIC_ASSERT((!stateful_value_traits)); //BOOST_INTRUSIVE_INVARIANT_ASSERT (!node_algorithms::inited(value_traits::to_node_ptr(const_cast (value)))); - return const_iterator (value_traits::to_node_ptr(const_cast (value)), const_real_value_traits_ptr()); + return const_iterator (value_traits::to_node_ptr(const_cast (value)), const_value_traits_ptr()); } //! Requires: value must be a reference to a value inserted in a list. @@ -1725,7 +1703,7 @@ class slist_impl iterator iterator_to(reference value) { //BOOST_INTRUSIVE_INVARIANT_ASSERT (!node_algorithms::inited(value_traits::to_node_ptr(value))); - return iterator (value_traits::to_node_ptr(value), this->real_value_traits_ptr()); + return iterator (value_traits::to_node_ptr(value), this->value_traits_ptr()); } //! Requires: value must be a const reference to a value inserted in a list. @@ -1740,7 +1718,7 @@ class slist_impl const_iterator iterator_to(const_reference value) const { //BOOST_INTRUSIVE_INVARIANT_ASSERT (!node_algorithms::inited(value_traits::to_node_ptr(const_cast (value)))); - return const_iterator (value_traits::to_node_ptr(const_cast (value)), this->real_value_traits_ptr()); + return const_iterator (value_traits::to_node_ptr(const_cast (value)), this->value_traits_ptr()); } //! Returns: The iterator to the element before i in the list. @@ -1789,11 +1767,11 @@ class slist_impl const_iterator previous(const_iterator prev_from, const_iterator i) const { if(cache_last && (i.pointed_node() == this->get_end_node())){ - return const_iterator(detail::uncast(this->get_last_node()), this->real_value_traits_ptr()); + return const_iterator(detail::uncast(this->get_last_node()), this->value_traits_ptr()); } return const_iterator (node_algorithms::get_previous_node - (prev_from.pointed_node(), i.pointed_node()), this->real_value_traits_ptr()); + (prev_from.pointed_node(), i.pointed_node()), this->value_traits_ptr()); } ///@cond @@ -1844,8 +1822,8 @@ class slist_impl BOOST_INTRUSIVE_INVARIANT_ASSERT(n > 0); BOOST_INTRUSIVE_INVARIANT_ASSERT (size_type(std::distance - ( iterator(f, this->real_value_traits_ptr()) - , iterator(before_l, this->real_value_traits_ptr()))) + ( iterator(f, this->value_traits_ptr()) + , iterator(before_l, this->value_traits_ptr()))) +1 == n); this->priv_incorporate_after(prev_pos.pointed_node(), f, before_l); if(constant_time_size){ @@ -2171,9 +2149,8 @@ class slist Options... #endif >::type Base; - typedef typename Base::real_value_traits real_value_traits; //Assert if passed value traits are compatible with the type - BOOST_STATIC_ASSERT((detail::is_same::value)); + BOOST_STATIC_ASSERT((detail::is_same::value)); BOOST_MOVABLE_BUT_NOT_COPYABLE(slist) public: diff --git a/include/boost/intrusive/splaytree.hpp b/include/boost/intrusive/splaytree.hpp index d754f5a..24e4c74 100644 --- a/include/boost/intrusive/splaytree.hpp +++ b/include/boost/intrusive/splaytree.hpp @@ -76,7 +76,6 @@ class splaytree_impl /// @cond typedef bstree_impl< ValueTraits, VoidOrKeyComp, SizeType , ConstantTimeSize, SplayTreeAlgorithms> tree_type; - typedef typename tree_type::real_value_traits real_value_traits; typedef tree_type implementation_defined; /// @endcond @@ -456,10 +455,10 @@ class splaytree_impl template iterator splay_down(const KeyType &key, KeyValueCompare comp) { - detail::key_nodeptr_comp - key_node_comp(comp, &this->get_real_value_traits()); + detail::key_nodeptr_comp + key_node_comp(comp, &this->get_value_traits()); node_ptr r = node_algorithms::splay_down(tree_type::header_ptr(), key, key_node_comp); - return iterator(r, this->real_value_traits_ptr()); + return iterator(r, this->value_traits_ptr()); } //! Effects: Rearranges the container so that if *this stores an element @@ -571,14 +570,13 @@ class splaytree public: typedef typename Base::value_compare value_compare; typedef typename Base::value_traits value_traits; - typedef typename Base::real_value_traits real_value_traits; typedef typename Base::iterator iterator; typedef typename Base::const_iterator const_iterator; typedef typename Base::reverse_iterator reverse_iterator; typedef typename Base::const_reverse_iterator const_reverse_iterator; //Assert if passed value traits are compatible with the type - BOOST_STATIC_ASSERT((detail::is_same::value)); + BOOST_STATIC_ASSERT((detail::is_same::value)); explicit splaytree( const value_compare &cmp = value_compare() , const value_traits &v_traits = value_traits()) diff --git a/include/boost/intrusive/treap.hpp b/include/boost/intrusive/treap.hpp index e3ced65..3bda6db 100644 --- a/include/boost/intrusive/treap.hpp +++ b/include/boost/intrusive/treap.hpp @@ -72,8 +72,8 @@ template - , public detail::ebo_functor_holder + : public bstree_impl + , public detail::ebo_functor_holder < typename get_prio < VoidOrPrioComp , typename bstree_impl @@ -87,7 +87,6 @@ class treap_impl typedef bstree_impl< ValueTraits, VoidOrKeyComp, SizeType , ConstantTimeSize, BsTreeAlgorithms> tree_type; typedef tree_type implementation_defined; - typedef typename tree_type::real_value_traits real_value_traits; typedef get_prio < VoidOrPrioComp , typename tree_type::value_type> get_prio_type; @@ -96,7 +95,7 @@ class treap_impl prio_base; /// @endcond - + typedef typename implementation_defined::pointer pointer; typedef typename implementation_defined::const_pointer const_pointer; typedef typename implementation_defined::value_type value_type; @@ -120,7 +119,7 @@ class treap_impl static const bool constant_time_size = implementation_defined::constant_time_size; static const bool stateful_value_traits = implementation_defined::stateful_value_traits; - static const bool safemode_or_autounlink = is_safe_autounlink::value; + static const bool safemode_or_autounlink = is_safe_autounlink::value; /// @cond private: @@ -217,7 +216,7 @@ class treap_impl //! //! Throws: Nothing. iterator top() - { return this->empty() ? this->end() : iterator(node_traits::get_parent(this->tree_type::header_ptr()), this); } + { return this->tree_type::root(); } //! Effects: Returns a const_iterator pointing to the highest priority object of the treap.. //! @@ -233,7 +232,7 @@ class treap_impl //! //! Throws: Nothing. const_iterator ctop() const - { return this->empty() ? this->cend() : const_iterator(node_traits::get_parent(this->tree_type::header_ptr()), this); } + { return this->tree_type::root(); } #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! @copydoc ::boost::intrusive::bstree::rbegin() @@ -363,15 +362,15 @@ class treap_impl //! No copy-constructors are called. iterator insert_equal(reference value) { - detail::key_nodeptr_comp - key_node_comp(this->value_comp(), &this->get_real_value_traits()); - detail::key_nodeptr_comp - key_node_pcomp(this->priv_pcomp(), &this->get_real_value_traits()); - node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + detail::key_nodeptr_comp + key_node_comp(this->value_comp(), &this->get_value_traits()); + detail::key_nodeptr_comp + key_node_pcomp(this->priv_pcomp(), &this->get_value_traits()); + node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); iterator ret(node_algorithms::insert_equal_upper_bound - (this->tree_type::header_ptr(), to_insert, key_node_comp, key_node_pcomp), this->real_value_traits_ptr()); + (this->tree_type::header_ptr(), to_insert, key_node_comp, key_node_pcomp), this->value_traits_ptr()); this->tree_type::sz_traits().increment(); return ret; } @@ -392,15 +391,15 @@ class treap_impl //! No copy-constructors are called. iterator insert_equal(const_iterator hint, reference value) { - detail::key_nodeptr_comp - key_node_comp(this->value_comp(), &this->get_real_value_traits()); - detail::key_nodeptr_comp - key_node_pcomp(this->priv_pcomp(), &this->get_real_value_traits()); - node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + detail::key_nodeptr_comp + key_node_comp(this->value_comp(), &this->get_value_traits()); + detail::key_nodeptr_comp + key_node_pcomp(this->priv_pcomp(), &this->get_value_traits()); + node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); iterator ret (node_algorithms::insert_equal - (this->tree_type::header_ptr(), hint.pointed_node(), to_insert, key_node_comp, key_node_pcomp), this->real_value_traits_ptr()); + (this->tree_type::header_ptr(), hint.pointed_node(), to_insert, key_node_comp, key_node_pcomp), this->value_traits_ptr()); this->tree_type::sz_traits().increment(); return ret; } @@ -540,14 +539,14 @@ class treap_impl ( const KeyType &key, KeyValueCompare key_value_comp , KeyValuePrioCompare key_value_pcomp, insert_commit_data &commit_data) { - detail::key_nodeptr_comp - ocomp(key_value_comp, &this->get_real_value_traits()); - detail::key_nodeptr_comp - pcomp(key_value_pcomp, &this->get_real_value_traits()); + detail::key_nodeptr_comp + ocomp(key_value_comp, &this->get_value_traits()); + detail::key_nodeptr_comp + pcomp(key_value_pcomp, &this->get_value_traits()); std::pair ret = (node_algorithms::insert_unique_check (this->tree_type::header_ptr(), key, ocomp, pcomp, commit_data)); - return std::pair(iterator(ret.first, this->real_value_traits_ptr()), ret.second); + return std::pair(iterator(ret.first, this->value_traits_ptr()), ret.second); } //! Requires: key_value_comp must be a comparison function that induces @@ -592,14 +591,14 @@ class treap_impl , KeyValuePrioCompare key_value_pcomp , insert_commit_data &commit_data) { - detail::key_nodeptr_comp - ocomp(key_value_comp, &this->get_real_value_traits()); - detail::key_nodeptr_comp - pcomp(key_value_pcomp, &this->get_real_value_traits()); + detail::key_nodeptr_comp + ocomp(key_value_comp, &this->get_value_traits()); + detail::key_nodeptr_comp + pcomp(key_value_pcomp, &this->get_value_traits()); std::pair ret = (node_algorithms::insert_unique_check (this->tree_type::header_ptr(), hint.pointed_node(), key, ocomp, pcomp, commit_data)); - return std::pair(iterator(ret.first, this->real_value_traits_ptr()), ret.second); + return std::pair(iterator(ret.first, this->value_traits_ptr()), ret.second); } //! Requires: value must be an lvalue of type value_type. commit_data @@ -621,12 +620,12 @@ class treap_impl //! erased between the "insert_check" and "insert_commit" calls. iterator insert_unique_commit(reference value, const insert_commit_data &commit_data) { - node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); node_algorithms::insert_unique_commit(this->tree_type::header_ptr(), to_insert, commit_data); this->tree_type::sz_traits().increment(); - return iterator(to_insert, this->real_value_traits_ptr()); + return iterator(to_insert, this->value_traits_ptr()); } //! Requires: value must be an lvalue, "pos" must be @@ -645,13 +644,13 @@ class treap_impl //! by advanced users. iterator insert_before(const_iterator pos, reference value) { - node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); - detail::key_nodeptr_comp - pcomp(this->priv_pcomp(), &this->get_real_value_traits()); + detail::key_nodeptr_comp + pcomp(this->priv_pcomp(), &this->get_value_traits()); iterator ret (node_algorithms::insert_before - (this->tree_type::header_ptr(), pos.pointed_node(), to_insert, pcomp), this->real_value_traits_ptr()); + (this->tree_type::header_ptr(), pos.pointed_node(), to_insert, pcomp), this->value_traits_ptr()); this->tree_type::sz_traits().increment(); return ret; } @@ -672,11 +671,11 @@ class treap_impl //! by advanced users. void push_back(reference value) { - node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); - detail::key_nodeptr_comp - pcomp(this->priv_pcomp(), &this->get_real_value_traits()); + detail::key_nodeptr_comp + pcomp(this->priv_pcomp(), &this->get_value_traits()); node_algorithms::push_back(this->tree_type::header_ptr(), to_insert, pcomp); this->tree_type::sz_traits().increment(); } @@ -697,11 +696,11 @@ class treap_impl //! by advanced users. void push_front(reference value) { - node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + node_ptr to_insert(this->get_value_traits().to_node_ptr(value)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); - detail::key_nodeptr_comp - pcomp(this->priv_pcomp(), &this->get_real_value_traits()); + detail::key_nodeptr_comp + pcomp(this->priv_pcomp(), &this->get_value_traits()); node_algorithms::push_front(this->tree_type::header_ptr(), to_insert, pcomp); this->tree_type::sz_traits().increment(); } @@ -721,8 +720,8 @@ class treap_impl node_ptr to_erase(i.pointed_node()); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!node_algorithms::unique(to_erase)); - detail::key_nodeptr_comp - key_node_pcomp(this->priv_pcomp(), &this->get_real_value_traits()); + detail::key_nodeptr_comp + key_node_pcomp(this->priv_pcomp(), &this->get_value_traits()); node_algorithms::erase(this->tree_type::header_ptr(), to_erase, key_node_pcomp); this->tree_type::sz_traits().decrement(); if(safemode_or_autounlink) @@ -796,7 +795,7 @@ class treap_impl { node_ptr to_erase(i.pointed_node()); iterator ret(this->erase(i)); - disposer(this->get_real_value_traits().to_value_ptr(to_erase)); + disposer(this->get_value_traits().to_value_ptr(to_erase)); return ret; } @@ -898,7 +897,7 @@ class treap_impl void clear_and_dispose(Disposer disposer) { node_algorithms::clear_and_dispose(this->tree_type::header_ptr() - , detail::node_disposer(disposer, &this->get_real_value_traits())); + , detail::node_disposer(disposer, &this->get_value_traits())); node_algorithms::init_header(this->tree_type::header_ptr()); this->tree_type::sz_traits().set_size(0); } @@ -1120,14 +1119,13 @@ class treap typedef typename Base::value_compare value_compare; typedef typename Base::priority_compare priority_compare; typedef typename Base::value_traits value_traits; - typedef typename Base::real_value_traits real_value_traits; typedef typename Base::iterator iterator; typedef typename Base::const_iterator const_iterator; typedef typename Base::reverse_iterator reverse_iterator; typedef typename Base::const_reverse_iterator const_reverse_iterator; //Assert if passed value traits are compatible with the type - BOOST_STATIC_ASSERT((detail::is_same::value)); + BOOST_STATIC_ASSERT((detail::is_same::value)); explicit treap( const value_compare &cmp = value_compare() , const priority_compare &pcmp = priority_compare() diff --git a/include/boost/intrusive/treap_set.hpp b/include/boost/intrusive/treap_set.hpp index 6812e1a..caad0df 100644 --- a/include/boost/intrusive/treap_set.hpp +++ b/include/boost/intrusive/treap_set.hpp @@ -44,6 +44,7 @@ class treap_set_impl #endif { /// @cond + public: typedef treap_impl tree_type; BOOST_MOVABLE_BUT_NOT_COPYABLE(treap_set_impl) diff --git a/include/boost/intrusive/unordered_set.hpp b/include/boost/intrusive/unordered_set.hpp index 5ba36fe..f91fc76 100644 --- a/include/boost/intrusive/unordered_set.hpp +++ b/include/boost/intrusive/unordered_set.hpp @@ -1029,15 +1029,15 @@ struct make_unordered_set typedef typename detail::get_value_traits ::type value_traits; - typedef typename make_real_bucket_traits - ::type real_bucket_traits; + typedef typename make_bucket_traits + ::type bucket_traits; typedef unordered_set_impl < value_traits , typename packed_options::hash , typename packed_options::equal , typename packed_options::size_type - , real_bucket_traits + , bucket_traits , (std::size_t(true)*hash_bool_flags::unique_keys_pos) | (std::size_t(packed_options::constant_time_size)*hash_bool_flags::constant_time_size_pos) | (std::size_t(packed_options::power_2_buckets)*hash_bool_flags::power_2_buckets_pos) @@ -2066,15 +2066,15 @@ struct make_unordered_multiset typedef typename detail::get_value_traits ::type value_traits; - typedef typename make_real_bucket_traits - ::type real_bucket_traits; + typedef typename make_bucket_traits + ::type bucket_traits; typedef unordered_multiset_impl < value_traits , typename packed_options::hash , typename packed_options::equal , typename packed_options::size_type - , real_bucket_traits + , bucket_traits , (std::size_t(false)*hash_bool_flags::unique_keys_pos) | (std::size_t(packed_options::constant_time_size)*hash_bool_flags::constant_time_size_pos) | (std::size_t(packed_options::power_2_buckets)*hash_bool_flags::power_2_buckets_pos) diff --git a/proj/vc7ide/Intrusive.sln b/proj/vc7ide/Intrusive.sln index 890c29e..aecfe69 100644 --- a/proj/vc7ide/Intrusive.sln +++ b/proj/vc7ide/Intrusive.sln @@ -31,10 +31,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "custom_bucket_traits", "cus ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "external_value_traits", "external_value_traits\external_value_traits.vcproj", "{97B69A72-B9D3-7389-17FB-74612F4A9543}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "splay_multiset", "splay_multiset\splay_multiset.vcproj", "{01E70176-B6C5-BF47-2C91-A949077BA323}" ProjectSection(ProjectDependencies) = postProject EndProjectSection @@ -119,6 +115,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pack_options", "pack_option ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "container_size_test", "container_size_test\container_size_test.vcproj", "{9E721E26-45AF-192C-AD67-A4CC7D096497}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject Global GlobalSection(SolutionConfiguration) = preSolution Debug = Debug @@ -159,10 +159,6 @@ Global {31C77B84-0B2C-9481-CB81-27A149F33825}.Debug.Build.0 = Debug|Win32 {31C77B84-0B2C-9481-CB81-27A149F33825}.Release.ActiveCfg = Release|Win32 {31C77B84-0B2C-9481-CB81-27A149F33825}.Release.Build.0 = Release|Win32 - {97B69A72-B9D3-7389-17FB-74612F4A9543}.Debug.ActiveCfg = Debug|Win32 - {97B69A72-B9D3-7389-17FB-74612F4A9543}.Debug.Build.0 = Debug|Win32 - {97B69A72-B9D3-7389-17FB-74612F4A9543}.Release.ActiveCfg = Release|Win32 - {97B69A72-B9D3-7389-17FB-74612F4A9543}.Release.Build.0 = Release|Win32 {01E70176-B6C5-BF47-2C91-A949077BA323}.Debug.ActiveCfg = Debug|Win32 {01E70176-B6C5-BF47-2C91-A949077BA323}.Debug.Build.0 = Debug|Win32 {01E70176-B6C5-BF47-2C91-A949077BA323}.Release.ActiveCfg = Release|Win32 @@ -247,6 +243,10 @@ Global {77F4139B-281B-F694-7CB1-3495467B4D35}.Debug.Build.0 = Debug|Win32 {77F4139B-281B-F694-7CB1-3495467B4D35}.Release.ActiveCfg = Release|Win32 {77F4139B-281B-F694-7CB1-3495467B4D35}.Release.Build.0 = Release|Win32 + {9E721E26-45AF-192C-AD67-A4CC7D096497}.Debug.ActiveCfg = Debug|Win32 + {9E721E26-45AF-192C-AD67-A4CC7D096497}.Debug.Build.0 = Debug|Win32 + {9E721E26-45AF-192C-AD67-A4CC7D096497}.Release.ActiveCfg = Release|Win32 + {9E721E26-45AF-192C-AD67-A4CC7D096497}.Release.Build.0 = Release|Win32 EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution EndGlobalSection diff --git a/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj b/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj index 079a8ae..fc4e758 100644 --- a/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj +++ b/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj @@ -364,9 +364,6 @@ - - diff --git a/proj/vc7ide/external_value_traits/external_value_traits.vcproj b/proj/vc7ide/container_size_test/container_size_test.vcproj similarity index 82% rename from proj/vc7ide/external_value_traits/external_value_traits.vcproj rename to proj/vc7ide/container_size_test/container_size_test.vcproj index 87ebd51..dad1be0 100644 --- a/proj/vc7ide/external_value_traits/external_value_traits.vcproj +++ b/proj/vc7ide/container_size_test/container_size_test.vcproj @@ -2,9 +2,8 @@ + UniqueIdentifier="{4F0C713E-750E-B78A-4373-52D2204C1ACA}"> + RelativePath="..\..\..\test\container_size_test.cpp"> diff --git a/test/container_size_test.cpp b/test/container_size_test.cpp new file mode 100644 index 0000000..d95cee5 --- /dev/null +++ b/test/container_size_test.cpp @@ -0,0 +1,187 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2014-2014 +// +// 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 +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace boost::intrusive; + +template +struct boolean +{ + static const bool value = Value; +}; + +template +struct pow2_and_equal_sizes +{ + static const std::size_t a_size = sizeof(A); + static const std::size_t b_size = sizeof(B); + static const bool a_b_sizes_equal = a_size == b_size; + static const bool value = !(a_size & (a_size - 1u)); +}; + +template +struct node : Hook +{}; + +//Avoid testing for uncommon architectures +void test_sizes(boolean, std::size_t) +{} + +template +void test_iterator_sizes(C &, std::size_t size) +{ + typedef typename C::iterator iterator; + typedef typename C::const_iterator const_iterator; + BOOST_TEST_EQ(sizeof(iterator), size); + BOOST_TEST_EQ(sizeof(const_iterator), size); +} + +//Test sizes for common 32 and 64 bit architectures +void test_sizes(boolean, std::size_t wordsize) +{ + { //list + list > > > c; + BOOST_TEST_EQ(sizeof(c), wordsize*3); + test_iterator_sizes(c, wordsize); + } + { + list > >, constant_time_size > c; + BOOST_TEST_EQ(sizeof(c), wordsize*2); + test_iterator_sizes(c, wordsize); + } + { //slist + slist > > > c; + BOOST_TEST_EQ(sizeof(c), wordsize*2); + test_iterator_sizes(c, wordsize); + } + { + slist > > , constant_time_size > c; + BOOST_TEST_EQ(sizeof(c), wordsize*1); + test_iterator_sizes(c, wordsize); + } + { + slist > > , cache_last > c; + BOOST_TEST_EQ(sizeof(c), wordsize*3); + test_iterator_sizes(c, wordsize); + } + { //set + set > > > c; + BOOST_TEST_EQ(sizeof(c), wordsize*5); + test_iterator_sizes(c, wordsize); + } + { + set > > , constant_time_size > c; + BOOST_TEST_EQ(sizeof(c), wordsize*4); + test_iterator_sizes(c, wordsize); + } + { + set > > > , constant_time_size > c; + BOOST_TEST_EQ(sizeof(c), wordsize*3); + test_iterator_sizes(c, wordsize); + } + { //avl + avl_set > > > c; + BOOST_TEST_EQ(sizeof(c), wordsize*5); + test_iterator_sizes(c, wordsize); + } + { + avl_set > > , constant_time_size > c; + BOOST_TEST_EQ(sizeof(c), wordsize*4); + test_iterator_sizes(c, wordsize); + } + { + avl_set > > > , constant_time_size > c; + BOOST_TEST_EQ(sizeof(c), wordsize*3); + test_iterator_sizes(c, wordsize); + } + { //splay + splay_set > > > c; + BOOST_TEST_EQ(sizeof(c), wordsize*4); + test_iterator_sizes(c, wordsize); + } + { + splay_set > > , constant_time_size > c; + BOOST_TEST_EQ(sizeof(c), wordsize*3); + test_iterator_sizes(c, wordsize); + } + { //scapegoat + sg_set > > c; + BOOST_TEST_EQ(sizeof(c), (wordsize*5+sizeof(float)*2)); + test_iterator_sizes(c, wordsize); + } + { //treap + treap_set > > c; + BOOST_TEST_EQ(sizeof(c), wordsize*4); + test_iterator_sizes(c, wordsize); + } + { + treap_set > , constant_time_size > c; + BOOST_TEST_EQ(sizeof(c), wordsize*3); + test_iterator_sizes(c, wordsize); + } + { //unordered + typedef unordered_set > > cont_type; + cont_type::bucket_type buckets[1]; + cont_type c(cont_type::bucket_traits(buckets, 1)); + BOOST_TEST_EQ(sizeof(c), wordsize*3); + test_iterator_sizes(c, wordsize*2); + } + { + typedef unordered_set > , power_2_buckets > cont_type; + cont_type::bucket_type buckets[1]; + cont_type c(cont_type::bucket_traits(buckets, 1)); + BOOST_TEST_EQ(sizeof(c), wordsize*3); + test_iterator_sizes(c, wordsize*2); + } + { + typedef unordered_set >, constant_time_size > cont_type; + cont_type::bucket_type buckets[1]; + cont_type c(cont_type::bucket_traits(buckets, 1)); + BOOST_TEST_EQ(sizeof(c), wordsize*2); + test_iterator_sizes(c, wordsize*2); + } + { + typedef unordered_set > >, constant_time_size > cont_type; + cont_type::bucket_type buckets[1]; + cont_type c(cont_type::bucket_traits(buckets, 1)); + BOOST_TEST_EQ(sizeof(c), wordsize*2); + test_iterator_sizes(c, wordsize*2); + } + { + typedef unordered_set > >, incremental > cont_type; + cont_type::bucket_type buckets[1]; + cont_type c(cont_type::bucket_traits(buckets, 1)); + BOOST_TEST_EQ(sizeof(c), wordsize*4); + test_iterator_sizes(c, wordsize*2); + } +} + +int main() +{ + test_sizes(boolean< pow2_and_equal_sizes::value >(), sizeof(std::size_t)); + return ::boost::report_errors(); +} + +#include diff --git a/test/external_value_traits_test.cpp b/test/external_value_traits_test.cpp deleted file mode 100644 index 60efc9d..0000000 --- a/test/external_value_traits_test.cpp +++ /dev/null @@ -1,241 +0,0 @@ -///////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2007-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 -#include -#include -#include -#include -#include -#include - -using namespace boost::intrusive; - -class MyClass -{ - public: - int int_; - - MyClass(int i = 0) - : int_(i) - {} - friend bool operator > (const MyClass &l, const MyClass &r) - { return l.int_ > r.int_; } - friend bool operator == (const MyClass &l, const MyClass &r) - { return l.int_ == r.int_; } - friend std::size_t hash_value(const MyClass &v) - { return boost::hash_value(v.int_); } -}; - -const int NumElements = 100; - -template -struct external_traits -{ - typedef NodeTraits 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 MyClass value_type; - typedef typename pointer_traits:: - template rebind_pointer::type pointer; - typedef typename pointer_traits:: - template rebind_pointer - ::type const_pointer; - static const link_mode_type link_mode = normal_link; - - external_traits(pointer values, std::size_t NumElem) - : values_(values), node_array_(NumElem) - {} - - node_ptr to_node_ptr (value_type &value) - { return (&node_array_[0]) + (&value - values_); } - - const_node_ptr to_node_ptr (const value_type &value) const - { return &node_array_[0] + (&value - values_); } - - pointer to_value_ptr(node_ptr n) - { return values_ + (n - &node_array_[0]); } - - const_pointer to_value_ptr(const_node_ptr n) const - { return values_ + (n - &node_array_[0]); } - - pointer values_; - std::vector node_array_; -}; - -template -struct value_traits_proxy; - -template -struct traits_holder - : public T -{}; - -typedef value_traits_proxy > list_value_traits_proxy; -typedef value_traits_proxy > slist_value_traits_proxy; -typedef value_traits_proxy > rbtree_value_traits_proxy; -typedef value_traits_proxy > > hash_value_traits_proxy; - -struct uset_bucket_traits -{ - private: - typedef unordered_bucket > > > >::type bucket_type; - - //Non-copyable - uset_bucket_traits(const uset_bucket_traits &other); - uset_bucket_traits & operator=(const uset_bucket_traits &other); - - public: - static const std::size_t NumBuckets = 100; - - uset_bucket_traits(){} - - bucket_type * bucket_begin() const - { return buckets_; } - - std::size_t bucket_count() const - { return NumBuckets; } - - mutable bucket_type buckets_[NumBuckets]; -}; - -struct bucket_traits_proxy -{ - static const bool external_bucket_traits = true; - typedef uset_bucket_traits bucket_traits; - - template - bucket_traits &get_bucket_traits(Container &cont); - - template - const bucket_traits &get_bucket_traits(const Container &cont) const; -}; - -//Define a list that will store MyClass using the external hook -typedef list > List; -//Define a slist that will store MyClass using the external hook -typedef slist > Slist; -//Define a rbtree that will store MyClass using the external hook -typedef rbtree< MyClass - , value_traits - , compare > > Rbtree; -//Define a hashtable that will store MyClass using the external hook - -typedef hashtable< MyClass - , value_traits - , bucket_traits - > Hash; - -template -struct value_traits_proxy -{ - static const bool external_value_traits = true; - typedef external_traits value_traits; - - template - const value_traits &get_value_traits(const Container &cont) const; - - template - value_traits &get_value_traits(Container &cont); -}; - -struct ContainerHolder - : public uset_bucket_traits - , public List - , public external_traits > - , public Slist - , public external_traits > - , public Rbtree - , public external_traits > - , public Hash - , public external_traits > > -{ - static const std::size_t NumBucket = 100; - ContainerHolder(MyClass *values, std::size_t num_elem) - : uset_bucket_traits() - , List() - , external_traits >(values, num_elem) - , Slist() - , external_traits >(values, num_elem) - , Rbtree() - , external_traits >(values, num_elem) - , Hash(Hash::bucket_traits()) - , external_traits > >(values, num_elem) - {} -}; - -template -template -typename value_traits_proxy::value_traits & - value_traits_proxy::get_value_traits(Container &cont) -{ return static_cast(static_cast(cont)); } - -template -template -const typename value_traits_proxy::value_traits & - value_traits_proxy::get_value_traits(const Container &cont) const -{ return static_cast(static_cast(cont)); } - -template -typename bucket_traits_proxy::bucket_traits & - bucket_traits_proxy::get_bucket_traits(Container &cont) -{ return static_cast(static_cast(cont)); } - -template -const typename bucket_traits_proxy::bucket_traits & - bucket_traits_proxy::get_bucket_traits(const Container &cont) const -{ return static_cast(static_cast(cont)); } - -int main() -{ - MyClass values [NumElements]; - //Create several MyClass objects, each one with a different value - for(int i = 0; i < NumElements; ++i) - values[i].int_ = i; - - ContainerHolder cont_holder(values, NumElements); - List &my_list = static_cast (cont_holder); - Slist &my_slist = static_cast (cont_holder); - Rbtree &my_rbtree = static_cast (cont_holder); - Hash &my_hash = static_cast (cont_holder); - - //Now insert them in containers - for(MyClass * it(&values[0]), *itend(&values[NumElements]) - ; it != itend; ++it){ - my_list.push_front(*it); - my_slist.push_front(*it); - my_rbtree.insert_unique(*it); - my_hash.insert_unique(*it); - } - - //Now test containers - { - List::const_iterator list_it (my_list.cbegin()); - Slist::const_iterator slist_it (my_slist.cbegin()); - Rbtree::const_iterator rbtree_it (my_rbtree.cbegin()); - Hash::const_iterator hash_it (my_hash.cbegin()); - MyClass *it_val(&values[NumElements] - 1), *it_rbeg_val(&values[0]-1); - - //Test inserted objects - for(; it_val != it_rbeg_val; --it_val, ++list_it, ++slist_it, ++rbtree_it){ - if(&*list_it != &*it_val) return 1; - if(&*slist_it != &*it_val) return 1; - if(&*rbtree_it != &*it_val) return 1; - hash_it = my_hash.find(*it_val); - if(hash_it == my_hash.cend() || &*hash_it != &*it_val) - return 1; - } - } - - return 0; -}