diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index 36fb46c..d21ab56 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -33,10 +33,12 @@ doxygen autodoc \"BOOST_RV_REF_END=&&\" \\ \"list_impl=list\" \\ \"slist_impl=slist\" \\ + \"bstree_impl=bstree\" \\ + \"bs_set_impl=bs_set\" \\ + \"bs_multiset_impl=bs_multiset\" \\ + \"rbtree_impl=rbtree\" \\ \"set_impl=set\" \\ \"multiset_impl=multiset\" \\ - \"bstree_impl=bstree\" \\ - \"rbtree_impl=rbtree\" \\ \"unordered_set_impl=unordered_set\" \\ \"unordered_multiset_impl=unordered_multiset\" \\ \"hashtable_impl=hashtable\" \\ @@ -51,7 +53,9 @@ doxygen autodoc \"avltree_impl=avltree\" \\ \"treap_set_impl=treap_set\" \\ \"treap_multiset_impl=treap_multiset\" \\ - \"treap_impl=treap\"" + \"treap_impl=treap\" \\ + \"BOOST_INTRUSIVE_OPTION_CONSTANT(OPTION_NAME, TYPE, VALUE, CONSTANT_NAME) = template struct OPTION_NAME{};\" \\ + \"BOOST_INTRUSIVE_OPTION_TYPE(OPTION_NAME, TYPE, TYPEDEF_EXPR, TYPEDEF_NAME) = template struct OPTION_NAME{};\" " ; xml intrusive : intrusive.qbk diff --git a/doc/intrusive.qbk b/doc/intrusive.qbk index c84700c..a7b15ac 100644 --- a/doc/intrusive.qbk +++ b/doc/intrusive.qbk @@ -871,11 +871,11 @@ the section [link intrusive.usage How to use Boost.Intrusive]: * [*`linear`]: the singly linked list is implemented as a null-terminated list instead of a circular list. This allows `O(1)` swap, but losses some operations like `container_from_end_iterator`. -* [*`cache_last`]: the singly linked also stores a pointer to the +* [*`cache_last`]: `slist` also stores a pointer to the last element of the singly linked list. This allows `O(1)` swap, `splice_after(iterator, slist &)` and makes the list offer new functions like `push_back(reference)` and `back()`. Logically, the size an empty list is - increased in `sizeof(void_pointer)` and the the cached last node pointer must + increased in `sizeof(void_pointer)` and the cached last node pointer must be updated in every operation, and that might incur in a slight performance impact. `auto_unlink` hooks are not usable if `linear` and/or `cache_last` options are @@ -1364,163 +1364,6 @@ the unordered container: [endsect] -[section:splay_set_multiset Intrusive splay tree based associative containers: splay_set, splay_multiset and , splay_tree] - -C++ associative containers are usually based on red-black tree implementations (e.g.: STL, -Boost.Intrusive associative containers). However, there are other interesting data -structures that offer some advantages (and also disadvantages). - -Splay trees are self-adjusting binary search trees used typically in caches, memory -allocators and other applications, because splay trees have a "caching effect": recently -accessed elements have better access times than elements accessed less frequently. -For more information on splay trees see [@http://en.wikipedia.org/wiki/Splay_tree Wikipedia entry]. - -[*Boost.Intrusive] offers 3 containers based on splay trees: -[classref boost::intrusive::splay_set splay_set], -[classref boost::intrusive::splay_multiset splay_multiset] and -[classref boost::intrusive::splaytree splaytree]. The first two are similar to -[classref boost::intrusive::set set] or -[classref boost::intrusive::multiset multiset] and the latter is a generalization -that offers functions both to insert unique and multiple keys. - -The memory overhead of these containers with Boost.Intrusive hooks is usually 3 pointers. -An empty, non constant-time size splay container has also a size of 3 pointers. - -[section:splay_set_multiset_disadvantages Advantages and disadvantages of splay tree based containers] - -Splay tree based intrusive containers have logarithmic complexity in many -operations like searches, insertions, erasures, etc., but if some elements are -more frequently accessed than others, splay trees perform faster searches than equivalent -balanced binary trees (such as red-black trees). - -The caching effect offered by splay trees comes with a cost: the tree must be -rebalanced when an element is searched. This disallows const versions of search -functions like `find()`, `lower_bound()`, `upper_bound()`, `equal_range()`, -`count()`, etc. - -Because of this, splay-tree based associative containers are not drop-in -replacements of [classref boost::intrusive::set set]/ -[classref boost::intrusive::multiset multiset]. - -Apart from this, if element searches are randomized, the tree will be rebalanced -without taking advantage of the cache effect, so splay trees can offer worse -performance than other balanced trees for some search patterns. - -[endsect] - -[section:splay_set_multiset_hooks splay_set, splay_multiset and splaytree hooks] - -[classref boost::intrusive::splay_set splay_set], -[classref boost::intrusive::splay_multiset splay_multiset] and -[classref boost::intrusive::splaytree splaytree] -share the same hooks. - -[c++] - - template - class splay_set_base_hook; - -* [classref boost::intrusive::splay_set_base_hook splay_set_base_hook]: - the user class derives publicly from this class to make - it compatible with splay tree based containers. - -[c++] - - template - class splay_set_member_hook; - -* [classref boost::intrusive::set_member_hook set_member_hook]: - the user class contains a public member of this class to make - it compatible with splay tree based containers. - -[classref boost::intrusive::splay_set_base_hook splay_set_base_hook] and -[classref boost::intrusive::splay_set_member_hook splay_set_member_hook] receive -the same options explained in the section -[link intrusive.usage How to use Boost.Intrusive]: - -* [*`tag`] (for base hooks only): This argument serves as a tag, - so you can derive from more than one base hook. - Default: `tag`. - -* [*`link_mode`]: The linking policy. - Default: `link_mode`. - -* [*`void_pointer`]: The pointer type to be used - internally in the hook and propagated to the container. - Default: `void_pointer`. - -[endsect] - -[section:set_multiset_containers splay_set, splay_multiset and splaytree containers] - -[c++] - - template - class splay_set; - - template - class splay_multiset; - - template - class splaytree; - -These containers receive the same options explained in the section -[link intrusive.usage How to use Boost.Intrusive]: - -* [*`base_hook`] / [*`member_hook`] / - [*`value_traits`]: To specify the hook type or value traits used - to configure the container. (To learn about value traits go to the section - [link intrusive.value_traits Containers with custom ValueTraits].) - -* [*`constant_time_size`]: To activate the constant-time `size()` operation. - Default: `constant_time_size` - -* [*`size_type`]: To specify the type that will be used to store the size - of the container. Default: `size_type` - -And they also can receive an additional option: - -* [*`compare`]: Comparison function for the objects to be inserted - in containers. The comparison functor must induce a strict weak ordering. - Default: `compare< std::less >` - -[endsect] - -[section:splay_set_bst_hook Splay trees with BST hooks] - -Intrusive splay containers can also use plain binary search tree hooks -[classref boost::intrusive::bs_set_base_hook bs_set_base_hook] and -[classref boost::intrusive::bs_set_base_hook bs_set_base_hook]. -These hooks can be used by other intrusive containers like -intrusive scapegoat containers -[classref boost::intrusive::sg_set sg_set] and -[classref boost::intrusive::sg_multiset sg_multiset]. A programmer -might prefer using a binary search tree hook so that the same type -can be inserted in some situations in a splay container but -also inserted in other compatible containers when -the hook is not being used in a splay container. - -[classref boost::intrusive::bs_set_base_hook bs_set_base_hook] and -[classref boost::intrusive::bs_set_base_hook bs_set_member_hook] admit -the same options as [classref boost::intrusive::splay_set_base_hook splay_set_base_hook]. - -[endsect] - -[section:splay_set_multiset_example Example] - -Now let's see a small example using both splay hooks, -binary search tree hooks and -[classref boost::intrusive::splay_set splay_set]/ -[classref boost::intrusive::splay_multiset splay_multiset] -containers: - -[import ../example/doc_splay_set.cpp] -[doc_splay_set_code] - -[endsect] - -[endsect] - [section:avl_set_multiset Intrusive avl tree based associative containers: avl_set, avl_multiset and avltree] Similar to red-black trees, AVL trees are balanced binary trees. @@ -1649,6 +1492,103 @@ containers: [endsect] +[section:splay_set_multiset Intrusive splay tree based associative containers: splay_set, splay_multiset and , splay_tree] + +C++ associative containers are usually based on red-black tree implementations (e.g.: STL, +Boost.Intrusive associative containers). However, there are other interesting data +structures that offer some advantages (and also disadvantages). + +Splay trees are self-adjusting binary search trees used typically in caches, memory +allocators and other applications, because splay trees have a "caching effect": recently +accessed elements have better access times than elements accessed less frequently. +For more information on splay trees see [@http://en.wikipedia.org/wiki/Splay_tree the corresponding Wikipedia entry]. + +[*Boost.Intrusive] offers 3 containers based on splay trees: +[classref boost::intrusive::splay_set splay_set], +[classref boost::intrusive::splay_multiset splay_multiset] and +[classref boost::intrusive::splaytree splaytree]. The first two are similar to +[classref boost::intrusive::set set] or +[classref boost::intrusive::multiset multiset] and the latter is a generalization +that offers functions both to insert unique and multiple keys. + +The memory overhead of these containers with Boost.Intrusive hooks is usually 3 pointers. +An empty, non constant-time size splay container has also a size of 3 pointers. + +[section:splay_set_multiset_disadvantages Advantages and disadvantages of splay tree based containers] + +Splay tree based intrusive containers have logarithmic complexity in many +operations like searches, insertions, erasures, etc., but if some elements are +more frequently accessed than others, splay trees perform faster searches than equivalent +balanced binary trees (such as red-black trees). + +The caching effect offered by splay trees comes with a cost: the tree must be +rebalanced when an element is searched. To maintain const-correctness and thread-safety +guarantees, this caching effect is not updated when const versions of +search functions like `find()`, `lower_bound()`, `upper_bound()`, `equal_range()`, +`count()`... are called. This means that using splay-tree based associative containers as drop-in +replacements of [classref boost::intrusive::set set]/ +[classref boost::intrusive::multiset multiset], specially for const search functions, +might not result in desired performance improvements. + +If element searches are randomized, the tree will be continuously srebalanced +without taking advantage of the cache effect, so splay trees can offer worse +performance than other balanced trees for several search patterns. + +[*Boost.Intrusive] splay associative containers don't use their own hook types but plain Binary search tree hooks. +See [link intrusive.bst_hooks Binary search tree hooks: bs_set_base_hook and bs_set_member_hook] section for more +information about these hooks. + +[endsect] + +[section:set_multiset_containers splay_set, splay_multiset and splaytree containers] + +[c++] + + template + class splay_set; + + template + class splay_multiset; + + template + class splaytree; + +These containers receive the same options explained in the section +[link intrusive.usage How to use Boost.Intrusive]: + +* [*`base_hook`] / [*`member_hook`] / + [*`value_traits`]: To specify the hook type or value traits used + to configure the container. (To learn about value traits go to the section + [link intrusive.value_traits Containers with custom ValueTraits].) + +* [*`constant_time_size`]: To activate the constant-time `size()` operation. + Default: `constant_time_size` + +* [*`size_type`]: To specify the type that will be used to store the size + of the container. Default: `size_type` + +And they also can receive an additional option: + +* [*`compare`]: Comparison function for the objects to be inserted + in containers. The comparison functor must induce a strict weak ordering. + Default: `compare< std::less >` + +[endsect] + +[section:splay_set_multiset_example Example] + +Now let's see a small example using +[classref boost::intrusive::splay_set splay_set]/ +[classref boost::intrusive::splay_multiset splay_multiset] +containers: + +[import ../example/doc_splay_set.cpp] +[doc_splay_set_code] + +[endsect] + +[endsect] + [section:sg_set_multiset Intrusive scapegoat tree based associative containers: sg_set, sg_multiset and sgtree] @@ -1705,50 +1645,9 @@ An empty, [classref boost::intrusive::sg_set sg_set], has also the size of 3 pointers, two integers and two floating point values (equivalent to the size of 7 pointers on most systems). -[section:sg_set_multiset_hooks Using binary search tree hooks: bs_set_base_hook and bs_set_member_hook] - -[classref boost::intrusive::sg_set sg_set], -[classref boost::intrusive::sg_multiset sg_multiset] and -[classref boost::intrusive::sgtree sgtree] don't use their -own hooks but plain binary search tree hooks. This has many advantages -since binary search tree hooks can also be used to insert values in -splay and treap containers. - -[c++] - - template - class bs_set_base_hook; - -* [classref boost::intrusive::bs_set_base_hook bs_set_base_hook]: - the user class derives publicly from this class to make - it compatible with scapegoat tree based containers. - -[c++] - - template - class bs_set_member_hook; - -* [classref boost::intrusive::set_member_hook set_member_hook]: - the user class contains a public member of this class to make - it compatible with scapegoat tree based containers. - -[classref boost::intrusive::bs_set_base_hook bs_set_base_hook] and -[classref boost::intrusive::bs_set_member_hook bs_set_member_hook] receive -the same options explained in the section -[link intrusive.usage How to use Boost.Intrusive]: - -* [*`tag`] (for base hooks only): This argument serves as a tag, - so you can derive from more than one base hook. - Default: `tag`. - -* [*`link_mode`]: The linking policy. - Default: `link_mode`. - -* [*`void_pointer`]: The pointer type to be used - internally in the hook and propagated to the container. - Default: `void_pointer`. - -[endsect] +[*Boost.Intrusive] scapegoat associative containers don't use their own hook types but plain Binary search tree hooks. +See [link intrusive.bst_hooks Binary search tree hooks: bs_set_base_hook and bs_set_member_hook] section for more +information about these hooks. [section:sg_set_multiset_containers sg_set, sg_multiset and sgtree containers] @@ -1791,7 +1690,7 @@ And they also can receive additional options: [section:sg_set_multiset_example Example] -Now let's see a small example using both hooks and +Now let's see a small example using binary search tree hooks and [classref boost::intrusive::sg_set sg_set]/ [classref boost::intrusive::sg_multiset sg_multiset] containers: @@ -1841,50 +1740,9 @@ An empty, [classref boost::intrusive::treap_set treap_set], has also the size of 3 pointers and an integer (supposing empty function objects for key and priority comparison and constant-time size). -[section:treap_set_multiset_hooks Using binary search tree hooks: bs_set_base_hook and bs_set_member_hook] - -[classref boost::intrusive::treap_set treap_set], -[classref boost::intrusive::treap_multiset treap_multiset] and -[classref boost::intrusive::treap treap] don't use their -own hooks but plain binary search tree hooks. This has many advantages -since binary search tree hooks can also be used to insert values in -splay containers and scapegoat trees. - -[c++] - - template - class bs_set_base_hook; - -* [classref boost::intrusive::bs_set_base_hook bs_set_base_hook]: - the user class derives publicly from this class to make - it compatible with scapegoat tree based containers. - -[c++] - - template - class bs_set_member_hook; - -* [classref boost::intrusive::set_member_hook set_member_hook]: - the user class contains a public member of this class to make - it compatible with scapegoat tree based containers. - -[classref boost::intrusive::bs_set_base_hook bs_set_base_hook] and -[classref boost::intrusive::bs_set_member_hook bs_set_member_hook] receive -the same options explained in the section -[link intrusive.usage How to use Boost.Intrusive]: - -* [*`tag`] (for base hooks only): This argument serves as a tag, - so you can derive from more than one base hook. - Default: `tag`. - -* [*`link_mode`]: The linking policy. - Default: `link_mode`. - -* [*`void_pointer`]: The pointer type to be used - internally in the hook and propagated to the container. - Default: `void_pointer`. - -[endsect] +[*Boost.Intrusive] treap associative containers don't use their own hook types but plain Binary search tree hooks. +See [link intrusive.bst_hooks Binary search tree hooks: bs_set_base_hook and bs_set_member_hook] section for more +information about these hooks. [section:treap_set_multiset_containers treap_set, treap_multiset and treap containers] @@ -1967,7 +1825,7 @@ the strongest possible behaviour in these situations. In summary: [section:treap_set_multiset_example Example] -Now let's see a small example using both hooks and +Now let's see a small example using binary search tree hooks and [classref boost::intrusive::treap_set treap_set]/ [classref boost::intrusive::treap_multiset treap_multiset] containers: @@ -1979,6 +1837,48 @@ containers: [endsect] +[section:bst_hooks Binary search tree hooks: bs_set_base_hook and bs_set_member_hook] + +Binary search tree hooks can be used with several tree-like containers that don't +need any additional metadata for rebalancing operations. This has many advantages +since binary search tree hooks can also be used to insert values in +plain binary search tree, splay tree, scapegoat tree, and treap containers. + +[c++] + + template + class bs_set_base_hook; + +* [classref boost::intrusive::bs_set_base_hook bs_set_base_hook]: + the user class derives publicly from this class to make + it compatible with the mentioned tree based containers. + +[c++] + + template + class bs_set_member_hook; + +* [classref boost::intrusive::bs_set_member_hook bs_set_member_hook]: + the user class contains a public member of this class to make + it compatible with the mentioned tree based containers. + +[classref boost::intrusive::bs_set_base_hook bs_set_base_hook] and +[classref boost::intrusive::bs_set_member_hook bs_set_member_hook] receive +the same options explained in the section +[link intrusive.usage How to use Boost.Intrusive]: + +* [*`tag`] (for base hooks only): This argument serves as a tag, + so you can derive from more than one base hook. + Default: `tag`. + +* [*`link_mode`]: The linking policy. + Default: `link_mode`. + +* [*`void_pointer`]: The pointer type to be used + internally in the hook and propagated to the container. + Default: `void_pointer`. + +[endsect] [section:advanced_lookups_insertions Advanced lookup and insertion functions for associative containers] @@ -3582,7 +3482,7 @@ and also derives from `test_class`. `func_ptr_adaptor` is just a functor adaptor to convert function objects taking `test_list` objects to function objects taking pointers to them. -You can find the full test code code in the +You can find the full test code in the [@../../libs/intrusive/perf/perf_list.cpp perf_list.cpp] source file. [section:performance_results_push_back Back insertion and destruction] @@ -3884,10 +3784,28 @@ to be inserted in intrusive containers are allocated using `std::vector` or `std [section:release_notes Release Notes] +[section:release_notes_boost_1_56_00 Boost 1.56 Release] + +* 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. + +* Fixed bugs: + * [@https://svn.boost.org/trac/boost/ticket/9332 #9332: ['"has_member_function_callable_with.hpp compile error on msvc-12.0"]]. + +* Optimized tree rebalancing code to avoid redundant assignments. + +[endsect] + [section:release_notes_boost_1_55_00 Boost 1.55 Release] * [*Source breaking]: Deprecated `xxx_dont_splay` functions from splay containers. - Deprecated `splay_set_hook` from splay containers, use `bs_set_hook` instead. + Deprecated `splay_set_base_hook` and `splay_set_member_hook`from splay containers, use + `bs_set_base_hook` or `bs_set_member_hook` instead. Both will be removed in Boost 1.56. * [*ABI breaking]: Hash containers' end iterator was implemented pointing to one-past the end of the bucket array diff --git a/example/doc_auto_unlink.cpp b/example/doc_auto_unlink.cpp index 5fb12f4..b44dd31 100644 --- a/example/doc_auto_unlink.cpp +++ b/example/doc_auto_unlink.cpp @@ -24,7 +24,8 @@ class MyClass : public auto_unlink_hook public: MyClass(int i = 0) : int_(i) {} - void unlink() { auto_unlink_hook::unlink(); } + int get_int() { return int_; } + void unlink() { auto_unlink_hook::unlink(); } bool is_linked() { return auto_unlink_hook::is_linked(); } }; 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/example/doc_splay_set.cpp b/example/doc_splay_set.cpp index 45deceb..6c333b7 100644 --- a/example/doc_splay_set.cpp +++ b/example/doc_splay_set.cpp @@ -11,7 +11,6 @@ ///////////////////////////////////////////////////////////////////////////// //[doc_splay_set_code #include -#include #include #include @@ -20,14 +19,13 @@ using namespace boost::intrusive; class mytag; class MyClass - : public splay_set_base_hook<> //This is an splay tree base hook - , public bs_set_base_hook< tag > //This is a binary search tree base hook + : public bs_set_base_hook<> { int int_; public: //This is a member hook - splay_set_member_hook<> member_hook_; + bs_set_member_hook<> member_hook_; MyClass(int i) : int_(i) @@ -43,11 +41,8 @@ class MyClass //Define a set using the base hook that will store values in reverse order typedef splay_set< MyClass, compare > > BaseSplaySet; -//Define a set using the binary search tree hook -typedef splay_set< MyClass, base_hook > > > BaseBsSplaySet; - //Define an multiset using the member hook -typedef member_hook, &MyClass::member_hook_> MemberOption; +typedef member_hook, &MyClass::member_hook_> MemberOption; typedef splay_multiset< MyClass, MemberOption> MemberSplayMultiset; int main() @@ -59,21 +54,18 @@ int main() for(int i = 0; i < 100; ++i) values.push_back(MyClass(i)); BaseSplaySet baseset; - BaseBsSplaySet bsbaseset; MemberSplayMultiset membermultiset; //Insert values in the container for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it){ baseset.insert(*it); - bsbaseset.insert(*it); membermultiset.insert(*it); } //Now test sets { BaseSplaySet::reverse_iterator rbit(baseset.rbegin()); - BaseBsSplaySet::iterator bsit(bsbaseset.begin()); MemberSplayMultiset::iterator mit(membermultiset.begin()); VectIt it(values.begin()), itend(values.end()); @@ -83,8 +75,7 @@ int main() } //Test the objects inserted in member and binary search hook sets - for(it = values.begin(); it != itend; ++it, ++bsit, ++mit){ - if(&*bsit != &*it) return 1; + for(it = values.begin(); it != itend; ++it, ++mit){ if(&*mit != &*it) return 1; } } diff --git a/include/boost/intrusive/any_hook.hpp b/include/boost/intrusive/any_hook.hpp index 03c299f..b53df9f 100644 --- a/include/boost/intrusive/any_hook.hpp +++ b/include/boost/intrusive/any_hook.hpp @@ -75,7 +75,7 @@ struct make_any_base_hook //! \c link_mode<> will specify the linking mode of the hook (\c normal_link, \c safe_link). //! //! \c void_pointer<> is the pointer type that will be used internally in the hook -//! and the the container configured to use this hook. +//! and the container configured to use this hook. #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else @@ -175,7 +175,7 @@ struct make_any_member_hook //! \c link_mode<> will specify the linking mode of the hook (\c normal_link or \c safe_link). //! //! \c void_pointer<> is the pointer type that will be used internally in the hook -//! and the the container configured to use this hook. +//! and the container configured to use this hook. #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else diff --git a/include/boost/intrusive/avl_set.hpp b/include/boost/intrusive/avl_set.hpp index 061a086..ce2d178 100644 --- a/include/boost/intrusive/avl_set.hpp +++ b/include/boost/intrusive/avl_set.hpp @@ -249,13 +249,19 @@ class avl_set_impl template void clear_and_dispose(Disposer disposer); + #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::avltree::count(const_reference)const - size_type count(const_reference value) const; + size_type count(const_reference value) const + { return static_cast(this->tree_type::find(value) != this->tree_type::cend()); } //! @copydoc ::boost::intrusive::avltree::count(const KeyType&,KeyValueCompare)const template - size_type count(const KeyType& key, KeyValueCompare comp) const; - + size_type count(const KeyType& key, KeyValueCompare comp) const + { return static_cast(this->tree_type::find(key, comp) != this->tree_type::cend()); } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::avltree::lower_bound(const_reference) iterator lower_bound(const_reference value); @@ -298,21 +304,29 @@ class avl_set_impl template const_iterator find(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::avltree::equal_range(const_reference) - std::pair equal_range(const_reference value); + #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! @copydoc ::boost::intrusive::avltree::equal_range(const KeyType&,KeyValueCompare) + //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference) + std::pair equal_range(const_reference value) + { return this->tree_type::lower_bound_range(value); } + + //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare) template - std::pair equal_range(const KeyType& key, KeyValueCompare comp); + std::pair equal_range(const KeyType& key, KeyValueCompare comp) + { return this->tree_type::lower_bound_range(key, comp); } - //! @copydoc ::boost::intrusive::avltree::equal_range(const_reference)const + //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference)const std::pair - equal_range(const_reference value) const; + equal_range(const_reference value) const + { return this->tree_type::lower_bound_range(value); } - //! @copydoc ::boost::intrusive::avltree::equal_range(const KeyType&,KeyValueCompare)const + //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare)const template std::pair - equal_range(const KeyType& key, KeyValueCompare comp) const; + equal_range(const KeyType& key, KeyValueCompare comp) const + { return this->tree_type::lower_bound_range(key, comp); } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! @copydoc ::boost::intrusive::avltree::bounded_range(const_reference,const_reference,bool,bool) std::pair bounded_range @@ -692,7 +706,7 @@ class avl_multiset_impl //! @copydoc ::boost::intrusive::avltree::count(const KeyType&,KeyValueCompare)const template size_type count(const KeyType& key, KeyValueCompare comp) const; - + //! @copydoc ::boost::intrusive::avltree::lower_bound(const_reference) iterator lower_bound(const_reference value); diff --git a/include/boost/intrusive/avl_set_hook.hpp b/include/boost/intrusive/avl_set_hook.hpp index cd0478d..7cb3e3d 100644 --- a/include/boost/intrusive/avl_set_hook.hpp +++ b/include/boost/intrusive/avl_set_hook.hpp @@ -74,7 +74,7 @@ struct make_avl_set_base_hook //! unique tag. //! //! \c void_pointer<> is the pointer type that will be used internally in the hook -//! and the the container configured to use this hook. +//! and the container configured to use this hook. //! //! \c link_mode<> will specify the linking mode of the hook (\c normal_link, //! \c auto_unlink or \c safe_link). @@ -200,7 +200,7 @@ struct make_avl_set_member_hook //! \c link_mode<> and \c optimize_size<>. //! //! \c void_pointer<> is the pointer type that will be used internally in the hook -//! and the the container configured to use this hook. +//! and the container configured to use this hook. //! //! \c link_mode<> will specify the linking mode of the hook (\c normal_link, //! \c auto_unlink or \c safe_link). diff --git a/include/boost/intrusive/avltree.hpp b/include/boost/intrusive/avltree.hpp index f0cb9fe..7a53b39 100644 --- a/include/boost/intrusive/avltree.hpp +++ b/include/boost/intrusive/avltree.hpp @@ -13,6 +13,7 @@ #define BOOST_INTRUSIVE_AVLTREE_HPP #include +#include #include #include #include @@ -21,7 +22,6 @@ #include #include -#include #include #include #include @@ -296,7 +296,7 @@ class avltree_impl //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const template size_type count(const KeyType& key, KeyValueCompare comp) const; - + //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference) iterator lower_bound(const_reference value); @@ -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/avltree_algorithms.hpp b/include/boost/intrusive/avltree_algorithms.hpp index 1dc2acf..e6127b8 100644 --- a/include/boost/intrusive/avltree_algorithms.hpp +++ b/include/boost/intrusive/avltree_algorithms.hpp @@ -15,9 +15,9 @@ #define BOOST_INTRUSIVE_AVLTREE_ALGORITHMS_HPP #include +#include #include -#include #include #include @@ -49,15 +49,6 @@ struct avltree_node_cloner } }; -template -struct avltree_erase_fixup -{ - typedef typename NodeTraits::node_ptr node_ptr; - - void operator()(const node_ptr & to_erase, const node_ptr & successor) - { NodeTraits::set_balance(successor, NodeTraits::get_balance(to_erase)); } -}; - /// @endcond //! avltree_algorithms is configured with a NodeTraits class, which encapsulates the @@ -225,7 +216,10 @@ class avltree_algorithms static node_ptr erase(const node_ptr & header, const node_ptr & z) { typename bstree_algo::data_for_rebalance info; - bstree_algo::erase(header, z, avltree_erase_fixup(), info); + bstree_algo::erase(header, z, info); + if(info.y != z){ + NodeTraits::set_balance(info.y, NodeTraits::get_balance(z)); + } //Rebalance avltree rebalance_after_erasure(header, info.x, info.x_parent); return z; @@ -274,6 +268,7 @@ class avltree_algorithms //! @copydoc ::boost::intrusive::bstree_algorithms::count(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) template static std::size_t count(const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp); + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal_upper_bound(const node_ptr&,const node_ptr&,NodePtrCompare) @@ -357,40 +352,92 @@ class avltree_algorithms /// @cond + static bool verify(const node_ptr &header) + { + std::size_t height; + std::size_t count; + return verify_recursion(NodeTraits::get_parent(header), count, height); + } + private: - static void rebalance_after_erasure(const node_ptr & header, const node_ptr & xnode, const node_ptr & xnode_parent) + static bool verify_recursion(node_ptr n, std::size_t &count, std::size_t &height) + { + if (!n){ + count = 0; + height = 0; + return true; + } + std::size_t leftcount, rightcount; + std::size_t leftheight, rightheight; + if(!verify_recursion(NodeTraits::get_left (n), leftcount, leftheight) || + !verify_recursion(NodeTraits::get_right(n), rightcount, rightheight) ){ + return false; + } + count = 1u + leftcount + rightcount; + height = 1u + (leftheight > rightheight ? leftheight : rightheight); + + //If equal height, balance must be zero + if(rightheight == leftheight){ + if(NodeTraits::get_balance(n) != NodeTraits::zero()){ + BOOST_ASSERT(0); + return false; + } + } + //If right is taller than left, then the difference must be at least 1 and the balance positive + else if(rightheight > leftheight){ + if(rightheight - leftheight > 1 ){ + BOOST_ASSERT(0); + return false; + } + else if(NodeTraits::get_balance(n) != NodeTraits::positive()){ + BOOST_ASSERT(0); + return false; + } + } + //If left is taller than right, then the difference must be at least 1 and the balance negative + else{ + if(leftheight - rightheight > 1 ){ + BOOST_ASSERT(0); + return false; + } + else if(NodeTraits::get_balance(n) != NodeTraits::negative()){ + BOOST_ASSERT(0); + return false; + } + } + return true; + } + + static void rebalance_after_erasure(const node_ptr & header, node_ptr x, node_ptr x_parent) { - node_ptr x(xnode), x_parent(xnode_parent); for (node_ptr root = NodeTraits::get_parent(header); x != root; root = NodeTraits::get_parent(header)) { const balance x_parent_balance = NodeTraits::get_balance(x_parent); + //Don't cache x_is_leftchild or similar because x can be null and + //equal to both x_parent_left and x_parent_right + const node_ptr x_parent_left (NodeTraits::get_left(x_parent)); + const node_ptr x_parent_right(NodeTraits::get_right(x_parent)); + if(x_parent_balance == NodeTraits::zero()){ - NodeTraits::set_balance(x_parent, - (x == NodeTraits::get_right(x_parent) ? NodeTraits::negative() : NodeTraits::positive())); + NodeTraits::set_balance( x_parent, x == x_parent_right ? NodeTraits::negative() : NodeTraits::positive() ); break; // the height didn't change, let's stop here } else if(x_parent_balance == NodeTraits::negative()){ - if (x == NodeTraits::get_left(x_parent)) { + if (x == x_parent_left) { ////x is left child or x and sibling are null NodeTraits::set_balance(x_parent, NodeTraits::zero()); // balanced x = x_parent; - x_parent = NodeTraits::get_parent(x_parent); } else { - // x is right child - // a is left child - node_ptr a = NodeTraits::get_left(x_parent); - BOOST_INTRUSIVE_INVARIANT_ASSERT(a); - if (NodeTraits::get_balance(a) == NodeTraits::positive()) { - // a MUST have a right child - BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_right(a)); - rotate_left_right(x_parent, header); - x = NodeTraits::get_parent(x_parent); - x_parent = NodeTraits::get_parent(x); + // x is right child (x_parent_left is the left child) + BOOST_INTRUSIVE_INVARIANT_ASSERT(x_parent_left); + if (NodeTraits::get_balance(x_parent_left) == NodeTraits::positive()) { + // x_parent_left MUST have a right child + BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_right(x_parent_left)); + x = avl_rotate_left_right(x_parent, x_parent_left, header); } else { - rotate_right(x_parent, header); - x = NodeTraits::get_parent(x_parent); - x_parent = NodeTraits::get_parent(x); + avl_rotate_right(x_parent, x_parent_left, header); + x = x_parent_left; } // if changed from negative to NodeTraits::positive(), no need to check above @@ -400,28 +447,22 @@ class avltree_algorithms } } else if(x_parent_balance == NodeTraits::positive()){ - if (x == NodeTraits::get_right(x_parent)) { + if (x == x_parent_right) { //x is right child or x and sibling are null NodeTraits::set_balance(x_parent, NodeTraits::zero()); // balanced x = x_parent; - x_parent = NodeTraits::get_parent(x_parent); } else { - // x is left child - // a is right child - node_ptr a = NodeTraits::get_right(x_parent); - BOOST_INTRUSIVE_INVARIANT_ASSERT(a); - if (NodeTraits::get_balance(a) == NodeTraits::negative()) { - // a MUST have then a left child - BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_left(a)); - rotate_right_left(x_parent, header); - - x = NodeTraits::get_parent(x_parent); - x_parent = NodeTraits::get_parent(x); + // x is left child (x_parent_right is the right child) + const node_ptr x_parent_right(NodeTraits::get_right(x_parent)); + BOOST_INTRUSIVE_INVARIANT_ASSERT(x_parent_right); + if (NodeTraits::get_balance(x_parent_right) == NodeTraits::negative()) { + // x_parent_right MUST have then a left child + BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_left(x_parent_right)); + x = avl_rotate_right_left(x_parent, x_parent_right, header); } else { - rotate_left(x_parent, header); - x = NodeTraits::get_parent(x_parent); - x_parent = NodeTraits::get_parent(x); + avl_rotate_left(x_parent, x_parent_right, header); + x = x_parent_right; } // if changed from NodeTraits::positive() to negative, no need to check above if (NodeTraits::get_balance(x) == NodeTraits::negative()){ @@ -432,47 +473,47 @@ class avltree_algorithms else{ BOOST_INTRUSIVE_INVARIANT_ASSERT(false); // never reached } + x_parent = NodeTraits::get_parent(x); } } - static void rebalance_after_insertion(const node_ptr & header, const node_ptr & xnode) + static void rebalance_after_insertion(const node_ptr & header, node_ptr x) { - node_ptr x(xnode); NodeTraits::set_balance(x, NodeTraits::zero()); // Rebalance. for(node_ptr root = NodeTraits::get_parent(header); x != root; root = NodeTraits::get_parent(header)){ - const balance x_parent_balance = NodeTraits::get_balance(NodeTraits::get_parent(x)); - + node_ptr const x_parent(NodeTraits::get_parent(x)); + node_ptr const x_parent_left(NodeTraits::get_left(x_parent)); + const balance x_parent_balance = NodeTraits::get_balance(x_parent); + const bool x_is_leftchild(x == x_parent_left); if(x_parent_balance == NodeTraits::zero()){ // if x is left, parent will have parent->bal_factor = negative // else, parent->bal_factor = NodeTraits::positive() - NodeTraits::set_balance( NodeTraits::get_parent(x) - , x == NodeTraits::get_left(NodeTraits::get_parent(x)) - ? NodeTraits::negative() : NodeTraits::positive() ); - x = NodeTraits::get_parent(x); + NodeTraits::set_balance( x_parent, x_is_leftchild ? NodeTraits::negative() : NodeTraits::positive() ); + x = x_parent; } else if(x_parent_balance == NodeTraits::positive()){ // if x is a left child, parent->bal_factor = zero - if (x == NodeTraits::get_left(NodeTraits::get_parent(x))) - NodeTraits::set_balance(NodeTraits::get_parent(x), NodeTraits::zero()); + if (x_is_leftchild) + NodeTraits::set_balance(x_parent, NodeTraits::zero()); else{ // x is a right child, needs rebalancing if (NodeTraits::get_balance(x) == NodeTraits::negative()) - rotate_right_left(NodeTraits::get_parent(x), header); + avl_rotate_right_left(x_parent, x, header); else - rotate_left(NodeTraits::get_parent(x), header); + avl_rotate_left(x_parent, x, header); } break; } else if(x_parent_balance == NodeTraits::negative()){ // if x is a left child, needs rebalancing - if (x == NodeTraits::get_left(NodeTraits::get_parent(x))) { + if (x_is_leftchild) { if (NodeTraits::get_balance(x) == NodeTraits::positive()) - rotate_left_right(NodeTraits::get_parent(x), header); + avl_rotate_left_right(x_parent, x, header); else - rotate_right(NodeTraits::get_parent(x), header); + avl_rotate_right(x_parent, x, header); } else - NodeTraits::set_balance(NodeTraits::get_parent(x), NodeTraits::zero()); + NodeTraits::set_balance(x_parent, NodeTraits::zero()); break; } else{ @@ -486,26 +527,28 @@ class avltree_algorithms // balancing... const balance c_balance = NodeTraits::get_balance(c); const balance zero_balance = NodeTraits::zero(); + const balance posi_balance = NodeTraits::positive(); + const balance nega_balance = NodeTraits::negative(); NodeTraits::set_balance(c, zero_balance); - if(c_balance == NodeTraits::negative()){ - NodeTraits::set_balance(a, NodeTraits::positive()); + if(c_balance == nega_balance){ + NodeTraits::set_balance(a, posi_balance); NodeTraits::set_balance(b, zero_balance); } else if(c_balance == zero_balance){ NodeTraits::set_balance(a, zero_balance); NodeTraits::set_balance(b, zero_balance); } - else if(c_balance == NodeTraits::positive()){ + else if(c_balance == posi_balance){ NodeTraits::set_balance(a, zero_balance); - NodeTraits::set_balance(b, NodeTraits::negative()); + NodeTraits::set_balance(b, nega_balance); } else{ BOOST_INTRUSIVE_INVARIANT_ASSERT(false); // never reached } } - static void rotate_left_right(const node_ptr a, const node_ptr & hdr) - { + static node_ptr avl_rotate_left_right(const node_ptr a, const node_ptr a_oldleft, const node_ptr & hdr) + { // [note: 'a_oldleft' is 'b'] // | | // // a(-2) c // // / \ / \ // @@ -513,16 +556,19 @@ class avltree_algorithms // (pos)b [g] b a // // / \ / \ / \ // // [d] c [d] e f [g] // - // / \ // - // e f // - node_ptr b = NodeTraits::get_left(a), c = NodeTraits::get_right(b); - bstree_algo::rotate_left(b, hdr); - bstree_algo::rotate_right(a, hdr); - left_right_balancing(a, b, c); + // / \ // + // e f // + const node_ptr c = NodeTraits::get_right(a_oldleft); + bstree_algo::rotate_left_no_parent_fix(a_oldleft, c); + //No need to link c with a [NodeTraits::set_parent(c, a) + NodeTraits::set_left(a, c)] + //as c is not root and another rotation is coming + bstree_algo::rotate_right(a, c, NodeTraits::get_parent(a), hdr); + left_right_balancing(a, a_oldleft, c); + return c; } - static void rotate_right_left(const node_ptr a, const node_ptr & hdr) - { + static node_ptr avl_rotate_right_left(const node_ptr a, const node_ptr a_oldright, const node_ptr & hdr) + { // [note: 'a_oldright' is 'b'] // | | // // a(pos) c // // / \ / \ // @@ -532,41 +578,42 @@ class avltree_algorithms // c [g] [d] e f [g] // // / \ // // e f // - node_ptr b = NodeTraits::get_right(a), c = NodeTraits::get_left(b); - bstree_algo::rotate_right(b, hdr); - bstree_algo::rotate_left(a, hdr); - left_right_balancing(b, a, c); + const node_ptr c (NodeTraits::get_left(a_oldright)); + bstree_algo::rotate_right_no_parent_fix(a_oldright, c); + //No need to link c with a [NodeTraits::set_parent(c, a) + NodeTraits::set_right(a, c)] + //as c is not root and another rotation is coming. + bstree_algo::rotate_left(a, c, NodeTraits::get_parent(a), hdr); + left_right_balancing(a_oldright, a, c); + return c; } - static void rotate_left(const node_ptr x, const node_ptr & hdr) + static void avl_rotate_left(const node_ptr &x, const node_ptr &x_oldright, const node_ptr & hdr) { - const node_ptr y = NodeTraits::get_right(x); - bstree_algo::rotate_left(x, hdr); + bstree_algo::rotate_left(x, x_oldright, NodeTraits::get_parent(x), hdr); // reset the balancing factor - if (NodeTraits::get_balance(y) == NodeTraits::positive()) { + if (NodeTraits::get_balance(x_oldright) == NodeTraits::positive()) { NodeTraits::set_balance(x, NodeTraits::zero()); - NodeTraits::set_balance(y, NodeTraits::zero()); + NodeTraits::set_balance(x_oldright, NodeTraits::zero()); } else { // this doesn't happen during insertions NodeTraits::set_balance(x, NodeTraits::positive()); - NodeTraits::set_balance(y, NodeTraits::negative()); + NodeTraits::set_balance(x_oldright, NodeTraits::negative()); } } - static void rotate_right(const node_ptr x, const node_ptr & hdr) + static void avl_rotate_right(const node_ptr &x, const node_ptr &x_oldleft, const node_ptr & hdr) { - const node_ptr y = NodeTraits::get_left(x); - bstree_algo::rotate_right(x, hdr); + bstree_algo::rotate_right(x, x_oldleft, NodeTraits::get_parent(x), hdr); // reset the balancing factor - if (NodeTraits::get_balance(y) == NodeTraits::negative()) { + if (NodeTraits::get_balance(x_oldleft) == NodeTraits::negative()) { NodeTraits::set_balance(x, NodeTraits::zero()); - NodeTraits::set_balance(y, NodeTraits::zero()); + NodeTraits::set_balance(x_oldleft, NodeTraits::zero()); } else { // this doesn't happen during insertions NodeTraits::set_balance(x, NodeTraits::negative()); - NodeTraits::set_balance(y, NodeTraits::positive()); + NodeTraits::set_balance(x_oldleft, NodeTraits::positive()); } } diff --git a/include/boost/intrusive/bs_set.hpp b/include/boost/intrusive/bs_set.hpp index 2062d49..9768382 100644 --- a/include/boost/intrusive/bs_set.hpp +++ b/include/boost/intrusive/bs_set.hpp @@ -247,13 +247,19 @@ class bs_set_impl template void clear_and_dispose(Disposer disposer); + #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::bstree::count(const_reference)const - size_type count(const_reference value) const; + size_type count(const_reference value) const + { return static_cast(this->tree_type::find(value) == this->tree_type::cend()); } //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const template - size_type count(const KeyType& key, KeyValueCompare comp) const; - + size_type count(const KeyType& key, KeyValueCompare comp) const + { return static_cast(this->tree_type::find(key, comp) == this->tree_type::cend()); } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference) iterator lower_bound(const_reference value); @@ -296,21 +302,29 @@ class bs_set_impl template const_iterator find(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::equal_range(const_reference) - std::pair equal_range(const_reference value); + #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare) + //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference) + std::pair equal_range(const_reference value) + { return this->tree_type::lower_bound_range(value); } + + //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare) template - std::pair equal_range(const KeyType& key, KeyValueCompare comp); + std::pair equal_range(const KeyType& key, KeyValueCompare comp) + { return this->tree_type::lower_bound_range(key, comp); } - //! @copydoc ::boost::intrusive::bstree::equal_range(const_reference)const + //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference)const std::pair - equal_range(const_reference value) const; + equal_range(const_reference value) const + { return this->tree_type::lower_bound_range(value); } - //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare)const + //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare)const template std::pair - equal_range(const KeyType& key, KeyValueCompare comp) const; + equal_range(const KeyType& key, KeyValueCompare comp) const + { return this->tree_type::lower_bound_range(key, comp); } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! @copydoc ::boost::intrusive::bstree::bounded_range(const_reference,const_reference,bool,bool) std::pair bounded_range diff --git a/include/boost/intrusive/bs_set_hook.hpp b/include/boost/intrusive/bs_set_hook.hpp index 1f16971..2ac050e 100644 --- a/include/boost/intrusive/bs_set_hook.hpp +++ b/include/boost/intrusive/bs_set_hook.hpp @@ -73,7 +73,7 @@ struct make_bs_set_base_hook //! unique tag. //! //! \c void_pointer<> is the pointer type that will be used internally in the hook -//! and the the container configured to use this hook. +//! and the container configured to use this hook. //! //! \c link_mode<> will specify the linking mode of the hook (\c normal_link, //! \c auto_unlink or \c safe_link). @@ -196,7 +196,7 @@ struct make_bs_set_member_hook //! The hook admits the following options: \c void_pointer<>, \c link_mode<>. //! //! \c void_pointer<> is the pointer type that will be used internally in the hook -//! and the the container configured to use this hook. +//! and the container configured to use this hook. //! //! \c link_mode<> will specify the linking mode of the hook (\c normal_link, //! \c auto_unlink or \c safe_link). diff --git a/include/boost/intrusive/bstree_algorithms.hpp b/include/boost/intrusive/bstree_algorithms.hpp index 78c49d6..d155d6d 100644 --- a/include/boost/intrusive/bstree_algorithms.hpp +++ b/include/boost/intrusive/bstree_algorithms.hpp @@ -14,8 +14,8 @@ #define BOOST_INTRUSIVE_BSTREE_ALGORITHMS_HPP #include -#include #include +#include #include #include #include @@ -173,7 +173,20 @@ class bstree_algorithms static node_ptr end_node(const const_node_ptr & header) { return detail::uncast(header); } - //! Requires: 'node' is a node of the tree or an node initialized + //! 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. //! //! Effects: Returns true if the node is initialized by init() or init_node(). @@ -487,18 +500,18 @@ class bstree_algorithms //! Throws: Nothing. static node_ptr next_node(const node_ptr & node) { - node_ptr p_right(NodeTraits::get_right(node)); - if(p_right){ - return minimum(p_right); + node_ptr const n_right(NodeTraits::get_right(node)); + if(n_right){ + return minimum(n_right); } else { - node_ptr p(node); - node_ptr x = NodeTraits::get_parent(p); - while(p == NodeTraits::get_right(x)){ - p = x; - x = NodeTraits::get_parent(x); + node_ptr n(node); + node_ptr p(NodeTraits::get_parent(n)); + while(n == NodeTraits::get_right(p)){ + n = p; + p = NodeTraits::get_parent(p); } - return NodeTraits::get_right(p) != x ? x : detail::uncast(p); + return NodeTraits::get_right(n) != p ? p : n; } } @@ -536,7 +549,7 @@ class bstree_algorithms //! Complexity: Logarithmic to the size of the subtree. //! //! Throws: Nothing. - static node_ptr minimum (node_ptr node) + static node_ptr minimum(node_ptr node) { for(node_ptr p_left = NodeTraits::get_left(node) ;p_left @@ -766,7 +779,7 @@ class bstree_algorithms //! ordering compatible with the strict weak ordering used to create the //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs. //! - //! Effects: Returns an node_ptr to the element that is equivalent to + //! Effects: Returns a node_ptr to the first element that is equivalent to //! "key" according to "comp" or "header" if that element does not exist. //! //! Complexity: Logarithmic. @@ -825,7 +838,6 @@ class bstree_algorithms //If the upper_key is less than x, the target //range is on the left part else if(comp(upper_key, x)){ - //y > upper_key y = x; x = NodeTraits::get_left(x); } @@ -864,7 +876,7 @@ class bstree_algorithms //! ordering compatible with the strict weak ordering used to create the //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs. //! - //! Effects: Returns the number of elements with a key equivalent to "key"pair of node_ptr delimiting a range containing + //! Effects: Returns the number of elements with a key equivalent to "key" //! according to "comp". //! //! Complexity: Logarithmic. @@ -908,7 +920,32 @@ class bstree_algorithms //! ordering compatible with the strict weak ordering used to create the //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs. //! - //! Effects: Returns an node_ptr to the first element that is + //! Effects: Returns an a pair of node_ptr delimiting a range containing + //! the first element that is equivalent to "key" according to "comp" or an + //! empty range that indicates the position where that element would be + //! if there are no equivalent elements. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If "comp" throws. + template + static std::pair lower_bound_range + (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) + { + node_ptr const lb(lower_bound(header, key, comp)); + std::pair ret_ii(lb, lb); + if(lb != header && !comp(key, lb)){ + ret_ii.second = next_node(ret_ii.second); + } + return ret_ii; + } + + //! Requires: "header" must be the header node of a tree. + //! KeyNodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs. + //! + //! Effects: Returns a node_ptr to the first element that is //! not less than "key" according to "comp" or "header" if that element does //! not exist. //! @@ -927,7 +964,7 @@ class bstree_algorithms //! ordering compatible with the strict weak ordering used to create the //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs. //! - //! Effects: Returns an node_ptr to the first element that is greater + //! Effects: Returns a node_ptr to the first element that is greater //! than "key" according to "comp" or "header" if that element does not exist. //! //! Complexity: Logarithmic. @@ -1025,16 +1062,12 @@ class bstree_algorithms //Since we've found the upper bound there is no other value with the same key if: // - There is no previous node // - The previous node is less than the key - if(!prev || comp(prev, key)){ + const bool not_present = !prev || comp(prev, key); + if(not_present){ commit_data.link_left = left_child; commit_data.node = y; - return std::pair(node_ptr(), true); - } - //If the previous value was not less than key, it means that it's equal - //(because we've checked the upper bound) - else{ - return std::pair(prev, false); } + return std::pair(prev, not_present); } //! Requires: "header" must be the header node of a tree. @@ -1325,7 +1358,7 @@ class bstree_algorithms static void erase(const node_ptr & header, const node_ptr & z) { data_for_rebalance ignored; - erase_impl(header, z, ignored); + erase(header, z, ignored); } //! Requires: node is a tree node but not the header. @@ -1410,6 +1443,88 @@ class bstree_algorithms } protected: + static void erase(const node_ptr & header, const node_ptr & z, data_for_rebalance &info) + { + node_ptr y(z); + node_ptr x; + const node_ptr z_left(NodeTraits::get_left(z)); + const node_ptr z_right(NodeTraits::get_right(z)); + + if(!z_left){ + x = z_right; // x might be null. + } + else if(!z_right){ // z has exactly one non-null child. y == z. + x = z_left; // x is not null. + BOOST_ASSERT(x); + } + else{ //make y != z + // y = find z's successor + y = bstree_algorithms::minimum(z_right); + x = NodeTraits::get_right(y); // x might be null. + } + + node_ptr x_parent; + const node_ptr z_parent(NodeTraits::get_parent(z)); + const bool z_is_leftchild(NodeTraits::get_left(z_parent) == z); + + if(y != z){ //has two children and y is the minimum of z + //y is z's successor and it has a null left child. + //x is the right child of y (it can be null) + //Relink y in place of z and link x with y's old parent + NodeTraits::set_parent(z_left, y); + NodeTraits::set_left(y, z_left); + if(y != z_right){ + //Link y with the right tree of z + NodeTraits::set_right(y, z_right); + NodeTraits::set_parent(z_right, y); + //Link x with y's old parent (y must be a left child) + x_parent = NodeTraits::get_parent(y); + BOOST_ASSERT(NodeTraits::get_left(x_parent) == y); + if(x) + NodeTraits::set_parent(x, x_parent); + //Since y was the successor and not the right child of z, it must be a left child + NodeTraits::set_left(x_parent, x); + } + else{ //y was the right child of y so no need to fix x's position + x_parent = y; + } + NodeTraits::set_parent(y, z_parent); + bstree_algorithms::set_child(header, y, z_parent, z_is_leftchild); + } + else { // z has zero or one child, x is one child (it can be null) + //Just link x to z's parent + x_parent = z_parent; + if(x) + NodeTraits::set_parent(x, z_parent); + bstree_algorithms::set_child(header, x, z_parent, z_is_leftchild); + + //Now update leftmost/rightmost in case z was one of them + if(NodeTraits::get_left(header) == z){ + //z_left must be null because z is the leftmost + BOOST_ASSERT(!z_left); + NodeTraits::set_left(header, !z_right ? + z_parent : // makes leftmost == header if z == root + bstree_algorithms::minimum(z_right)); + } + if(NodeTraits::get_right(header) == z){ + //z_right must be null because z is the rightmost + BOOST_ASSERT(!z_right); + NodeTraits::set_right(header, !z_left ? + z_parent : // makes rightmost == header if z == root + bstree_algorithms::maximum(z_left)); + } + } + + //If z had 0/1 child, y == z and one of its children (and maybe null) + //If z had 2 children, y is the successor of z and x is the right child of y + info.x = x; + info.y = y; + //If z had 0/1 child, x_parent is the new parent of the old right child of y (z's successor) + //If z had 2 children, x_parent is the new parent of y (z_parent) + BOOST_ASSERT(!x || NodeTraits::get_parent(x) == x_parent); + info.x_parent = x_parent; + } + //! Requires: node is a node of the tree but it's not the header. //! //! Effects: Returns the number of nodes of the subtree. @@ -1473,83 +1588,6 @@ class bstree_algorithms static bool is_right_child(const node_ptr & p) { return NodeTraits::get_right(NodeTraits::get_parent(p)) == p; } - template - static void erase(const node_ptr & header, const node_ptr & z, F z_and_successor_fixup, data_for_rebalance &info) - { - erase_impl(header, z, info); - if(info.y != z){ - z_and_successor_fixup(z, info.y); - } - } - - //Fix header and own's parent data when replacing x with own, providing own's old data with parent - static void replace_own_impl(const node_ptr & own, const node_ptr & x, const node_ptr & header, const node_ptr & own_parent, bool own_was_left) - { - if(NodeTraits::get_parent(header) == own) - NodeTraits::set_parent(header, x); - else if(own_was_left) - NodeTraits::set_left(own_parent, x); - else - NodeTraits::set_right(own_parent, x); - } - - //Fix header and own's parent data when replacing x with own, supposing own - //links with its parent are still ok - static void replace_own(const node_ptr & own, const node_ptr & x, const node_ptr & header) - { - node_ptr own_parent(NodeTraits::get_parent(own)); - bool own_is_left(NodeTraits::get_left(own_parent) == own); - replace_own_impl(own, x, header, own_parent, own_is_left); - } - - // rotate parent p to left (no header and p's parent fixup) - static node_ptr rotate_left(const node_ptr & p) - { - node_ptr x(NodeTraits::get_right(p)); - node_ptr x_left(NodeTraits::get_left(x)); - NodeTraits::set_right(p, x_left); - if(x_left){ - NodeTraits::set_parent(x_left, p); - } - NodeTraits::set_left(x, p); - NodeTraits::set_parent(p, x); - return x; - } - - // rotate parent p to left (with header and p's parent fixup) - static void rotate_left(const node_ptr & p, const node_ptr & header) - { - bool p_was_left(is_left_child(p)); - node_ptr p_old_parent(NodeTraits::get_parent(p)); - node_ptr x(rotate_left(p)); - NodeTraits::set_parent(x, p_old_parent); - replace_own_impl(p, x, header, p_old_parent, p_was_left); - } - - // rotate parent p to right (no header and p's parent fixup) - static node_ptr rotate_right(const node_ptr & p) - { - node_ptr x(NodeTraits::get_left(p)); - node_ptr x_right(NodeTraits::get_right(x)); - NodeTraits::set_left(p, x_right); - if(x_right){ - NodeTraits::set_parent(x_right, p); - } - NodeTraits::set_right(x, p); - NodeTraits::set_parent(p, x); - return x; - } - - // rotate parent p to right (with header and p's parent fixup) - static void rotate_right(const node_ptr & p, const node_ptr & header) - { - bool p_was_left(is_left_child(p)); - node_ptr p_old_parent(NodeTraits::get_parent(p)); - node_ptr x(rotate_right(p)); - NodeTraits::set_parent(x, p_old_parent); - replace_own_impl(p, x, header, p_old_parent, p_was_left); - } - static void insert_before_check (const node_ptr &header, const node_ptr & pos , insert_commit_data &commit_data @@ -1631,12 +1669,40 @@ class bstree_algorithms template static void insert_equal_upper_bound_check (const node_ptr & h, const node_ptr & new_node, NodePtrCompare comp, insert_commit_data & commit_data, std::size_t *pdepth = 0) - { insert_equal_check_impl(true, h, new_node, comp, commit_data, pdepth); } + { + std::size_t depth = 0; + node_ptr y(h); + node_ptr x(NodeTraits::get_parent(y)); + + while(x){ + ++depth; + y = x; + x = comp(new_node, x) ? + NodeTraits::get_left(x) : NodeTraits::get_right(x); + } + if(pdepth) *pdepth = depth; + commit_data.link_left = (y == h) || comp(new_node, y); + commit_data.node = y; + } template static void insert_equal_lower_bound_check (const node_ptr & h, const node_ptr & new_node, NodePtrCompare comp, insert_commit_data & commit_data, std::size_t *pdepth = 0) - { insert_equal_check_impl(false, h, new_node, comp, commit_data, pdepth); } + { + std::size_t depth = 0; + node_ptr y(h); + node_ptr x(NodeTraits::get_parent(y)); + + while(x){ + ++depth; + y = x; + x = !comp(x, new_node) ? + NodeTraits::get_left(x) : NodeTraits::get_right(x); + } + if(pdepth) *pdepth = depth; + commit_data.link_left = (y == h) || !comp(y, new_node); + commit_data.node = y; + } static void insert_commit (const node_ptr & header, const node_ptr & new_node, const insert_commit_data &commit_data) @@ -1664,7 +1730,61 @@ class bstree_algorithms NodeTraits::set_left(new_node, node_ptr()); } + //Fix header and own's parent data when replacing x with own, providing own's old data with parent + static void set_child(const node_ptr & header, const node_ptr & new_child, const node_ptr & new_parent, const bool link_left) + { + if(new_parent == header) + NodeTraits::set_parent(header, new_child); + else if(link_left) + NodeTraits::set_left(new_parent, new_child); + else + NodeTraits::set_right(new_parent, new_child); + } + + // rotate p to left (no header and p's parent fixup) + static void rotate_left_no_parent_fix(const node_ptr & p, const node_ptr &p_right) + { + node_ptr p_right_left(NodeTraits::get_left(p_right)); + NodeTraits::set_right(p, p_right_left); + if(p_right_left){ + NodeTraits::set_parent(p_right_left, p); + } + NodeTraits::set_left(p_right, p); + NodeTraits::set_parent(p, p_right); + } + + // rotate p to left (with header and p's parent fixup) + static void rotate_left(const node_ptr & p, const node_ptr & p_right, const node_ptr & p_parent, const node_ptr & header) + { + const bool p_was_left(NodeTraits::get_left(p_parent) == p); + rotate_left_no_parent_fix(p, p_right); + NodeTraits::set_parent(p_right, p_parent); + set_child(header, p_right, p_parent, p_was_left); + } + + // rotate p to right (no header and p's parent fixup) + static void rotate_right_no_parent_fix(const node_ptr & p, const node_ptr &p_left) + { + node_ptr p_left_right(NodeTraits::get_right(p_left)); + NodeTraits::set_left(p, p_left_right); + if(p_left_right){ + NodeTraits::set_parent(p_left_right, p); + } + NodeTraits::set_right(p_left, p); + NodeTraits::set_parent(p, p_left); + } + + // rotate p to right (with header and p's parent fixup) + static void rotate_right(const node_ptr & p, const node_ptr & p_left, const node_ptr & p_parent, const node_ptr & header) + { + const bool p_was_left(NodeTraits::get_left(p_parent) == p); + rotate_right_no_parent_fix(p, p_left); + NodeTraits::set_parent(p_left, p_parent); + set_child(header, p_left, p_parent, p_was_left); + } + private: + static void subtree_to_vine(node_ptr vine_tail, std::size_t &size) { //Inspired by LibAVL: @@ -1877,98 +1997,6 @@ class bstree_algorithms } return y; } - - - template - static void insert_equal_check_impl - (bool upper, const node_ptr & h, const node_ptr & new_node, NodePtrCompare comp, insert_commit_data & commit_data, std::size_t *pdepth = 0) - { - std::size_t depth = 0; - node_ptr y(h); - node_ptr x(NodeTraits::get_parent(y)); - bool link_left; - - if(upper){ - while(x){ - ++depth; - y = x; - x = comp(new_node, x) ? - NodeTraits::get_left(x) : NodeTraits::get_right(x); - } - link_left = (y == h) || comp(new_node, y); - } - else{ - while(x){ - ++depth; - y = x; - x = !comp(x, new_node) ? - NodeTraits::get_left(x) : NodeTraits::get_right(x); - } - link_left = (y == h) || !comp(y, new_node); - } - - commit_data.link_left = link_left; - commit_data.node = y; - if(pdepth) *pdepth = depth; - } - - static void erase_impl(const node_ptr & header, const node_ptr & z, data_for_rebalance &info) - { - node_ptr y(z); - node_ptr x; - node_ptr x_parent = node_ptr(); - node_ptr z_left(NodeTraits::get_left(z)); - node_ptr z_right(NodeTraits::get_right(z)); - if(!z_left){ - x = z_right; // x might be null. - } - else if(!z_right){ // z has exactly one non-null child. y == z. - x = z_left; // x is not null. - } - else{ - // find z's successor - y = bstree_algorithms::minimum (z_right); - x = NodeTraits::get_right(y); // x might be null. - } - - if(y != z){ - // relink y in place of z. y is z's successor - NodeTraits::set_parent(NodeTraits::get_left(z), y); - NodeTraits::set_left(y, NodeTraits::get_left(z)); - if(y != NodeTraits::get_right(z)){ - x_parent = NodeTraits::get_parent(y); - if(x) - NodeTraits::set_parent(x, x_parent); - NodeTraits::set_left(x_parent, x); // y must be a child of left_ - NodeTraits::set_right(y, NodeTraits::get_right(z)); - NodeTraits::set_parent(NodeTraits::get_right(z), y); - } - else - x_parent = y; - bstree_algorithms::replace_own (z, y, header); - NodeTraits::set_parent(y, NodeTraits::get_parent(z)); - } - else { // y == z --> z has only one child, or void - x_parent = NodeTraits::get_parent(z); - if(x) - NodeTraits::set_parent(x, x_parent); - bstree_algorithms::replace_own (z, x, header); - if(NodeTraits::get_left(header) == z){ - NodeTraits::set_left(header, !NodeTraits::get_right(z) ? // z->get_left() must be null also - NodeTraits::get_parent(z) : // makes leftmost == header if z == root - bstree_algorithms::minimum (x)); - } - if(NodeTraits::get_right(header) == z){ - NodeTraits::set_right(header, !NodeTraits::get_left(z) ? // z->get_right() must be null also - NodeTraits::get_parent(z) : // makes rightmost == header if z == root - bstree_algorithms::maximum(x)); - } - } - - info.x = x; - info.x_parent = x_parent; - info.y = y; - } }; /// @cond diff --git a/include/boost/intrusive/derivation_value_traits.hpp b/include/boost/intrusive/derivation_value_traits.hpp index 0b3c936..5581ab6 100644 --- a/include/boost/intrusive/derivation_value_traits.hpp +++ b/include/boost/intrusive/derivation_value_traits.hpp @@ -13,6 +13,9 @@ #ifndef BOOST_INTRUSIVE_DERIVATION_VALUE_TRAITS_HPP #define BOOST_INTRUSIVE_DERIVATION_VALUE_TRAITS_HPP +#include +#include + #include #include #include @@ -24,7 +27,12 @@ namespace intrusive { //!This value traits template is used to create value traits //!from user defined node traits where value_traits::value_type will //!derive from node_traits::node -template + +template struct derivation_value_traits { public: @@ -67,4 +75,6 @@ struct derivation_value_traits } //namespace intrusive } //namespace boost +#include + #endif //BOOST_INTRUSIVE_DERIVATION_VALUE_TRAITS_HPP diff --git a/include/boost/intrusive/detail/assert.hpp b/include/boost/intrusive/detail/assert.hpp index 3dacbcc..d75d225 100644 --- a/include/boost/intrusive/detail/assert.hpp +++ b/include/boost/intrusive/detail/assert.hpp @@ -13,7 +13,7 @@ #ifndef BOOST_INTRUSIVE_DETAIL_ASSERT_HPP #define BOOST_INTRUSIVE_DETAIL_ASSERT_HPP -#if defined(_MSC_VER)&&(_MSC_VER>=1200) +#if defined(_MSC_VER) #pragma once #endif diff --git a/include/boost/intrusive/detail/generic_hook.hpp b/include/boost/intrusive/detail/generic_hook.hpp index 8848aff..835a8c7 100644 --- a/include/boost/intrusive/detail/generic_hook.hpp +++ b/include/boost/intrusive/detail/generic_hook.hpp @@ -33,9 +33,9 @@ enum base_hook_type , SlistBaseHookId , RbTreeBaseHookId , HashBaseHookId -, SplayTreeBaseHookId , AvlTreeBaseHookId , BsTreeBaseHookId +, TreapTreeBaseHookId , AnyBaseHookId }; @@ -59,10 +59,6 @@ template struct hook_tags_definer { typedef HookTags default_hashtable_hook; }; -template -struct hook_tags_definer -{ typedef HookTags default_splaytree_hook; }; - template struct hook_tags_definer { typedef HookTags default_avltree_hook; }; diff --git a/include/boost/intrusive/detail/has_member_function_callable_with.hpp b/include/boost/intrusive/detail/has_member_function_callable_with.hpp index be4a015..12eec96 100644 --- a/include/boost/intrusive/detail/has_member_function_callable_with.hpp +++ b/include/boost/intrusive/detail/has_member_function_callable_with.hpp @@ -70,11 +70,11 @@ #error "BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END not defined!" #endif - #if BOOST_PP_ITERATION_START() != 0 - #error "BOOST_PP_ITERATION_START() must be zero (0)" + #if BOOST_PP_ITERATION_START() > BOOST_PP_ITERATION_FINISH() + #error "BOOST_PP_ITERATION_START() must be <= BOOST_PP_ITERATION_FINISH()" #endif - #if BOOST_PP_ITERATION() == 0 + #if BOOST_PP_ITERATION() == BOOST_PP_ITERATION_START() BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN @@ -114,6 +114,119 @@ }; //! + #else //!defined(BOOST_INTRUSIVE_PERFECT_FORWARDING) + + template + struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl); + + template + struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl) + + { + static const bool value = false; + }; + + #ifdef BOOST_NO_CXX11_DECLTYPE + + //Special case for 0 args + template< class F + , std::size_t N = + sizeof((boost::move_detail::declval(). + BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME (), 0))> + struct BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME) + { + boost_intrusive_has_member_function_callable_with::yes_type dummy; + BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)(int); + }; + + //For buggy compilers like MSVC 7.1+ ((F*)0)->func() does not + //SFINAE-out the zeroarg_checker_ instantiation but sizeof yields to 0. + template + struct BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME) + { + boost_intrusive_has_member_function_callable_with::no_type dummy; + BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)(int); + }; + + #endif //#ifdef BOOST_NO_CXX11_DECLTYPE + + template + struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl) + + { + #ifndef BOOST_NO_CXX11_DECLTYPE + template().BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME()) > + static boost_intrusive_has_member_function_callable_with::yes_type Test(U*); + #else + template + static BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME) + Test(BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)*); + #endif + + template + static boost_intrusive_has_member_function_callable_with::no_type Test(...); + + static const bool value = sizeof(Test< Fun >(0)) + == sizeof(boost_intrusive_has_member_function_callable_with::yes_type); + }; + + template + struct BOOST_PP_CAT( funwrap_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME ) + : Fun + { + BOOST_PP_CAT( funwrap_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME )(); + using Fun::BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME; + + boost_intrusive_has_member_function_callable_with::private_type + BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME + ( DontCares...) const; + }; + + template + struct BOOST_PP_CAT( BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME), _impl) + + { + template + struct make_dontcare + { + typedef boost_intrusive_has_member_function_callable_with::dont_care type; + }; + + typedef BOOST_PP_CAT( funwrap_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME ) + ::type...> FunWrap; + + static bool const value = (sizeof(boost_intrusive_has_member_function_callable_with::no_type) == + sizeof(boost_intrusive_has_member_function_callable_with::is_private_type + ( (::boost::move_detail::declval< FunWrap >(). + BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME + ( ::boost::move_detail::declval()... ), 0) ) + ) + ); + }; + + template + struct BOOST_PP_CAT( has_member_function_callable_with_ + , BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME) + : public BOOST_PP_CAT( BOOST_PP_CAT(has_member_function_callable_with_ + , BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl) + < Fun + , BOOST_PP_CAT( has_member_function_named_ + , BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME )::value + , Args... > + {}; + + #endif //!defined(BOOST_INTRUSIVE_PERFECT_FORWARDING) + + BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END + + #endif //BOOST_PP_ITERATION() == BOOST_PP_ITERATION_START() + + #if BOOST_PP_ITERATION() == 0 + + BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN + + #if !defined(BOOST_INTRUSIVE_PERFECT_FORWARDING) + #if !defined(_MSC_VER) || (_MSC_VER < 1600) #if defined(BOOST_INTRUSIVE_DETAIL_HAS_MEMBER_FUNCTION_CALLABLE_WITH_0_ARGS_UNSUPPORTED) @@ -171,9 +284,9 @@ { template - static decltype( boost::move_detail::declval().BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME() + static decltype( boost::move_detail::declval().BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME() , boost_intrusive_has_member_function_callable_with::yes_type()) - Test(Fun*); + Test(U*); template static boost_intrusive_has_member_function_callable_with::no_type Test(...); @@ -185,96 +298,6 @@ #else //#if !defined(BOOST_INTRUSIVE_PERFECT_FORWARDING) - template - struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl); - - template - struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl) - - { - static const bool value = false; - }; - - //Special case for 0 args - template< class F - , std::size_t N = - sizeof((boost::move_detail::declval(). - BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME (), 0))> - struct BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME) - { - boost_intrusive_has_member_function_callable_with::yes_type dummy; - BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)(int); - }; - - //For buggy compilers like MSVC 7.1+ ((F*)0)->func() does not - //SFINAE-out the zeroarg_checker_ instantiation but sizeof yields to 0. - template - struct BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME) - { - boost_intrusive_has_member_function_callable_with::no_type dummy; - BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)(int); - }; - - template - struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl) - - { - template - static BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME) - Test(BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)*); - - template - static boost_intrusive_has_member_function_callable_with::no_type Test(...); - - static const bool value = sizeof(Test< Fun >(0)) - == sizeof(boost_intrusive_has_member_function_callable_with::yes_type); - }; - - template - struct BOOST_PP_CAT( funwrap_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME ) - : Fun - { - BOOST_PP_CAT( funwrap_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME )(); - using Fun::BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME; - - boost_intrusive_has_member_function_callable_with::private_type - BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME - ( DontCares...) const; - }; - - template - struct BOOST_PP_CAT( BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME), _impl) - - { - template - struct make_dontcare - { - typedef boost_intrusive_has_member_function_callable_with::dont_care type; - }; - - typedef BOOST_PP_CAT( funwrap_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME ) - ::type...> FunWrap; - - static bool const value = (sizeof(boost_intrusive_has_member_function_callable_with::no_type) == - sizeof(boost_intrusive_has_member_function_callable_with::is_private_type - ( (::boost::move_detail::declval< FunWrap >(). - BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME - ( ::boost::move_detail::declval()... ), 0) ) - ) - ); - }; - - template - struct BOOST_PP_CAT( has_member_function_callable_with_ - , BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME) - : public BOOST_PP_CAT( BOOST_PP_CAT(has_member_function_callable_with_ - , BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl) - < Fun - , BOOST_PP_CAT( has_member_function_named_ - , BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME )::value - , Args... > - {}; - #endif //#if !defined(BOOST_INTRUSIVE_PERFECT_FORWARDING) BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END diff --git a/include/boost/intrusive/detail/memory_util.hpp b/include/boost/intrusive/detail/memory_util.hpp index bfc9b14..e425c3b 100644 --- a/include/boost/intrusive/detail/memory_util.hpp +++ b/include/boost/intrusive/detail/memory_util.hpp @@ -17,7 +17,7 @@ #ifndef BOOST_INTRUSIVE_ALLOCATOR_MEMORY_UTIL_HPP #define BOOST_INTRUSIVE_ALLOCATOR_MEMORY_UTIL_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -118,25 +118,25 @@ struct LowPriorityConversion #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME pointer_to #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace intrusive { namespace detail { #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}} -#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, 1, )) +#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 1, )) #include BOOST_PP_ITERATE() #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME static_cast_from #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace intrusive { namespace detail { #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}} -#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, 1, )) +#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 1, )) #include BOOST_PP_ITERATE() #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME const_cast_from #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace intrusive { namespace detail { #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}} -#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, 1, )) +#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 1, )) #include BOOST_PP_ITERATE() #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME dynamic_cast_from #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace intrusive { namespace detail { #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}} -#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, 1, )) +#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 1, )) #include BOOST_PP_ITERATE() namespace boost { diff --git a/include/boost/intrusive/detail/mpl.hpp b/include/boost/intrusive/detail/mpl.hpp index 6f99d7c..4358aec 100644 --- a/include/boost/intrusive/detail/mpl.hpp +++ b/include/boost/intrusive/detail/mpl.hpp @@ -29,6 +29,12 @@ struct bool_ static const bool value = C_; }; +template< class Integer, Integer Value > +struct integer +{ + static const Integer value = Value; +}; + typedef bool_ true_; typedef bool_ false_; diff --git a/include/boost/intrusive/detail/preprocessor.hpp b/include/boost/intrusive/detail/preprocessor.hpp index b3ed6e6..b8143a4 100644 --- a/include/boost/intrusive/detail/preprocessor.hpp +++ b/include/boost/intrusive/detail/preprocessor.hpp @@ -11,7 +11,7 @@ #ifndef BOOST_INTRUSIVE_DETAIL_PREPROCESSOR_HPP #define BOOST_INTRUSIVE_DETAIL_PREPROCESSOR_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/include/boost/intrusive/hashtable.hpp b/include/boost/intrusive/hashtable.hpp index ff25a41..607e80d 100644 --- a/include/boost/intrusive/hashtable.hpp +++ b/include/boost/intrusive/hashtable.hpp @@ -13,6 +13,7 @@ #define BOOST_INTRUSIVE_HASHTABLE_HPP #include +#include //std C++ #include //std::equal_to #include //std::pair @@ -24,7 +25,6 @@ #include #include //General intrusive utilities -#include #include #include #include @@ -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(const bucket_ptr buckets_ptr, const size_type bucket_cnt) { @@ -2713,7 +2739,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 @@ -2791,7 +2817,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()); } @@ -3006,21 +3032,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 @@ -3061,15 +3084,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) @@ -3109,7 +3132,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; @@ -3119,7 +3141,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/intrusive_fwd.hpp b/include/boost/intrusive/intrusive_fwd.hpp index 0e5e21c..5beeffd 100644 --- a/include/boost/intrusive/intrusive_fwd.hpp +++ b/include/boost/intrusive/intrusive_fwd.hpp @@ -13,12 +13,47 @@ #ifndef BOOST_INTRUSIVE_FWD_HPP #define BOOST_INTRUSIVE_FWD_HPP +//! \file +//! This header file forward declares most Intrusive classes. +//! +//! It forward declares the following containers and hooks: +//! - boost::intrusive::slist / boost::intrusive::slist_base_hook / boost::intrusive::slist_member_hook +//! - boost::intrusive::list / boost::intrusive::list_base_hook / boost::intrusive::list_member_hook +//! - boost::intrusive::bstree / boost::intrusive::bs_set / boost::intrusive::bs_multiset / +//! boost::intrusive::bs_set_base_hook / boost::intrusive::bs_set_member_hook +//! - boost::intrusive::rbtree / boost::intrusive::set / boost::intrusive::multiset / +//! boost::intrusive::set_base_hook / boost::intrusive::set_member_hook +//! - boost::intrusive::avltree / boost::intrusive::avl_set / boost::intrusive::avl_multiset / +//! boost::intrusive::avl_set_base_hook / boost::intrusive::avl_set_member_hook +//! - boost::intrusive::splaytree / boost::intrusive::splay_set / boost::intrusive::splay_multiset +//! - boost::intrusive::sgtree / boost::intrusive::sg_set / boost::intrusive::sg_multiset +//! - boost::intrusive::treap / boost::intrusive::treap_set / boost::intrusive::treap_multiset +//! - boost::intrusive::hashtable / boost::intrusive::unordered_set / boost::intrusive::unordered_multiset / +//! boost::intrusive::unordered_set_base_hook / boost::intrusive::unordered_set_member_hook / +//! - boost::intrusive::any_base_hook / boost::intrusive::any_member_hook +//! +//! It forward declares the following container or hook options: +//! - boost::intrusive::constant_time_size / boost::intrusive::size_type / boost::intrusive::compare / boost::intrusive::equal +//! - boost::intrusive::floating_point / boost::intrusive::priority / boost::intrusive::hash +//! - boost::intrusive::value_traits / boost::intrusive::member_hook / boost::intrusive::function_hook / boost::intrusive::base_hook +//! - boost::intrusive::void_pointer / boost::intrusive::tag / boost::intrusive::link_mode +//! - boost::intrusive::optimize_size / boost::intrusive::linear / boost::intrusive::cache_last +//! - boost::intrusive::bucket_traits / boost::intrusive::store_hash / boost::intrusive::optimize_multikey +//! - boost::intrusive::power_2_buckets / boost::intrusive::cache_begin / boost::intrusive::compare_hash / boost::intrusive::incremental +//! +//! It forward declares the following value traits utilities: +//! - boost::intrusive::value_traits / boost::intrusive::derivation_value_traits / +//! boost::intrusive::trivial_value_traits +//! +//! Finally it forward declares the following general purpose utilities: +//! - boost::intrusive::pointer_plus_bits / boost::intrusive::priority_compare. + +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + #include #include #include -/// @cond - namespace boost { namespace intrusive { @@ -33,15 +68,33 @@ class circular_list_algorithms; template class circular_slist_algorithms; +template +class linear_slist_algorithms; + +template +class bstree_algorithms; + template class rbtree_algorithms; +template +class avltree_algorithms; + +template +class sgtree_algorithms; + +template +class splaytree_algorithms; + +template +class treap_algorithms; + //////////////////////////// // Containers //////////////////////////// //slist -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -55,7 +108,7 @@ template #endif class slist; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = void , class O2 = void @@ -66,7 +119,7 @@ template #endif class slist_base_hook; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = void , class O2 = void @@ -78,7 +131,7 @@ template class slist_member_hook; //list -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -90,7 +143,7 @@ template #endif class list; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = void , class O2 = void @@ -101,7 +154,7 @@ template #endif class list_base_hook; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = void , class O2 = void @@ -112,19 +165,8 @@ template #endif class list_member_hook; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) -template - < class O1 = void - , class O2 = void - , class O3 = void - > -#else -template -#endif -class list_hook; - //rbtree/set/multiset -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -137,7 +179,7 @@ template #endif class rbtree; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -150,7 +192,7 @@ template #endif class set; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -163,7 +205,7 @@ template #endif class multiset; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = void , class O2 = void @@ -175,7 +217,7 @@ template #endif class set_base_hook; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = void , class O2 = void @@ -188,7 +230,7 @@ template class set_member_hook; //splaytree/splay_set/splay_multiset -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -201,7 +243,7 @@ template #endif class splaytree; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -214,7 +256,7 @@ template #endif class splay_set; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -227,30 +269,8 @@ template #endif class splay_multiset; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) -template - < class O1 = void - , class O2 = void - , class O3 = void - > -#else -template -#endif -class splay_set_base_hook; - -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) -template - < class O1 = void - , class O2 = void - , class O3 = void - > -#else -template -#endif -class splay_set_member_hook; - //avltree/avl_set/avl_multiset -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -263,7 +283,7 @@ template #endif class avltree; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -276,7 +296,7 @@ template #endif class avl_set; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -289,7 +309,7 @@ template #endif class avl_multiset; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = void , class O2 = void @@ -301,7 +321,7 @@ template #endif class avl_set_base_hook; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = void , class O2 = void @@ -315,7 +335,7 @@ class avl_set_member_hook; //treap/treap_set/treap_multiset -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -328,7 +348,7 @@ template #endif class treap; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -341,7 +361,7 @@ template #endif class treap_set; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -354,12 +374,8 @@ template #endif class treap_multiset; -//Default priority comparison functor -template -struct priority_compare; - //sgtree/sg_set/sg_multiset -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -372,7 +388,7 @@ template #endif class sgtree; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -385,7 +401,7 @@ template #endif class sg_set; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -398,7 +414,7 @@ template #endif class sg_multiset; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -411,7 +427,7 @@ template #endif class bstree; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -424,7 +440,7 @@ template #endif class bs_set; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -437,7 +453,7 @@ template #endif class bs_multiset; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = void , class O2 = void @@ -448,7 +464,7 @@ template #endif class bs_set_base_hook; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = void , class O2 = void @@ -461,7 +477,7 @@ class bs_set_member_hook; //hashtable/unordered_set/unordered_multiset -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -480,7 +496,7 @@ template #endif class hashtable; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -499,7 +515,7 @@ template #endif class unordered_set; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = void @@ -518,7 +534,7 @@ template #endif class unordered_multiset; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = void , class O2 = void @@ -530,7 +546,7 @@ template #endif class unordered_set_base_hook; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = void , class O2 = void @@ -542,7 +558,7 @@ template #endif class unordered_set_member_hook; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = void , class O2 = void @@ -553,7 +569,7 @@ template #endif class any_base_hook; -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = void , class O2 = void @@ -564,9 +580,126 @@ template #endif class any_member_hook; +//Options + +template +struct constant_time_size; + +template +struct size_type; + +template +struct compare; + +template +struct floating_point; + +template +struct equal; + +template +struct priority; + +template +struct hash; + +template struct value_traits; + +template< typename Parent + , typename MemberHook + , MemberHook Parent::* PtrToMember> +struct member_hook; + +template +struct function_hook; + +template +struct base_hook; + +template +struct void_pointer; + +template +struct tag; + +template +struct link_mode; + +template struct +optimize_size; + +template +struct linear; + +template +struct cache_last; + +template +struct bucket_traits; + +template +struct store_hash; + +template +struct optimize_multikey; + +template +struct power_2_buckets; + +template +struct cache_begin; + +template +struct compare_hash; + +template +struct incremental; + +//Value traits + +template +struct value_traits; + +template< typename Parent + , typename MemberHook + , MemberHook Parent::* PtrToMember> +struct member_hook; + +template< typename Functor> +struct function_hook; + +template +struct base_hook; + +template +struct derivation_value_traits; + +template +struct trivial_value_traits; + +//Additional utilities + +template +struct max_pointer_plus_bits; + +template +struct max_pointer_plus_bits; + +template +struct pointer_plus_bits; + +template +struct pointer_plus_bits; + +template +struct pointer_traits; + +template +struct pointer_traits; + } //namespace intrusive { } //namespace boost { -/// @endcond +#endif //#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) #endif //#ifndef BOOST_INTRUSIVE_FWD_HPP diff --git a/include/boost/intrusive/list_hook.hpp b/include/boost/intrusive/list_hook.hpp index ef55425..0d9bb32 100644 --- a/include/boost/intrusive/list_hook.hpp +++ b/include/boost/intrusive/list_hook.hpp @@ -77,7 +77,7 @@ struct make_list_base_hook //! \c auto_unlink or \c safe_link). //! //! \c void_pointer<> is the pointer type that will be used internally in the hook -//! and the the container configured to use this hook. +//! and the container configured to use this hook. #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else @@ -199,7 +199,7 @@ struct make_list_member_hook //! \c auto_unlink or \c safe_link). //! //! \c void_pointer<> is the pointer type that will be used internally in the hook -//! and the the container configured to use this hook. +//! and the container configured to use this hook. #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else diff --git a/include/boost/intrusive/member_value_traits.hpp b/include/boost/intrusive/member_value_traits.hpp index ce35fdc..bd5f1fb 100644 --- a/include/boost/intrusive/member_value_traits.hpp +++ b/include/boost/intrusive/member_value_traits.hpp @@ -13,6 +13,9 @@ #ifndef BOOST_INTRUSIVE_MEMBER_VALUE_TRAITS_HPP #define BOOST_INTRUSIVE_MEMBER_VALUE_TRAITS_HPP +#include +#include + #include #include #include @@ -26,7 +29,11 @@ namespace intrusive { //!store a node_traits::node template< class T, class NodeTraits , typename NodeTraits::node T::* PtrToMember - , link_mode_type LinkMode = safe_link> + , link_mode_type LinkMode + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + = safe_link + #endif +> struct member_value_traits { public: @@ -67,4 +74,6 @@ struct member_value_traits } //namespace intrusive } //namespace boost +#include + #endif //BOOST_INTRUSIVE_MEMBER_VALUE_TRAITS_HPP diff --git a/include/boost/intrusive/options.hpp b/include/boost/intrusive/options.hpp index 6d06a79..7652f9a 100644 --- a/include/boost/intrusive/options.hpp +++ b/include/boost/intrusive/options.hpp @@ -16,15 +16,15 @@ #include #include #include +#include #include #include #include - namespace boost { namespace intrusive { -/// @cond +#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED //typedef void default_tag; struct default_tag; @@ -34,8 +34,6 @@ namespace detail{ struct default_hook_tag{}; -#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED - #define BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER) \ struct BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER : public default_hook_tag\ {\ @@ -50,35 +48,9 @@ BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_rbtree_hook); BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_hashtable_hook); BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_avltree_hook); BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_bstree_hook); -//BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_splaytree_hook); -//BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_sgtree_hook); -//BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_treap_hook); #undef BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION -#endif //BOOST_INTRUSIVE_DOXYGEN_INVOKED - -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 { @@ -165,7 +137,7 @@ struct get_value_traits //...get it's internal value traits using //the provided T value type. , get_base_value_traits - //...else use it's internal value traits tag + //...else use its internal value traits tag //(member hooks and custom value traits are in this group) , detail::eval_if_c < internal_member_value_traits::value @@ -191,7 +163,7 @@ struct get_node_traits //...get it's internal value traits using //the provided T value type. , get_base_node_traits - //...else use it's internal value traits tag + //...else use its internal value traits tag //(member hooks and custom value traits are in this group) , detail::eval_if_c < internal_member_value_traits::value @@ -203,50 +175,20 @@ struct get_node_traits } //namespace detail{ -/// @endcond +#endif //BOOST_INTRUSIVE_DOXYGEN_INVOKED //!This option setter specifies if the intrusive //!container stores its size as a member to //!obtain constant-time size() member. -template -struct constant_time_size -{ -/// @cond - template - struct pack : Base - { - static const bool constant_time_size = Enabled; - }; -/// @endcond -}; +BOOST_INTRUSIVE_OPTION_CONSTANT(constant_time_size, bool, Enabled, constant_time_size) //!This option setter specifies the type that //!the container will use to store its size. -template -struct size_type -{ -/// @cond - template - struct pack : Base - { - typedef SizeType size_type; - }; -/// @endcond -}; +BOOST_INTRUSIVE_OPTION_TYPE(size_type, SizeType, SizeType, size_type) //!This option setter specifies the strict weak ordering //!comparison functor for the value type -template -struct compare -{ -/// @cond - template - struct pack : Base - { - typedef Compare compare; - }; -/// @endcond -}; +BOOST_INTRUSIVE_OPTION_TYPE(compare, Compare, Compare, compare) //!This option setter for scapegoat containers specifies if //!the intrusive scapegoat container should use a non-variable @@ -260,74 +202,39 @@ struct compare //!If the user only needs an alpha value near 1/sqrt(2), this //!option also improves performance since avoids logarithm //!and division operations when rebalancing the tree. -template -struct floating_point -{ -/// @cond - template - struct pack : Base - { - static const bool floating_point = Enabled; - }; -/// @endcond -}; +BOOST_INTRUSIVE_OPTION_CONSTANT(floating_point, bool, Enabled, floating_point) //!This option setter specifies the equality //!functor for the value type -template -struct equal -{ -/// @cond - template - struct pack : Base - { - typedef Equal equal; - }; -/// @endcond -}; +BOOST_INTRUSIVE_OPTION_TYPE(equal, Equal, Equal, equal) //!This option setter specifies the equality //!functor for the value type -template -struct priority -{ -/// @cond - template - struct pack : Base - { - typedef Priority priority; - }; -/// @endcond -}; +BOOST_INTRUSIVE_OPTION_TYPE(priority, Priority, Priority, priority) //!This option setter specifies the hash //!functor for the value type -template -struct hash -{ -/// @cond - template - struct pack : Base - { - typedef Hash hash; - }; -/// @endcond -}; +BOOST_INTRUSIVE_OPTION_TYPE(hash, Hash, Hash, hash) //!This option setter specifies the relationship between the type //!to be managed by the container (the value type) and the node to be //!used in the node algorithms. It also specifies the linking policy. -template -struct value_traits -{ -/// @cond - template - struct pack : Base - { - typedef ValueTraits proto_value_traits; - }; -/// @endcond -}; +BOOST_INTRUSIVE_OPTION_TYPE(value_traits, ValueTraits, ValueTraits, proto_value_traits) + +//#define BOOST_INTRUSIVE_COMMA , +//#define BOOST_INTRUSIVE_LESS < +//#define BOOST_INTRUSIVE_MORE > +//BOOST_INTRUSIVE_OPTION_TYPE (member_hook, Parent BOOST_INTRUSIVE_COMMA class MemberHook BOOST_INTRUSIVE_COMMA MemberHook Parent::* PtrToMember , mhtraits BOOST_INTRUSIVE_LESS Parent BOOST_INTRUSIVE_COMMA MemberHook BOOST_INTRUSIVE_COMMA PtrToMember BOOST_INTRUSIVE_MORE , proto_value_traits) +//template< class Parent , class MemberHook , MemberHook Parent::* PtrToMember> +//struct member_hook { +// template struct pack : Base { +// typedef mhtraits < Parent , MemberHook , PtrToMember > proto_value_traits; +// }; +//}; +// +//#undef BOOST_INTRUSIVE_COMMA +//#undef BOOST_INTRUSIVE_LESS +//#undef BOOST_INTRUSIVE_MORE //!This option setter specifies the member hook the //!container must use. @@ -336,27 +243,21 @@ template< typename Parent , MemberHook Parent::* PtrToMember> struct member_hook { -/// @cond -/* - typedef typename MemberHook::hooktags::node_traits node_traits; - typedef typename node_traits::node node_type; - typedef node_type Parent::* Ptr2MemNode; - typedef mhtraits - < Parent - , node_traits - //This cast is really ugly but necessary to reduce template bloat. - //Since we control the layout between the hook and the node, and there is - //always single inheritance, the offset of the node is exactly the offset of - //the hook. Since the node type is shared between all member hooks, this saves - //quite a lot of symbol stuff. - , (Ptr2MemNode)PtrToMember - , MemberHook::hooktags::link_mode> member_value_traits; -*/ - typedef mhtraits - < Parent - , MemberHook - , PtrToMember - > member_value_traits; +// @cond +// typedef typename MemberHook::hooktags::node_traits node_traits; +// typedef typename node_traits::node node_type; +// typedef node_type Parent::* Ptr2MemNode; +// typedef mhtraits +// < Parent +// , node_traits +// //This cast is really ugly but necessary to reduce template bloat. +// //Since we control the layout between the hook and the node, and there is +// //always single inheritance, the offset of the node is exactly the offset of +// //the hook. Since the node type is shared between all member hooks, this saves +// //quite a lot of symbol stuff. +// , (Ptr2MemNode)PtrToMember +// , MemberHook::hooktags::link_mode> member_value_traits; + typedef mhtraits member_value_traits; template struct pack : Base { @@ -365,158 +266,55 @@ struct member_hook /// @endcond }; - //!This option setter specifies the function object that will //!be used to convert between values to be inserted in a container //!and the hook to be used for that purpose. -template< typename Functor> -struct function_hook -{ -/// @cond - typedef fhtraits - function_value_traits; - template - struct pack : Base - { - typedef function_value_traits proto_value_traits; - }; -/// @endcond -}; - +BOOST_INTRUSIVE_OPTION_TYPE(function_hook, Functor, fhtraits, proto_value_traits) //!This option setter specifies that the container //!must use the specified base hook -template -struct base_hook -{ -/// @cond - template - struct pack : Base - { - typedef BaseHook proto_value_traits; - }; -/// @endcond -}; +BOOST_INTRUSIVE_OPTION_TYPE(base_hook, BaseHook, BaseHook, proto_value_traits) //!This option setter specifies the type of //!a void pointer. This will instruct the hook //!to use this type of pointer instead of the //!default one -template -struct void_pointer -{ -/// @cond - template - struct pack : Base - { - typedef VoidPointer void_pointer; - }; -/// @endcond -}; +BOOST_INTRUSIVE_OPTION_TYPE(void_pointer, VoidPointer, VoidPointer, void_pointer) //!This option setter specifies the type of //!the tag of a base hook. A type cannot have two //!base hooks of the same type, so a tag can be used //!to differentiate two base hooks with otherwise same type -template -struct tag -{ -/// @cond - template - struct pack : Base - { - typedef Tag tag; - }; -/// @endcond -}; +BOOST_INTRUSIVE_OPTION_TYPE(tag, Tag, Tag, tag) //!This option setter specifies the link mode //!(normal_link, safe_link or auto_unlink) -template -struct link_mode -{ -/// @cond - template - struct pack : Base - { - static const link_mode_type link_mode = LinkType; - }; -/// @endcond -}; +BOOST_INTRUSIVE_OPTION_CONSTANT(link_mode, link_mode_type, LinkType, link_mode) //!This option setter specifies if the hook //!should be optimized for size instead of for speed. -template -struct optimize_size -{ -/// @cond - template - struct pack : Base - { - static const bool optimize_size = Enabled; - }; -/// @endcond -}; +BOOST_INTRUSIVE_OPTION_CONSTANT(optimize_size, bool, Enabled, optimize_size) -//!This option setter specifies if the list container should +//!This option setter specifies if the slist container should //!use a linear implementation instead of a circular one. -template -struct linear -{ -/// @cond - template - struct pack : Base - { - static const bool linear = Enabled; - }; -/// @endcond -}; +BOOST_INTRUSIVE_OPTION_CONSTANT(linear, bool, Enabled, linear) -//!This option setter specifies if the list container should -//!use a linear implementation instead of a circular one. -template -struct cache_last -{ -/// @cond - template - struct pack : Base - { - static const bool cache_last = Enabled; - }; -/// @endcond -}; +//!If true, slist also stores a pointer to the last element of the singly linked list. +//!This allows O(1) swap and splice_after(iterator, slist &) for circular slists and makes +//!possible new functions like push_back(reference) and back(). +BOOST_INTRUSIVE_OPTION_CONSTANT(cache_last, bool, Enabled, cache_last) //!This option setter specifies the bucket traits //!class for unordered associative containers. When this option is specified, //!instead of using the default bucket traits, a user defined holder will be defined -template -struct bucket_traits -{ -/// @cond - template - struct pack : Base - { - typedef BucketTraits bucket_traits; - }; -/// @endcond -}; +BOOST_INTRUSIVE_OPTION_TYPE(bucket_traits, BucketTraits, BucketTraits, bucket_traits) //!This option setter specifies if the unordered hook //!should offer room to store the hash value. //!Storing the hash in the hook will speed up rehashing //!processes in applications where rehashing is frequent, //!rehashing might throw or the value is heavy to hash. -template -struct store_hash -{ -/// @cond - template - struct pack : Base - { - static const bool store_hash = Enabled; - }; -/// @endcond -}; +BOOST_INTRUSIVE_OPTION_CONSTANT(store_hash, bool, Enabled, store_hash) //!This option setter specifies if the unordered hook //!should offer room to store another link to another node @@ -524,51 +322,20 @@ struct store_hash //!Storing this link will speed up lookups and insertions on //!unordered_multiset containers with a great number of elements //!with the same key. -template -struct optimize_multikey -{ -/// @cond - template - struct pack : Base - { - static const bool optimize_multikey = Enabled; - }; -/// @endcond -}; +BOOST_INTRUSIVE_OPTION_CONSTANT(optimize_multikey, bool, Enabled, optimize_multikey) //!This option setter specifies if the bucket array will be always power of two. //!This allows using masks instead of the default modulo operation to determine //!the bucket number from the hash value, leading to better performance. //!In debug mode, if power of two buckets mode is activated, the bucket length //!will be checked to through assertions to assure the bucket length is power of two. -template -struct power_2_buckets -{ -/// @cond - template - struct pack : Base - { - static const bool power_2_buckets = Enabled; - }; -/// @endcond -}; +BOOST_INTRUSIVE_OPTION_CONSTANT(power_2_buckets, bool, Enabled, power_2_buckets) //!This option setter specifies if the container will cache a pointer to the first //!non-empty bucket so that begin() is always constant-time. //!This is specially helpful when we can have containers with a few elements //!but with big bucket arrays (that is, hashtables with low load factors). -template -struct cache_begin -{ -/// @cond - template - struct pack : Base - { - static const bool cache_begin = Enabled; - }; -/// @endcond -}; - +BOOST_INTRUSIVE_OPTION_CONSTANT(cache_begin, bool, Enabled, cache_begin) //!This option setter specifies if the container will compare the hash value //!before comparing objects. This option can't be specified if store_hash<> @@ -576,17 +343,7 @@ struct cache_begin //!This is specially helpful when we have containers with a high load factor. //!and the comparison function is much more expensive that comparing already //!stored hash values. -template -struct compare_hash -{ -/// @cond - template - struct pack : Base - { - static const bool compare_hash = Enabled; - }; -/// @endcond -}; +BOOST_INTRUSIVE_OPTION_CONSTANT(compare_hash, bool, Enabled, compare_hash) //!This option setter specifies if the hash container will use incremental //!hashing. With incremental hashing the cost of hash table expansion is spread @@ -594,17 +351,7 @@ struct compare_hash //!Therefore linear hashing is well suited for interactive applications or real-time //!appplications where the worst-case insertion time of non-incremental hash containers //!(rehashing the whole bucket array) is not admisible. -template -struct incremental -{ - /// @cond - template - struct pack : Base - { - static const bool incremental = Enabled; - }; - /// @endcond -}; +BOOST_INTRUSIVE_OPTION_CONSTANT(incremental, bool, Enabled, incremental) /// @cond @@ -615,210 +362,6 @@ struct none {}; }; -//To-do: pass to variadic templates -#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - -template -struct do_pack -{ - //Use "pack" member template to pack options - typedef typename Next::template pack type; -}; - -template -struct do_pack -{ - //Avoid packing "void" to shorten template names - typedef Prev type; -}; - -template - < class DefaultOptions - , class O1 = void - , class O2 = void - , class O3 = void - , class O4 = void - , class O5 = void - , class O6 = void - , class O7 = void - , class O8 = void - , class O9 = void - , class O10 = void - , class O11 = void - > -struct pack_options -{ - // join options - typedef - typename do_pack - < typename do_pack - < typename do_pack - < typename do_pack - < typename do_pack - < typename do_pack - < typename do_pack - < typename do_pack - < typename do_pack - < typename do_pack - < typename do_pack - < DefaultOptions - , O1 - >::type - , O2 - >::type - , O3 - >::type - , O4 - >::type - , O5 - >::type - , O6 - >::type - , O7 - >::type - , O8 - >::type - , O9 - >::type - , O10 - >::type - , O11 - >::type - type; -}; -#else - -//index_tuple -template -struct index_tuple{}; - -//build_number_seq -template > -struct build_number_seq; - -template -struct build_number_seq > - : build_number_seq > -{}; - -template -struct build_number_seq<0, index_tuple > -{ typedef index_tuple type; }; - -template -struct typelist -{}; - -//invert_typelist -template -struct invert_typelist; - -template -struct typelist_element; - -template -struct typelist_element > -{ - typedef typename typelist_element >::type type; -}; - -template -struct typelist_element<0, typelist > -{ - typedef Head type; -}; - -template -typelist >::type...> - inverted_typelist(index_tuple, typelist) -{ - return typelist >::type...>(); -} - -//sizeof_typelist -template -struct sizeof_typelist; - -template -struct sizeof_typelist< typelist > -{ - static const std::size_t value = sizeof...(Types); -}; - -//invert_typelist_impl -template -struct invert_typelist_impl; - - -template -struct invert_typelist_impl< Typelist, index_tuple > -{ - static const std::size_t last_idx = sizeof_typelist::value - 1; - typedef typelist - ::type...> type; -}; - -template -struct invert_typelist_impl< Typelist, index_tuple > -{ - typedef Typelist type; -}; - -template -struct invert_typelist_impl< Typelist, index_tuple<> > -{ - typedef Typelist type; -}; - -//invert_typelist -template -struct invert_typelist; - -template -struct invert_typelist< typelist > -{ - typedef typelist typelist_t; - typedef typename build_number_seq::type indexes_t; - typedef typename invert_typelist_impl::type type; -}; - -//Do pack -template -struct do_pack; - -template<> -struct do_pack >; - -template -struct do_pack > -{ - typedef Prev type; -}; - -template -struct do_pack > -{ - typedef typename Prev::template pack type; -}; - -template -struct do_pack > -{ - typedef typename Prev::template pack - >::type> type; -}; - - -template -struct pack_options -{ - typedef typelist typelist_t; - typedef typename invert_typelist::type inverted_typelist; - typedef typename do_pack::type type; -}; - -#endif - struct hook_defaults { typedef void* void_pointer; diff --git a/include/boost/intrusive/parent_from_member.hpp b/include/boost/intrusive/parent_from_member.hpp index e06f156..0f3eb5c 100644 --- a/include/boost/intrusive/parent_from_member.hpp +++ b/include/boost/intrusive/parent_from_member.hpp @@ -13,6 +13,8 @@ #define BOOST_INTRUSIVE_GET_PARENT_FROM_MEMBER_HPP #include +#include + #include namespace boost { diff --git a/include/boost/intrusive/pointer_plus_bits.hpp b/include/boost/intrusive/pointer_plus_bits.hpp index 7b0a793..3893d66 100644 --- a/include/boost/intrusive/pointer_plus_bits.hpp +++ b/include/boost/intrusive/pointer_plus_bits.hpp @@ -13,6 +13,8 @@ #ifndef BOOST_INTRUSIVE_POINTER_PLUS_BITS_HPP #define BOOST_INTRUSIVE_POINTER_PLUS_BITS_HPP +#include +#include #include //ls_zeros #include //BOOST_INTRUSIVE_INVARIANT_ASSERT @@ -83,4 +85,6 @@ struct pointer_plus_bits } //namespace intrusive } //namespace boost +#include + #endif //BOOST_INTRUSIVE_POINTER_PLUS_BITS_HPP diff --git a/include/boost/intrusive/pointer_traits.hpp b/include/boost/intrusive/pointer_traits.hpp index 7d32a89..839c47e 100644 --- a/include/boost/intrusive/pointer_traits.hpp +++ b/include/boost/intrusive/pointer_traits.hpp @@ -17,11 +17,12 @@ #ifndef BOOST_INTRUSIVE_POINTER_TRAITS_HPP #define BOOST_INTRUSIVE_POINTER_TRAITS_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif #include +#include #include #include #include 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 8acfe45..c4ff5f4 100644 --- a/include/boost/intrusive/rbtree.hpp +++ b/include/boost/intrusive/rbtree.hpp @@ -13,13 +13,13 @@ #define BOOST_INTRUSIVE_RBTREE_HPP #include +#include #include #include #include #include #include -#include #include #include #include @@ -292,7 +292,7 @@ class rbtree_impl //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const template size_type count(const KeyType& key, KeyValueCompare comp) const; - + //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference) iterator lower_bound(const_reference value); @@ -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/rbtree_algorithms.hpp b/include/boost/intrusive/rbtree_algorithms.hpp index 38a5cdc..0c1225e 100644 --- a/include/boost/intrusive/rbtree_algorithms.hpp +++ b/include/boost/intrusive/rbtree_algorithms.hpp @@ -10,31 +10,6 @@ // See http://www.boost.org/libs/intrusive for documentation. // ///////////////////////////////////////////////////////////////////////////// -// The internal implementation of red-black trees is based on that of SGI STL -// stl_tree.h file: -// -// Copyright (c) 1996,1997 -// Silicon Graphics Computer Systems, Inc. -// -// Permission to use, copy, modify, distribute and sell this software -// and its documentation for any purpose is hereby granted without fee, -// provided that the above copyright notice appear in all copies and -// that both that copyright notice and this permission notice appear -// in supporting documentation. Silicon Graphics makes no -// representations about the suitability of this software for any -// purpose. It is provided "as is" without express or implied warranty. -// -// -// Copyright (c) 1994 -// Hewlett-Packard Company -// -// Permission to use, copy, modify, distribute and sell this software -// and its documentation for any purpose is hereby granted without fee, -// provided that the above copyright notice appear in all copies and -// that both that copyright notice and this permission notice appear -// in supporting documentation. Hewlett-Packard Company makes no -// representations about the suitability of this software for any -// purpose. It is provided "as is" without express or implied warranty. // // The tree destruction algorithm is based on Julienne Walker and The EC Team code: // @@ -49,9 +24,9 @@ #define BOOST_INTRUSIVE_RBTREE_ALGORITHMS_HPP #include +#include #include -#include #include #include @@ -82,21 +57,6 @@ struct rbtree_node_cloner } }; -template -struct rbtree_erase_fixup -{ - typedef typename NodeTraits::node_ptr node_ptr; - typedef typename NodeTraits::color color; - - void operator()(const node_ptr & to_erase, const node_ptr & successor) - { - //Swap color of y and z - color tmp(NodeTraits::get_color(successor)); - NodeTraits::set_color(successor, NodeTraits::get_color(to_erase)); - NodeTraits::set_color(to_erase, tmp); - } -}; - #endif //#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! rbtree_algorithms provides basic algorithms to manipulate @@ -270,10 +230,18 @@ class rbtree_algorithms static node_ptr erase(const node_ptr & header, const node_ptr & z) { typename bstree_algo::data_for_rebalance info; - bstree_algo::erase(header, z, rbtree_erase_fixup(), info); + bstree_algo::erase(header, z, info); - //Rebalance rbtree - if(NodeTraits::get_color(z) != NodeTraits::red()){ + color new_z_color; + if(info.y != z){ + new_z_color = NodeTraits::get_color(info.y); + NodeTraits::set_color(info.y, NodeTraits::get_color(z)); + } + else{ + new_z_color = NodeTraits::get_color(z); + } + //Rebalance rbtree if needed + if(new_z_color != NodeTraits::red()){ rebalance_after_erasure(header, info.x, info.x_parent); } return z; @@ -322,6 +290,7 @@ class rbtree_algorithms //! @copydoc ::boost::intrusive::bstree_algorithms::count(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) template static std::size_t count(const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp); + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal_upper_bound(const node_ptr&,const node_ptr&,NodePtrCompare) @@ -411,64 +380,76 @@ class rbtree_algorithms static void rebalance_after_erasure(const node_ptr & header, node_ptr x, node_ptr x_parent) { - while(x != NodeTraits::get_parent(header) && (!x || NodeTraits::get_color(x) == NodeTraits::black())){ - if(x == NodeTraits::get_left(x_parent)){ + while(1){ + if(x_parent == header || (x && NodeTraits::get_color(x) != NodeTraits::black())){ + break; + } + //Don't cache x_is_leftchild or similar because x can be null and + //equal to both x_parent_left and x_parent_right + const node_ptr x_parent_left(NodeTraits::get_left(x_parent)); + if(x == x_parent_left){ //x is left child node_ptr w = NodeTraits::get_right(x_parent); BOOST_ASSERT(w); if(NodeTraits::get_color(w) == NodeTraits::red()){ NodeTraits::set_color(w, NodeTraits::black()); NodeTraits::set_color(x_parent, NodeTraits::red()); - bstree_algo::rotate_left(x_parent, header); + bstree_algo::rotate_left(x_parent, w, NodeTraits::get_parent(x_parent), header); w = NodeTraits::get_right(x_parent); } - if((!NodeTraits::get_left(w) || NodeTraits::get_color(NodeTraits::get_left(w)) == NodeTraits::black()) && - (!NodeTraits::get_right(w) || NodeTraits::get_color(NodeTraits::get_right(w)) == NodeTraits::black())){ + node_ptr const w_left (NodeTraits::get_left(w)); + node_ptr const w_right(NodeTraits::get_right(w)); + if((!w_left || NodeTraits::get_color(w_left) == NodeTraits::black()) && + (!w_right || NodeTraits::get_color(w_right) == NodeTraits::black())){ NodeTraits::set_color(w, NodeTraits::red()); x = x_parent; x_parent = NodeTraits::get_parent(x_parent); } else { - if(!NodeTraits::get_right(w) || NodeTraits::get_color(NodeTraits::get_right(w)) == NodeTraits::black()){ - NodeTraits::set_color(NodeTraits::get_left(w), NodeTraits::black()); + if(!w_right || NodeTraits::get_color(w_right) == NodeTraits::black()){ + NodeTraits::set_color(w_left, NodeTraits::black()); NodeTraits::set_color(w, NodeTraits::red()); - bstree_algo::rotate_right(w, header); + bstree_algo::rotate_right(w, w_left, NodeTraits::get_parent(w), header); w = NodeTraits::get_right(x_parent); } NodeTraits::set_color(w, NodeTraits::get_color(x_parent)); NodeTraits::set_color(x_parent, NodeTraits::black()); - if(NodeTraits::get_right(w)) - NodeTraits::set_color(NodeTraits::get_right(w), NodeTraits::black()); - bstree_algo::rotate_left(x_parent, header); + const node_ptr new_wright(NodeTraits::get_right(w)); + if(new_wright) + NodeTraits::set_color(new_wright, NodeTraits::black()); + bstree_algo::rotate_left(x_parent, NodeTraits::get_right(x_parent), NodeTraits::get_parent(x_parent), header); break; } } else { // same as above, with right_ <-> left_. - node_ptr w = NodeTraits::get_left(x_parent); + node_ptr w = x_parent_left; if(NodeTraits::get_color(w) == NodeTraits::red()){ NodeTraits::set_color(w, NodeTraits::black()); NodeTraits::set_color(x_parent, NodeTraits::red()); - bstree_algo::rotate_right(x_parent, header); + bstree_algo::rotate_right(x_parent, w, NodeTraits::get_parent(x_parent), header); w = NodeTraits::get_left(x_parent); } - if((!NodeTraits::get_right(w) || NodeTraits::get_color(NodeTraits::get_right(w)) == NodeTraits::black()) && - (!NodeTraits::get_left(w) || NodeTraits::get_color(NodeTraits::get_left(w)) == NodeTraits::black())){ + node_ptr const w_left (NodeTraits::get_left(w)); + node_ptr const w_right(NodeTraits::get_right(w)); + if((!w_right || NodeTraits::get_color(w_right) == NodeTraits::black()) && + (!w_left || NodeTraits::get_color(w_left) == NodeTraits::black())){ NodeTraits::set_color(w, NodeTraits::red()); x = x_parent; x_parent = NodeTraits::get_parent(x_parent); } else { - if(!NodeTraits::get_left(w) || NodeTraits::get_color(NodeTraits::get_left(w)) == NodeTraits::black()){ - NodeTraits::set_color(NodeTraits::get_right(w), NodeTraits::black()); + if(!w_left || NodeTraits::get_color(w_left) == NodeTraits::black()){ + NodeTraits::set_color(w_right, NodeTraits::black()); NodeTraits::set_color(w, NodeTraits::red()); - bstree_algo::rotate_left(w, header); + bstree_algo::rotate_left(w, w_right, NodeTraits::get_parent(w), header); w = NodeTraits::get_left(x_parent); } NodeTraits::set_color(w, NodeTraits::get_color(x_parent)); NodeTraits::set_color(x_parent, NodeTraits::black()); - if(NodeTraits::get_left(w)) - NodeTraits::set_color(NodeTraits::get_left(w), NodeTraits::black()); - bstree_algo::rotate_right(x_parent, header); + const node_ptr new_wleft(NodeTraits::get_left(w)); + if(new_wleft) + NodeTraits::set_color(new_wleft, NodeTraits::black()); + bstree_algo::rotate_right(x_parent, NodeTraits::get_left(x_parent), NodeTraits::get_parent(x_parent), header); break; } } @@ -480,48 +461,49 @@ class rbtree_algorithms static void rebalance_after_insertion(const node_ptr & header, node_ptr p) { NodeTraits::set_color(p, NodeTraits::red()); - while(p != NodeTraits::get_parent(header) && NodeTraits::get_color(NodeTraits::get_parent(p)) == NodeTraits::red()){ + while(1){ node_ptr p_parent(NodeTraits::get_parent(p)); - node_ptr p_parent_parent(NodeTraits::get_parent(p_parent)); - if(bstree_algo::is_left_child(p_parent)){ - node_ptr x = NodeTraits::get_right(p_parent_parent); - if(x && NodeTraits::get_color(x) == NodeTraits::red()){ - NodeTraits::set_color(p_parent, NodeTraits::black()); - NodeTraits::set_color(p_parent_parent, NodeTraits::red()); - NodeTraits::set_color(x, NodeTraits::black()); - p = p_parent_parent; - } - else { - if(!bstree_algo::is_left_child(p)){ - p = p_parent; - bstree_algo::rotate_left(p, header); - } - node_ptr new_p_parent(NodeTraits::get_parent(p)); - node_ptr new_p_parent_parent(NodeTraits::get_parent(new_p_parent)); - NodeTraits::set_color(new_p_parent, NodeTraits::black()); - NodeTraits::set_color(new_p_parent_parent, NodeTraits::red()); - bstree_algo::rotate_right(new_p_parent_parent, header); - } + const node_ptr p_grandparent(NodeTraits::get_parent(p_parent)); + if(p_parent == header || NodeTraits::get_color(p_parent) == NodeTraits::black() || p_grandparent == header){ + break; } - else{ - node_ptr x = NodeTraits::get_left(p_parent_parent); - if(x && NodeTraits::get_color(x) == NodeTraits::red()){ - NodeTraits::set_color(p_parent, NodeTraits::black()); - NodeTraits::set_color(p_parent_parent, NodeTraits::red()); - NodeTraits::set_color(x, NodeTraits::black()); - p = p_parent_parent; - } - else{ - if(bstree_algo::is_left_child(p)){ - p = p_parent; - bstree_algo::rotate_right(p, header); + + NodeTraits::set_color(p_grandparent, NodeTraits::red()); + node_ptr const p_grandparent_left (NodeTraits::get_left (p_grandparent)); + bool const p_parent_is_left_child = p_parent == p_grandparent_left; + node_ptr const x(p_parent_is_left_child ? NodeTraits::get_right(p_grandparent) : p_grandparent_left); + + if(x && NodeTraits::get_color(x) == NodeTraits::red()){ + NodeTraits::set_color(x, NodeTraits::black()); + NodeTraits::set_color(p_parent, NodeTraits::black()); + p = p_grandparent; + } + else{ //Final step + const bool p_is_left_child(NodeTraits::get_left(p_parent) == p); + if(p_parent_is_left_child){ //p_parent is left child + if(!p_is_left_child){ //p is right child + bstree_algo::rotate_left_no_parent_fix(p_parent, p); + //No need to link p and p_grandparent: + // [NodeTraits::set_parent(p, p_grandparent) + NodeTraits::set_left(p_grandparent, p)] + //as p_grandparent is not the header, another rotation is coming and p_parent + //will be the left child of p_grandparent + p_parent = p; } - node_ptr new_p_parent(NodeTraits::get_parent(p)); - node_ptr new_p_parent_parent(NodeTraits::get_parent(new_p_parent)); - NodeTraits::set_color(new_p_parent, NodeTraits::black()); - NodeTraits::set_color(new_p_parent_parent, NodeTraits::red()); - bstree_algo::rotate_left(new_p_parent_parent, header); + bstree_algo::rotate_right(p_grandparent, p_parent, NodeTraits::get_parent(p_grandparent), header); } + else{ //p_parent is right child + if(p_is_left_child){ //p is left child + bstree_algo::rotate_right_no_parent_fix(p_parent, p); + //No need to link p and p_grandparent: + // [NodeTraits::set_parent(p, p_grandparent) + NodeTraits::set_right(p_grandparent, p)] + //as p_grandparent is not the header, another rotation is coming and p_parent + //will be the right child of p_grandparent + p_parent = p; + } + bstree_algo::rotate_left(p_grandparent, p_parent, NodeTraits::get_parent(p_grandparent), header); + } + NodeTraits::set_color(p_parent, NodeTraits::black()); + break; } } NodeTraits::set_color(NodeTraits::get_parent(header), NodeTraits::black()); diff --git a/include/boost/intrusive/set.hpp b/include/boost/intrusive/set.hpp index c8c197c..b2e4290 100644 --- a/include/boost/intrusive/set.hpp +++ b/include/boost/intrusive/set.hpp @@ -15,6 +15,7 @@ #include #include + #include #include #include @@ -248,13 +249,19 @@ class set_impl template void clear_and_dispose(Disposer disposer); + #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::rbtree::count(const_reference)const - size_type count(const_reference value) const; + size_type count(const_reference value) const + { return static_cast(this->tree_type::find(value) != this->tree_type::cend()); } //! @copydoc ::boost::intrusive::rbtree::count(const KeyType&,KeyValueCompare)const template - size_type count(const KeyType& key, KeyValueCompare comp) const; - + size_type count(const KeyType& key, KeyValueCompare comp) const + { return static_cast(this->tree_type::find(key, comp) != this->tree_type::cend()); } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::rbtree::lower_bound(const_reference) iterator lower_bound(const_reference value); @@ -297,21 +304,29 @@ class set_impl template const_iterator find(const KeyType& key, KeyValueCompare comp) const; + #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference) - std::pair equal_range(const_reference value); + std::pair equal_range(const_reference value) + { return this->tree_type::lower_bound_range(value); } //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare) template - std::pair equal_range(const KeyType& key, KeyValueCompare comp); + std::pair equal_range(const KeyType& key, KeyValueCompare comp) + { return this->tree_type::lower_bound_range(key, comp); } //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference)const std::pair - equal_range(const_reference value) const; + equal_range(const_reference value) const + { return this->tree_type::lower_bound_range(value); } //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare)const template std::pair - equal_range(const KeyType& key, KeyValueCompare comp) const; + equal_range(const KeyType& key, KeyValueCompare comp) const + { return this->tree_type::lower_bound_range(key, comp); } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! @copydoc ::boost::intrusive::rbtree::bounded_range(const_reference,const_reference,bool,bool) std::pair bounded_range @@ -691,7 +706,7 @@ class multiset_impl //! @copydoc ::boost::intrusive::rbtree::count(const KeyType&,KeyValueCompare)const template size_type count(const KeyType& key, KeyValueCompare comp) const; - + //! @copydoc ::boost::intrusive::rbtree::lower_bound(const_reference) iterator lower_bound(const_reference value); diff --git a/include/boost/intrusive/set_hook.hpp b/include/boost/intrusive/set_hook.hpp index 38da7bc..e6bb3bd 100644 --- a/include/boost/intrusive/set_hook.hpp +++ b/include/boost/intrusive/set_hook.hpp @@ -16,6 +16,7 @@ #include #include + #include #include #include @@ -76,7 +77,7 @@ struct make_set_base_hook //! unique tag. //! //! \c void_pointer<> is the pointer type that will be used internally in the hook -//! and the the container configured to use this hook. +//! and the container configured to use this hook. //! //! \c link_mode<> will specify the linking mode of the hook (\c normal_link, //! \c auto_unlink or \c safe_link). @@ -203,7 +204,7 @@ struct make_set_member_hook //! \c link_mode<> and \c optimize_size<>. //! //! \c void_pointer<> is the pointer type that will be used internally in the hook -//! and the the container configured to use this hook. +//! and the container configured to use this hook. //! //! \c link_mode<> will specify the linking mode of the hook (\c normal_link, //! \c auto_unlink or \c safe_link). diff --git a/include/boost/intrusive/sg_set.hpp b/include/boost/intrusive/sg_set.hpp index 7e5d072..1997696 100644 --- a/include/boost/intrusive/sg_set.hpp +++ b/include/boost/intrusive/sg_set.hpp @@ -247,13 +247,19 @@ class sg_set_impl template void clear_and_dispose(Disposer disposer); + #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::sgtree::count(const_reference)const - size_type count(const_reference value) const; + size_type count(const_reference value) const + { return static_cast(this->tree_type::find(value) != this->tree_type::cend()); } //! @copydoc ::boost::intrusive::sgtree::count(const KeyType&,KeyValueCompare)const template - size_type count(const KeyType& key, KeyValueCompare comp) const; - + size_type count(const KeyType& key, KeyValueCompare comp) const + { return static_cast(this->tree_type::find(key, comp) != this->tree_type::cend()); } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::sgtree::lower_bound(const_reference) iterator lower_bound(const_reference value); @@ -296,21 +302,29 @@ class sg_set_impl template const_iterator find(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::sgtree::equal_range(const_reference) - std::pair equal_range(const_reference value); + #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! @copydoc ::boost::intrusive::sgtree::equal_range(const KeyType&,KeyValueCompare) + //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference) + std::pair equal_range(const_reference value) + { return this->tree_type::lower_bound_range(value); } + + //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare) template - std::pair equal_range(const KeyType& key, KeyValueCompare comp); + std::pair equal_range(const KeyType& key, KeyValueCompare comp) + { return this->tree_type::lower_bound_range(key, comp); } - //! @copydoc ::boost::intrusive::sgtree::equal_range(const_reference)const + //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference)const std::pair - equal_range(const_reference value) const; + equal_range(const_reference value) const + { return this->tree_type::lower_bound_range(value); } - //! @copydoc ::boost::intrusive::sgtree::equal_range(const KeyType&,KeyValueCompare)const + //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare)const template std::pair - equal_range(const KeyType& key, KeyValueCompare comp) const; + equal_range(const KeyType& key, KeyValueCompare comp) const + { return this->tree_type::lower_bound_range(key, comp); } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! @copydoc ::boost::intrusive::sgtree::bounded_range(const_reference,const_reference,bool,bool) std::pair bounded_range diff --git a/include/boost/intrusive/sgtree.hpp b/include/boost/intrusive/sgtree.hpp index 0be42dc..8cb2b5c 100644 --- a/include/boost/intrusive/sgtree.hpp +++ b/include/boost/intrusive/sgtree.hpp @@ -19,6 +19,7 @@ #define BOOST_INTRUSIVE_SGTREE_HPP #include +#include #include #include #include @@ -28,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -48,6 +48,12 @@ namespace intrusive { namespace detail{ +///////////////////////////////////////////////////////////// +// +// Halpha for fixed floating_point option +// +///////////////////////////////////////////////////////////// + //! Returns floor(log2(n)/log2(sqrt(2))) -> floor(2*log2(n)) //! Undefined if N is 0. //! @@ -55,7 +61,7 @@ namespace detail{ inline std::size_t calculate_h_sqrt2 (std::size_t n) { std::size_t f_log2 = detail::floor_log2(n); - return (2*f_log2) + (n >= detail::sqrt2_pow_2xplus1 (f_log2)); + return (2*f_log2) + static_cast(n >= detail::sqrt2_pow_2xplus1(f_log2)); } struct h_alpha_sqrt2_t @@ -76,6 +82,12 @@ struct alpha_0_75_by_max_size_t } }; +///////////////////////////////////////////////////////////// +// +// Halpha for fixed floating_point option +// +///////////////////////////////////////////////////////////// + struct h_alpha_t { explicit h_alpha_t(float inv_minus_logalpha) @@ -84,9 +96,12 @@ struct h_alpha_t std::size_t operator()(std::size_t n) const { - //Returns floor(log2(1/alpha(n))) -> - // floor(log2(n)/log(1/alpha)) -> - // floor(log2(n)/(-log2(alpha))) + //////////////////////////////////////////////////////////// + // This function must return "floor(log2(1/alpha(n)))" -> + // floor(log2(n)/log(1/alpha)) -> + // floor(log2(n)/-log2(alpha)) + // floor(log2(n)*(1/-log2(alpha))) + //////////////////////////////////////////////////////////// //return static_cast(std::log(float(n))*inv_minus_logalpha_); return static_cast(detail::fast_log2(float(n))*inv_minus_logalpha_); } @@ -119,7 +134,7 @@ struct alpha_holder typedef boost::intrusive::detail::alpha_by_max_size_t multiply_by_alpha_t; alpha_holder() : max_tree_size_(0) - { set_alpha(0.7f); } + { set_alpha(0.70711f); } // ~1/sqrt(2) float get_alpha() const { return alpha_; } @@ -211,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 @@ -248,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 @@ -397,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_; @@ -408,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_; @@ -425,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) @@ -462,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&) @@ -476,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_; @@ -496,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) @@ -517,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_; @@ -526,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_; @@ -546,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_; @@ -605,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; } @@ -666,7 +680,7 @@ class sgtree_impl //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const template size_type count(const KeyType& key, KeyValueCompare comp) const; - + //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference) iterator lower_bound(const_reference value); @@ -915,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/sgtree_algorithms.hpp b/include/boost/intrusive/sgtree_algorithms.hpp index 2dd129c..2e4ce28 100644 --- a/include/boost/intrusive/sgtree_algorithms.hpp +++ b/include/boost/intrusive/sgtree_algorithms.hpp @@ -18,9 +18,9 @@ #define BOOST_INTRUSIVE_SGTREE_ALGORITHMS_HPP #include +#include #include -#include #include #include #include @@ -187,6 +187,7 @@ class sgtree_algorithms //! @copydoc ::boost::intrusive::bstree_algorithms::count(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) template static std::size_t count(const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp); + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal_upper_bound(const node_ptr&,const node_ptr&,NodePtrCompare) @@ -330,25 +331,21 @@ class sgtree_algorithms //than the weight balanced method. node_ptr s = x; std::size_t size = 1; - for(std::size_t ancestor = 1; true; ++ancestor){ - if(ancestor == depth){ //Check if whole tree must be rebuilt - max_tree_size = tree_size; - bstree_algo::rebalance_subtree(NodeTraits::get_parent(s)); - break; - } - else{ //Go to the next scapegoat candidate - const node_ptr s_parent = NodeTraits::get_parent(s); - const node_ptr s_parent_left = NodeTraits::get_left(s_parent); - //Obtain parent's size (previous size + parent + sibling tree) - const node_ptr s_sibling = s_parent_left == s ? NodeTraits::get_right(s_parent) : s_parent_left; - size += 1 + bstree_algo::subtree_size(s_sibling); - s = s_parent; - if(ancestor > h_alpha(size)){ //is 's' scapegoat? - bstree_algo::rebalance_subtree(s); - break; - } + for(std::size_t ancestor = 1; ancestor != depth; ++ancestor){ + const node_ptr s_parent = NodeTraits::get_parent(s); + const node_ptr s_parent_left = NodeTraits::get_left(s_parent); + //Obtain parent's size (previous size + parent + sibling tree) + const node_ptr s_sibling = s_parent_left == s ? NodeTraits::get_right(s_parent) : s_parent_left; + size += 1 + bstree_algo::subtree_size(s_sibling); + s = s_parent; + if(ancestor > h_alpha(size)){ //is 's' scapegoat? + bstree_algo::rebalance_subtree(s); + return; } } + //The whole tree must be rebuilt + max_tree_size = tree_size; + bstree_algo::rebalance_subtree(NodeTraits::get_parent(s)); } } /// @endcond diff --git a/include/boost/intrusive/slist_hook.hpp b/include/boost/intrusive/slist_hook.hpp index fc160d9..a9d5be6 100644 --- a/include/boost/intrusive/slist_hook.hpp +++ b/include/boost/intrusive/slist_hook.hpp @@ -80,7 +80,7 @@ struct make_slist_base_hook //! \c auto_unlink or \c safe_link). //! //! \c void_pointer<> is the pointer type that will be used internally in the hook -//! and the the container configured to use this hook. +//! and the container configured to use this hook. #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else @@ -203,7 +203,7 @@ struct make_slist_member_hook //! \c auto_unlink or \c safe_link). //! //! \c void_pointer<> is the pointer type that will be used internally in the hook -//! and the the container configured to use this hook. +//! and the container configured to use this hook. #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else diff --git a/include/boost/intrusive/splay_set.hpp b/include/boost/intrusive/splay_set.hpp index 0a80ce6..f47799c 100644 --- a/include/boost/intrusive/splay_set.hpp +++ b/include/boost/intrusive/splay_set.hpp @@ -247,12 +247,18 @@ class splay_set_impl template void clear_and_dispose(Disposer disposer); - //! @copydoc ::boost::intrusive::splaytree::count(const_reference) - size_type count(const_reference value); + #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + + //! @copydoc ::boost::intrusive::splaytree::count(const_reference)const + size_type count(const_reference value) const + { return static_cast(this->tree_type::find(value) != this->tree_type::cend()); } //! @copydoc ::boost::intrusive::splaytree::count(const KeyType&,KeyValueCompare)const template - size_type count(const KeyType& key, KeyValueCompare comp); + size_type count(const KeyType& key, KeyValueCompare comp) const + { return static_cast(this->tree_type::find(key, comp) != this->tree_type::cend()); } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! @copydoc ::boost::intrusive::splaytree::count(const_reference)const size_type count(const_reference value) const; @@ -261,13 +267,6 @@ class splay_set_impl template size_type count(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::count_dont_splay(const_reference)const - size_type count_dont_splay(const_reference value) const; - - //! @copydoc ::boost::intrusive::splaytree::count_dont_splay(const KeyType&,KeyValueCompare)const - template - size_type count_dont_splay(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::lower_bound(const_reference) iterator lower_bound(const_reference value); @@ -282,13 +281,6 @@ class splay_set_impl template const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::lower_bound_dont_splay(const_reference)const - const_iterator lower_bound_dont_splay(const_reference value) const; - - //! @copydoc ::boost::intrusive::splaytree::lower_bound_dont_splay(const KeyType&,KeyValueCompare)const - template - const_iterator lower_bound_dont_splay(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::upper_bound(const_reference) iterator upper_bound(const_reference value); @@ -303,13 +295,6 @@ class splay_set_impl template const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::upper_bound_dont_splay(const_reference)const - const_iterator upper_bound_dont_splay(const_reference value) const; - - //! @copydoc ::boost::intrusive::splaytree::upper_bound_dont_splay(const KeyType&,KeyValueCompare)const - template - const_iterator upper_bound_dont_splay(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::find(const_reference) iterator find(const_reference value); @@ -324,37 +309,29 @@ class splay_set_impl template const_iterator find(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::find_dont_splay(const_reference)const - const_iterator find_dont_splay(const_reference value) const; + #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! @copydoc ::boost::intrusive::splaytree::find_dont_splay(const KeyType&,KeyValueCompare)const + //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference) + std::pair equal_range(const_reference value) + { return this->tree_type::lower_bound_range(value); } + + //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare) template - const_iterator find_dont_splay(const KeyType& key, KeyValueCompare comp) const; + std::pair equal_range(const KeyType& key, KeyValueCompare comp) + { return this->tree_type::lower_bound_range(key, comp); } - //! @copydoc ::boost::intrusive::splaytree::equal_range(const_reference) - std::pair equal_range(const_reference value); - - //! @copydoc ::boost::intrusive::splaytree::equal_range(const KeyType&,KeyValueCompare) - template - std::pair equal_range(const KeyType& key, KeyValueCompare comp); - - //! @copydoc ::boost::intrusive::splaytree::equal_range(const_reference)const + //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference)const std::pair - equal_range(const_reference value) const; + equal_range(const_reference value) const + { return this->tree_type::lower_bound_range(value); } - //! @copydoc ::boost::intrusive::splaytree::equal_range(const KeyType&,KeyValueCompare)const + //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare)const template std::pair - equal_range(const KeyType& key, KeyValueCompare comp) const; + equal_range(const KeyType& key, KeyValueCompare comp) const + { return this->tree_type::lower_bound_range(key, comp); } - //! @copydoc ::boost::intrusive::splaytree::equal_range_dont_splay(const_reference)const - std::pair - equal_range_dont_splay(const_reference value) const; - - //! @copydoc ::boost::intrusive::splaytree::equal_range_dont_splay(const KeyType&,KeyValueCompare)const - template - std::pair - equal_range_dont_splay(const KeyType& key, KeyValueCompare comp) const; + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! @copydoc ::boost::intrusive::splaytree::bounded_range(const_reference,const_reference,bool,bool) std::pair bounded_range @@ -374,15 +351,6 @@ class splay_set_impl std::pair bounded_range (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; - //! @copydoc ::boost::intrusive::splaytree::bounded_range_dont_splay(const_reference,const_reference,bool,bool)const - std::pair bounded_range_dont_splay - (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; - - //! @copydoc ::boost::intrusive::splaytree::bounded_range_dont_splay(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const - template - std::pair bounded_range_dont_splay - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; - //! @copydoc ::boost::intrusive::splaytree::s_iterator_to(reference) static iterator s_iterator_to(reference value); @@ -760,20 +728,6 @@ class splay_multiset_impl template size_type count(const KeyType& key, KeyValueCompare comp); - //! @copydoc ::boost::intrusive::splaytree::count(const_reference)const - size_type count(const_reference value) const; - - //! @copydoc ::boost::intrusive::splaytree::count(const KeyType&,KeyValueCompare)const - template - size_type count(const KeyType& key, KeyValueCompare comp) const; - - //! @copydoc ::boost::intrusive::splaytree::count_dont_splay(const_reference)const - size_type count_dont_splay(const_reference value) const; - - //! @copydoc ::boost::intrusive::splaytree::count_dont_splay(const KeyType&,KeyValueCompare)const - template - size_type count_dont_splay(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::lower_bound(const_reference) iterator lower_bound(const_reference value); @@ -788,13 +742,6 @@ class splay_multiset_impl template const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::lower_bound_dont_splay(const_reference)const - const_iterator lower_bound_dont_splay(const_reference value) const; - - //! @copydoc ::boost::intrusive::splaytree::lower_bound_dont_splay(const KeyType&,KeyValueCompare)const - template - const_iterator lower_bound_dont_splay(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::upper_bound(const_reference) iterator upper_bound(const_reference value); @@ -809,13 +756,6 @@ class splay_multiset_impl template const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::upper_bound_dont_splay(const_reference)const - const_iterator upper_bound_dont_splay(const_reference value) const; - - //! @copydoc ::boost::intrusive::splaytree::upper_bound_dont_splay(const KeyType&,KeyValueCompare)const - template - const_iterator upper_bound_dont_splay(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::find(const_reference) iterator find(const_reference value); @@ -830,13 +770,6 @@ class splay_multiset_impl template const_iterator find(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::find_dont_splay(const_reference)const - const_iterator find_dont_splay(const_reference value) const; - - //! @copydoc ::boost::intrusive::splaytree::find_dont_splay(const KeyType&,KeyValueCompare)const - template - const_iterator find_dont_splay(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::equal_range(const_reference) std::pair equal_range(const_reference value); @@ -853,15 +786,6 @@ class splay_multiset_impl std::pair equal_range(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::equal_range_dont_splay(const_reference)const - std::pair - equal_range_dont_splay(const_reference value) const; - - //! @copydoc ::boost::intrusive::splaytree::equal_range_dont_splay(const KeyType&,KeyValueCompare)const - template - std::pair - equal_range_dont_splay(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::splaytree::bounded_range(const_reference,const_reference,bool,bool) std::pair bounded_range (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); @@ -880,15 +804,6 @@ class splay_multiset_impl std::pair bounded_range (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; - //! @copydoc ::boost::intrusive::splaytree::bounded_range_dont_splay(const_reference,const_reference,bool,bool)const - std::pair bounded_range_dont_splay - (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; - - //! @copydoc ::boost::intrusive::splaytree::bounded_range_dont_splay(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const - template - std::pair bounded_range_dont_splay - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; - //! @copydoc ::boost::intrusive::splaytree::s_iterator_to(reference) static iterator s_iterator_to(reference value); diff --git a/include/boost/intrusive/splay_set_hook.hpp b/include/boost/intrusive/splay_set_hook.hpp deleted file mode 100644 index c78b4a3..0000000 --- a/include/boost/intrusive/splay_set_hook.hpp +++ /dev/null @@ -1,286 +0,0 @@ -///////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-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. -// -///////////////////////////////////////////////////////////////////////////// -#ifndef BOOST_INTRUSIVE_SPLAY_SET_HOOK_HPP -#define BOOST_INTRUSIVE_SPLAY_SET_HOOK_HPP - -#include -#include - -namespace boost { -namespace intrusive { - -//! Helper metafunction to define a \c splay_set_base_hook that yields to the same -//! type when the same options (either explicitly or implicitly) are used. -//! WARNING: Deprecated class, use `make_bs_set_base_hook` instead. -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) -template -#else -template -#endif -struct make_splay_set_base_hook -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) - #if defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - : public make_bs_set_base_hook - #else - : public make_bs_set_base_hook - #endif -#endif -{ - /// @cond - typedef typename make_bs_set_base_hook - < - #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - O1, O2, O3 - #else - Options... - #endif - >::type implementation_defined; - /// @endcond - typedef implementation_defined type; -}; - -//! Derive a class from splay_set_base_hook in order to store objects in -//! in a splay_set/splay_multiset. splay_set_base_hook holds the data necessary to maintain -//! the splay_set/splay_multiset and provides an appropriate value_traits class for splay_set/splay_multiset. -//! -//! The hook admits the following options: \c tag<>, \c void_pointer<>, -//! \c link_mode<> and \c optimize_size<>. -//! -//! \c tag<> defines a tag to identify the node. -//! The same tag value can be used in different classes, but if a class is -//! derived from more than one \c list_base_hook, then each \c list_base_hook needs its -//! unique tag. -//! -//! \c void_pointer<> is the pointer type that will be used internally in the hook -//! and the the container configured to use this hook. -//! -//! \c link_mode<> will specify the linking mode of the hook (\c normal_link, -//! \c auto_unlink or \c safe_link). -//! -//! WARNING: Deprecated class, use `bs_set_base_hook` instead. -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) -template -#else -template -#endif -class splay_set_base_hook - : public make_splay_set_base_hook< - #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - O1, O2, O3 - #else - Options... - #endif - >::type -{ - #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) - public: - //! Effects: If link_mode is \c auto_unlink or \c safe_link - //! initializes the node to an unlinked state. - //! - //! Throws: Nothing. - splay_set_base_hook(); - - //! Effects: If link_mode is \c auto_unlink or \c safe_link - //! initializes the node to an unlinked state. The argument is ignored. - //! - //! Throws: Nothing. - //! - //! Rationale: Providing a copy-constructor - //! makes classes using the hook STL-compliant without forcing the - //! user to do some additional work. \c swap can be used to emulate - //! move-semantics. - splay_set_base_hook(const splay_set_base_hook& ); - - //! Effects: Empty function. The argument is ignored. - //! - //! Throws: Nothing. - //! - //! Rationale: Providing an assignment operator - //! makes classes using the hook STL-compliant without forcing the - //! user to do some additional work. \c swap can be used to emulate - //! move-semantics. - splay_set_base_hook& operator=(const splay_set_base_hook& ); - - //! Effects: If link_mode is \c normal_link, the destructor does - //! nothing (ie. no code is generated). If link_mode is \c safe_link and the - //! object is stored in a set an assertion is raised. If link_mode is - //! \c auto_unlink and \c is_linked() is true, the node is unlinked. - //! - //! Throws: Nothing. - ~splay_set_base_hook(); - - //! Effects: Swapping two nodes swaps the position of the elements - //! related to those nodes in one or two containers. That is, if the node - //! this is part of the element e1, the node x is part of the element e2 - //! and both elements are included in the containers s1 and s2, then after - //! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1 - //! at the position of e1. If one element is not in a container, then - //! after the swap-operation the other element is not in a container. - //! Iterators to e1 and e2 related to those nodes are invalidated. - //! - //! Complexity: Constant - //! - //! Throws: Nothing. - void swap_nodes(splay_set_base_hook &other); - - //! Precondition: link_mode must be \c safe_link or \c auto_unlink. - //! - //! Returns: true, if the node belongs to a container, false - //! otherwise. This function can be used to test whether \c set::iterator_to - //! will return a valid iterator. - //! - //! Complexity: Constant - bool is_linked() const; - - //! Effects: Removes the node if it's inserted in a container. - //! This function is only allowed if link_mode is \c auto_unlink. - //! - //! Throws: Nothing. - void unlink(); - #endif -}; - -//! Helper metafunction to define a \c splay_set_member_hook that yields to the same -//! type when the same options (either explicitly or implicitly) are used. -//! -//! WARNING: Deprecated class, use `make_bs_set_member_hook` instead. -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) -template -#else -template -#endif -struct make_splay_set_member_hook -#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) - #if defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - : public make_bs_set_member_hook - #else - : public make_bs_set_member_hook - #endif -#endif -{ - /// @cond - typedef typename make_bs_set_member_hook - < - #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - O1, O2, O3 - #else - Options... - #endif - >::type implementation_defined; - /// @endcond - typedef implementation_defined type; -}; - -//! Put a public data member splay_set_member_hook in order to store objects of this -//! class in a splay_set/splay_multiset. splay_set_member_hook holds the data -//! necessary for maintaining the splay_set/splay_multiset and provides an appropriate -//! value_traits class for splay_set/splay_multiset. -//! -//! The hook admits the following options: \c void_pointer<>, -//! \c link_mode<> and \c optimize_size<>. -//! -//! \c void_pointer<> is the pointer type that will be used internally in the hook -//! and the the container configured to use this hook. -//! -//! \c link_mode<> will specify the linking mode of the hook (\c normal_link, -//! \c auto_unlink or \c safe_link). -//! -//! WARNING: Deprecated class, use `bs_set_member_hook` instead. -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) -template -#else -template -#endif -class splay_set_member_hook - : public make_splay_set_member_hook< - #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - O1, O2, O3 - #else - Options... - #endif - >::type -{ - #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) - public: - //! Effects: If link_mode is \c auto_unlink or \c safe_link - //! initializes the node to an unlinked state. - //! - //! Throws: Nothing. - splay_set_member_hook(); - - //! Effects: If link_mode is \c auto_unlink or \c safe_link - //! initializes the node to an unlinked state. The argument is ignored. - //! - //! Throws: Nothing. - //! - //! Rationale: Providing a copy-constructor - //! makes classes using the hook STL-compliant without forcing the - //! user to do some additional work. \c swap can be used to emulate - //! move-semantics. - splay_set_member_hook(const splay_set_member_hook& ); - - //! Effects: Empty function. The argument is ignored. - //! - //! Throws: Nothing. - //! - //! Rationale: Providing an assignment operator - //! makes classes using the hook STL-compliant without forcing the - //! user to do some additional work. \c swap can be used to emulate - //! move-semantics. - splay_set_member_hook& operator=(const splay_set_member_hook& ); - - //! Effects: If link_mode is \c normal_link, the destructor does - //! nothing (ie. no code is generated). If link_mode is \c safe_link and the - //! object is stored in a set an assertion is raised. If link_mode is - //! \c auto_unlink and \c is_linked() is true, the node is unlinked. - //! - //! Throws: Nothing. - ~splay_set_member_hook(); - - //! Effects: Swapping two nodes swaps the position of the elements - //! related to those nodes in one or two containers. That is, if the node - //! this is part of the element e1, the node x is part of the element e2 - //! and both elements are included in the containers s1 and s2, then after - //! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1 - //! at the position of e1. If one element is not in a container, then - //! after the swap-operation the other element is not in a container. - //! Iterators to e1 and e2 related to those nodes are invalidated. - //! - //! Complexity: Constant - //! - //! Throws: Nothing. - void swap_nodes(splay_set_member_hook &other); - - //! Precondition: link_mode must be \c safe_link or \c auto_unlink. - //! - //! Returns: true, if the node belongs to a container, false - //! otherwise. This function can be used to test whether \c set::iterator_to - //! will return a valid iterator. - //! - //! Complexity: Constant - bool is_linked() const; - - //! Effects: Removes the node if it's inserted in a container. - //! This function is only allowed if link_mode is \c auto_unlink. - //! - //! Throws: Nothing. - void unlink(); - #endif -}; - -} //namespace intrusive -} //namespace boost - -#include - -#endif //BOOST_INTRUSIVE_SPLAY_SET_HOOK_HPP diff --git a/include/boost/intrusive/splaytree.hpp b/include/boost/intrusive/splaytree.hpp index f02de06..24e4c74 100644 --- a/include/boost/intrusive/splaytree.hpp +++ b/include/boost/intrusive/splaytree.hpp @@ -13,6 +13,7 @@ #define BOOST_INTRUSIVE_SPLAYTREE_HPP #include +#include #include #include #include @@ -20,8 +21,6 @@ #include #include -#include -#include #include #include #include @@ -77,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 @@ -267,7 +265,6 @@ class splaytree_impl //! @copydoc ::boost::intrusive::bstree::erase(const KeyType&,KeyValueCompare) template - size_type erase(const KeyType& key, KeyValueCompare comp); //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_iterator,Disposer) @@ -293,60 +290,32 @@ class splaytree_impl template void clear_and_dispose(Disposer disposer); - #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! @copydoc ::boost::intrusive::bstree::count(const_reference)const - //! Additional note: non-const function, splaying is performed for the first - //! element of the equal range of "value" - size_type count(const_reference value) - { return this->count(value, this->value_comp()); } + //! Additional note: non-const function, splaying is performed. + size_type count(const_reference value); //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const - //! Additional note: non-const function, splaying is performed for the first - //! element of the equal range of "key" + //! Additional note: non-const function, splaying is performed. template - size_type count(const KeyType &key, KeyValueCompare comp) - { - std::pair ret = this->equal_range(key, comp); - return std::distance(ret.first, ret.second); - } + size_type count(const KeyType &key, KeyValueCompare comp); //! @copydoc ::boost::intrusive::bstree::count(const_reference)const - //! Additional note: Deprecated function, use count const overload instead. - size_type count(const_reference value) const - { return tree_type::count(value); } + //! Additional note: const function, no splaying is performed + size_type count(const_reference value) const; //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const - //! Additional note: Deprecated function, use count const overload instead. + //! Additional note: const function, no splaying is performed template - size_type count(const KeyType &key, KeyValueCompare comp) const - { return tree_type::count(key, comp); } + size_type count(const KeyType &key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::count(const_reference)const - //! Additional note: Deprecated function, use count const overload instead. - size_type count_dont_splay(const_reference value) const - { return tree_type::count(value); } - - //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const - //! Additional note: Deprecated function, use count const overload instead. - template - size_type count_dont_splay(const KeyType &key, KeyValueCompare comp) const - { return tree_type::count(key, comp); } - - #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference) - //! Additional note: non-const function, splaying is performed for the first - //! element of the equal range of "value" + //! Additional note: non-const function, splaying is performed. iterator lower_bound(const_reference value); //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference)const //! Additional note: const function, no splaying is performed const_iterator lower_bound(const_reference value) const; - //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference)const - //! Additional note: Deprecated function, use lower_bound const overload instead. - const_iterator lower_bound_dont_splay(const_reference value) const; - //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare) //! Additional note: non-const function, splaying is performed for the first //! element of the equal range of "key" @@ -358,11 +327,6 @@ class splaytree_impl template const_iterator lower_bound(const KeyType &key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare) - //! Additional note: Deprecated function, use lower_bound const overload instead. - template - iterator lower_bound_dont_splay(const KeyType &key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference) //! Additional note: non-const function, splaying is performed for the first //! element of the equal range of "value" @@ -372,10 +336,6 @@ class splaytree_impl //! Additional note: const function, no splaying is performed const_iterator upper_bound(const_reference value) const; - //! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference)const - //! Additional note: Deprecated function, use upper_bound const overload instead. - const_iterator upper_bound_dont_splay(const_reference value) const; - //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare) //! Additional note: non-const function, splaying is performed for the first //! element of the equal range of "key" @@ -387,11 +347,6 @@ class splaytree_impl template const_iterator upper_bound(const KeyType &key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare) - //! Additional note: Deprecated function, use upper_bound const overload instead. - template - const_iterator upper_bound_dont_splay(const KeyType &key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::find(const_reference) //! Additional note: non-const function, splaying is performed for the first //! element of the equal range of "value" @@ -401,10 +356,6 @@ class splaytree_impl //! Additional note: const function, no splaying is performed const_iterator find(const_reference value) const; - //! @copydoc ::boost::intrusive::bstree::find(const_reference)const - //! Additional note: Deprecated function, use find const overload instead. - const_iterator find_dont_splay(const_reference value) const; - //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare) //! Additional note: non-const function, splaying is performed for the first //! element of the equal range of "key" @@ -416,11 +367,6 @@ class splaytree_impl template const_iterator find(const KeyType &key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare)const - //! Additional note: Deprecated function, use find const overload instead. - template - const_iterator find_dont_splay(const KeyType &key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::equal_range(const_reference) //! Additional note: non-const function, splaying is performed for the first //! element of the equal range of "value" @@ -430,10 +376,6 @@ class splaytree_impl //! Additional note: const function, no splaying is performed std::pair equal_range(const_reference value) const; - //! @copydoc ::boost::intrusive::bstree::equal_range(const_reference)const - //! Additional note: Deprecated function, use equal_range const overload instead. - std::pair equal_range_dont_splay(const_reference value) const; - //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare) //! Additional note: non-const function, splaying is performed for the first //! element of the equal range of "key" @@ -445,11 +387,6 @@ class splaytree_impl template std::pair equal_range(const KeyType &key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare) - //! Additional note: Deprecated function, use equal_range const overload instead. - template - std::pair equal_range_dont_splay(const KeyType &key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::bstree::bounded_range(const_reference,const_reference,bool,bool) std::pair bounded_range (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); @@ -468,17 +405,6 @@ class splaytree_impl std::pair bounded_range (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; - //! @copydoc ::boost::intrusive::bstree::bounded_range(const_reference,const_reference,bool,bool)const - //! Additional note: Deprecated function, use bounded_range const overload instead. - std::pair bounded_range_dont_splay - (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; - - //! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const - //! Additional note: Deprecated function, use bounded_range const overload instead. - template - std::pair bounded_range_dont_splay - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; - //! @copydoc ::boost::intrusive::bstree::s_iterator_to(reference) static iterator s_iterator_to(reference value); @@ -529,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 @@ -644,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/splaytree_algorithms.hpp b/include/boost/intrusive/splaytree_algorithms.hpp index d9ce54c..b70bd86 100644 --- a/include/boost/intrusive/splaytree_algorithms.hpp +++ b/include/boost/intrusive/splaytree_algorithms.hpp @@ -31,8 +31,8 @@ #define BOOST_INTRUSIVE_SPLAYTREE_ALGORITHMS_HPP #include -#include #include +#include #include #include #include @@ -45,33 +45,70 @@ namespace intrusive { namespace detail { template -struct splaydown_rollback +struct splaydown_assemble_and_fix_header { typedef typename NodeTraits::node_ptr node_ptr; - splaydown_rollback( const node_ptr *pcur_subtree, const node_ptr & header - , const node_ptr & leftmost , const node_ptr & rightmost) - : pcur_subtree_(pcur_subtree) , header_(header) - , leftmost_(leftmost) , rightmost_(rightmost) + + splaydown_assemble_and_fix_header(const node_ptr & t, const node_ptr & header, const node_ptr &leftmost, const node_ptr &rightmost) + : t_(t) + , null_node_(header) + , l_(null_node_) + , r_(null_node_) + , leftmost_(leftmost) + , rightmost_(rightmost) {} - void release() - { pcur_subtree_ = 0; } - - ~splaydown_rollback() + ~splaydown_assemble_and_fix_header() { - if(pcur_subtree_){ - //Exception can only be thrown by comp, but - //tree invariants still hold. *pcur_subtree is the current root - //so link it to the header. - NodeTraits::set_parent(*pcur_subtree_, header_); - NodeTraits::set_parent(header_, *pcur_subtree_); - //Recover leftmost/rightmost pointers - NodeTraits::set_left (header_, leftmost_); - NodeTraits::set_right(header_, rightmost_); + this->assemble(); + + //Now recover the original header except for the + //splayed root node. + //"t_" is the current root and "null_node_" is the header node + NodeTraits::set_parent(null_node_, t_); + NodeTraits::set_parent(t_, null_node_); + //Recover leftmost/rightmost pointers + NodeTraits::set_left (null_node_, leftmost_); + NodeTraits::set_right(null_node_, rightmost_); + } + + private: + + void assemble() + { + //procedure assemble; + // left(r), right(l) := right(t), left(t); + // left(t), right(t) := right(null), left(null); + //end assemble; + { // left(r), right(l) := right(t), left(t); + + node_ptr const old_t_left = NodeTraits::get_left(t_); + node_ptr const old_t_right = NodeTraits::get_right(t_); + NodeTraits::set_right(l_, old_t_left); + NodeTraits::set_left (r_, old_t_right); + if(old_t_left){ + NodeTraits::set_parent(old_t_left, l_); + } + if(old_t_right){ + NodeTraits::set_parent(old_t_right, r_); + } + } + { // left(t), right(t) := right(null), left(null); + node_ptr const null_right = NodeTraits::get_right(null_node_); + node_ptr const null_left = NodeTraits::get_left(null_node_); + NodeTraits::set_left (t_, null_right); + NodeTraits::set_right(t_, null_left); + if(null_right){ + NodeTraits::set_parent(null_right, t_); + } + if(null_left){ + NodeTraits::set_parent(null_left, t_); + } } } - const node_ptr *pcur_subtree_; - node_ptr header_, leftmost_, rightmost_; + + public: + node_ptr t_, null_node_, l_, r_, leftmost_, rightmost_; }; } //namespace detail { @@ -184,32 +221,28 @@ class splaytree_algorithms #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! @copydoc ::boost::intrusive::bstree_algorithms::erase(const node_ptr&,const node_ptr&) - //! Additional notes: the previous node of z is splayed. The "splay" parameter which indicated if splaying - //! should be performed, it's deprecated and will disappear in future versions. - static void erase(const node_ptr & header, const node_ptr & z, bool splay = true) + //! Additional notes: the previous node of z is splayed to speed up range deletions. + static void erase(const node_ptr & header, const node_ptr & z) { //posibility 1 - if(splay && NodeTraits::get_left(z)){ + if(NodeTraits::get_left(z)){ splay_up(bstree_algo::prev_node(z), header); } /* //possibility 2 - if(splay && NodeTraits::get_left(z)){ + if(NodeTraits::get_left(z)){ node_ptr l = NodeTraits::get_left(z); splay_up(l, header); - }*//* - if(splay && NodeTraits::get_left(z)){ + }*/ + /* + if(NodeTraits::get_left(z)){ node_ptr l = bstree_algo::prev_node(z); splay_up_impl(l, z); }*/ /* //possibility 4 - if(splay){ - splay_up(z, header); - }*/ - - //if(splay) - //splay_up(z, header); + splay_up(z, header); + */ bstree_algo::erase(header, z); } @@ -225,7 +258,7 @@ class splaytree_algorithms #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! @copydoc ::boost::intrusive::bstree_algorithms::count(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) - //! Additional notes: the first node of the range is splayed. + //! Additional notes: an element with key `key` is splayed. template static std::size_t count (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) @@ -247,15 +280,14 @@ class splaytree_algorithms { return bstree_algo::count(header, key, comp); } //! @copydoc ::boost::intrusive::bstree_algorithms::lower_bound(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) - //! Additional notes: the first node of the range is splayed. The "splay" parameter which indicated if splaying - //! should be performed, it's deprecated and will disappear in future versions. + //! Additional notes: the first node of the range is splayed. template static node_ptr lower_bound - (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool splay = true) + (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) { - //splay_down(detail::uncast(header), key, comp); + splay_down(detail::uncast(header), key, comp); node_ptr y = bstree_algo::lower_bound(header, key, comp); - if(splay) splay_up(y, detail::uncast(header)); + //splay_up(y, detail::uncast(header)); return y; } @@ -267,15 +299,14 @@ class splaytree_algorithms { return bstree_algo::lower_bound(header, key, comp); } //! @copydoc ::boost::intrusive::bstree_algorithms::upper_bound(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) - //! Additional notes: the first node of the range is splayed. The "splay" parameter which indicated if splaying - //! should be performed, it's deprecated and will disappear in future versions. + //! Additional notes: the first node of the range is splayed. template static node_ptr upper_bound - (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool splay = true) + (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) { - //splay_down(detail::uncast(header), key, comp); + splay_down(detail::uncast(header), key, comp); node_ptr y = bstree_algo::upper_bound(header, key, comp); - if(splay) splay_up(y, detail::uncast(header)); + //splay_up(y, detail::uncast(header)); return y; } @@ -287,17 +318,13 @@ class splaytree_algorithms { return bstree_algo::upper_bound(header, key, comp); } //! @copydoc ::boost::intrusive::bstree_algorithms::find(const const_node_ptr&, const KeyType&,KeyNodePtrCompare) - //! Additional notes: the found node of the lower bound is splayed. The "splay" parameter which indicated if splaying - //! should be performed, it's deprecated and will disappear in future versions. + //! Additional notes: the found node of the lower bound is splayed. template static node_ptr find - (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool splay = true) + (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) { - if(splay) splay_down(detail::uncast(header), key, comp); - node_ptr end = detail::uncast(header); - node_ptr y = bstree_algo::lower_bound(header, key, comp); - node_ptr r = (y == end || comp(key, y)) ? end : y; - return r; + splay_down(detail::uncast(header), key, comp); + return bstree_algo::find(header, key, comp); } //! @copydoc ::boost::intrusive::bstree_algorithms::find(const const_node_ptr&, const KeyType&,KeyNodePtrCompare) @@ -308,15 +335,14 @@ class splaytree_algorithms { return bstree_algo::find(header, key, comp); } //! @copydoc ::boost::intrusive::bstree_algorithms::equal_range(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) - //! Additional notes: the first node of the range is splayed. The "splay" parameter which indicated if splaying - //! should be performed, it's deprecated and will disappear in future versions. + //! Additional notes: the first node of the range is splayed. template static std::pair equal_range - (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool splay = true) + (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) { - //splay_down(detail::uncast(header), key, comp); + splay_down(detail::uncast(header), key, comp); std::pair ret = bstree_algo::equal_range(header, key, comp); - if(splay) splay_up(ret.first, detail::uncast(header)); + //splay_up(ret.first, detail::uncast(header)); return ret; } @@ -327,17 +353,36 @@ class splaytree_algorithms (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) { return bstree_algo::equal_range(header, key, comp); } + //! @copydoc ::boost::intrusive::bstree_algorithms::lower_bound_range(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) + //! Additional notes: the first node of the range is splayed. + template + static std::pair lower_bound_range + (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) + { + splay_down(detail::uncast(header), key, comp); + std::pair ret = bstree_algo::lower_bound_range(header, key, comp); + //splay_up(ret.first, detail::uncast(header)); + return ret; + } + + //! @copydoc ::boost::intrusive::bstree_algorithms::lower_bound_range(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) + //! Additional note: no splaying is performed + template + static std::pair lower_bound_range + (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) + { return bstree_algo::lower_bound_range(header, key, comp); } + //! @copydoc ::boost::intrusive::bstree_algorithms::bounded_range(const const_node_ptr&,const KeyType&,const KeyType&,KeyNodePtrCompare,bool,bool) - //! Additional notes: the first node of the range is splayed. The "splay" parameter which indicated if splaying - //! should be performed, it's deprecated and will disappear in future versions. + //! Additional notes: the first node of the range is splayed. template static std::pair bounded_range (const node_ptr & header, const KeyType &lower_key, const KeyType &upper_key, KeyNodePtrCompare comp - , bool left_closed, bool right_closed, bool splay = true) + , bool left_closed, bool right_closed) { + splay_down(detail::uncast(header), lower_key, comp); std::pair ret = bstree_algo::bounded_range(header, lower_key, upper_key, comp, left_closed, right_closed); - if(splay) splay_up(ret.first, detail::uncast(header)); + //splay_up(ret.first, detail::uncast(header)); return ret; } @@ -445,6 +490,20 @@ class splaytree_algorithms // bottom-up splay, use data_ as parent for n | complexity : logarithmic | exception : nothrow static void splay_up(const node_ptr & node, const node_ptr & header) + { priv_splay_up(node, header); } + + // top-down splay | complexity : logarithmic | exception : strong, note A + template + static node_ptr splay_down(const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool *pfound = 0) + { return priv_splay_down(header, key, comp, pfound); } + + private: + + /// @cond + + // bottom-up splay, use data_ as parent for n | complexity : logarithmic | exception : nothrow + template + static void priv_splay_up(const node_ptr & node, const node_ptr & header) { // If (node == header) do a splay for the right most node instead // this is to boost performance of equal_range/count on equivalent containers in the case @@ -470,20 +529,19 @@ class splaytree_algorithms rotate(p); rotate(n); } - else{ + else { // zig-zag rotate(n); - rotate(n); + if(!SimpleSplay){ + rotate(n); + } } } } - // top-down splay | complexity : logarithmic | exception : strong, note A - template - static node_ptr splay_down(const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) + template + static node_ptr priv_splay_down(const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool *pfound = 0) { - if(!NodeTraits::get_parent(header)) - return header; //Most splay tree implementations use a dummy/null node to implement. //this function. This has some problems for a generic library like Intrusive: // @@ -494,118 +552,87 @@ class splaytree_algorithms //are not changed when splaying (because the invariants of the tree don't //change) We can back up them, use the header as the null node and //reassign old values after the function has been completed. - node_ptr t = NodeTraits::get_parent(header); - //Check if tree has a single node - if(!NodeTraits::get_left(t) && !NodeTraits::get_right(t)) - return t; - //Backup leftmost/rightmost - node_ptr leftmost (NodeTraits::get_left(header)); - node_ptr rightmost(NodeTraits::get_right(header)); - { - //Anti-exception rollback, recovers the original header node if an exception is thrown. - detail::splaydown_rollback rollback(&t, header, leftmost, rightmost); - node_ptr null_node = header; - node_ptr l = null_node; - node_ptr r = null_node; + node_ptr const old_root = NodeTraits::get_parent(header); + node_ptr const leftmost = NodeTraits::get_left(header); + node_ptr const rightmost = NodeTraits::get_right(header); + if(leftmost == rightmost){ //Empty or unique node + if(pfound){ + *pfound = old_root && !comp(key, old_root) && !comp(old_root, key); + } + return old_root ? old_root : header; + } + else{ + //Initialize "null node" (the header in our case) + NodeTraits::set_left (header, node_ptr()); + NodeTraits::set_right(header, node_ptr()); + //Class that will backup leftmost/rightmost from header, commit the assemble(), + //and will restore leftmost/rightmost to header even if "comp" throws + detail::splaydown_assemble_and_fix_header commit(old_root, header, leftmost, rightmost); + bool found = false; for( ;; ){ - if(comp(key, t)){ - if(NodeTraits::get_left(t) == node_ptr() ) + if(comp(key, commit.t_)){ + node_ptr const t_left = NodeTraits::get_left(commit.t_); + if(!t_left) break; - if(comp(key, NodeTraits::get_left(t))){ - t = bstree_algo::rotate_right(t); - - if(NodeTraits::get_left(t) == node_ptr()) + if(comp(key, t_left)){ + bstree_algo::rotate_right_no_parent_fix(commit.t_, t_left); + commit.t_ = t_left; + if( !NodeTraits::get_left(commit.t_) ) break; - link_right(t, r); - } - else if(comp(NodeTraits::get_left(t), key)){ - link_right(t, r); - - if(NodeTraits::get_right(t) == node_ptr() ) - break; - link_left(t, l); + link_right(commit.t_, commit.r_); } else{ - link_right(t, r); + link_right(commit.t_, commit.r_); + if(!SimpleSplay && comp(t_left, key)){ + if( !NodeTraits::get_right(commit.t_) ) + break; + link_left(commit.t_, commit.l_); + } } } - else if(comp(t, key)){ - if(NodeTraits::get_right(t) == node_ptr() ) + else if(comp(commit.t_, key)){ + node_ptr const t_right = NodeTraits::get_right(commit.t_); + if(!t_right) break; - if(comp(NodeTraits::get_right(t), key)){ - t = bstree_algo::rotate_left( t ); - - if(NodeTraits::get_right(t) == node_ptr() ) + if(comp(t_right, key)){ + bstree_algo::rotate_left_no_parent_fix(commit.t_, t_right); + commit.t_ = t_right; + if( !NodeTraits::get_right(commit.t_) ) break; - link_left(t, l); - } - else if(comp(key, NodeTraits::get_right(t))){ - link_left(t, l); - - if(NodeTraits::get_left(t) == node_ptr()) - break; - - link_right(t, r); + link_left(commit.t_, commit.l_); } else{ - link_left(t, l); + link_left(commit.t_, commit.l_); + if(!SimpleSplay && comp(key, t_right)){ + if( !NodeTraits::get_left(commit.t_) ) + break; + link_right(commit.t_, commit.r_); + } } } else{ + found = true; break; } } - assemble(t, l, r, null_node); - rollback.release(); - } - - //Now recover the original header except for the - //splayed root node. - //t is the current root - NodeTraits::set_parent(header, t); - NodeTraits::set_parent(t, header); - //Recover leftmost/rightmost pointers - NodeTraits::set_left (header, leftmost); - NodeTraits::set_right(header, rightmost); - return t; - } - - private: - - /// @cond - - // assemble the three sub-trees into new tree pointed to by t | complexity : constant | exception : nothrow - static void assemble(const node_ptr &t, const node_ptr & l, const node_ptr & r, const const_node_ptr & null_node ) - { - NodeTraits::set_right(l, NodeTraits::get_left(t)); - NodeTraits::set_left(r, NodeTraits::get_right(t)); - - if(NodeTraits::get_right(l) != node_ptr()){ - NodeTraits::set_parent(NodeTraits::get_right(l), l); - } - - if(NodeTraits::get_left(r) != node_ptr()){ - NodeTraits::set_parent(NodeTraits::get_left(r), r); - } - - NodeTraits::set_left (t, NodeTraits::get_right(null_node)); - NodeTraits::set_right(t, NodeTraits::get_left(null_node)); - - if( NodeTraits::get_left(t) != node_ptr() ){ - NodeTraits::set_parent(NodeTraits::get_left(t), t); - } - - if( NodeTraits::get_right(t) ){ - NodeTraits::set_parent(NodeTraits::get_right(t), t); + //commit.~splaydown_assemble_and_fix_header() will first + //"assemble()" + link the new root & recover header's leftmost & rightmost + if(pfound){ + *pfound = found; + } + return commit.t_; } } // break link to left child node and attach it to left tree pointed to by l | complexity : constant | exception : nothrow static void link_left(node_ptr & t, node_ptr & l) { + //procedure link_left; + // t, l, right(l) := right(t), t, t + //end link_left NodeTraits::set_right(l, t); NodeTraits::set_parent(t, l); l = t; @@ -615,6 +642,9 @@ class splaytree_algorithms // break link to right child node and attach it to right tree pointed to by r | complexity : constant | exception : nothrow static void link_right(node_ptr & t, node_ptr & r) { + //procedure link_right; + // t, r, left(r) := left(t), t, t + //end link_right; NodeTraits::set_left(r, t); NodeTraits::set_parent(t, r); r = t; @@ -624,6 +654,9 @@ class splaytree_algorithms // rotate n with its parent | complexity : constant | exception : nothrow static void rotate(const node_ptr & n) { + //procedure rotate_left; + // t, right(t), left(right(t)) := right(t), left(right(t)), t + //end rotate_left; node_ptr p = NodeTraits::get_parent(n); node_ptr g = NodeTraits::get_parent(p); //Test if g is header before breaking tree @@ -632,13 +665,13 @@ class splaytree_algorithms if(NodeTraits::get_left(p) == n){ NodeTraits::set_left(p, NodeTraits::get_right(n)); - if(NodeTraits::get_left(p) != node_ptr()) + if(NodeTraits::get_left(p)) NodeTraits::set_parent(NodeTraits::get_left(p), p); NodeTraits::set_right(n, p); } else{ // must be ( p->right == n ) NodeTraits::set_right(p, NodeTraits::get_left(n)); - if(NodeTraits::get_right(p) != node_ptr()) + if(NodeTraits::get_right(p)) NodeTraits::set_parent(NodeTraits::get_right(p), p); NodeTraits::set_left(n, p); } diff --git a/include/boost/intrusive/treap.hpp b/include/boost/intrusive/treap.hpp index 38b02d5..3bda6db 100644 --- a/include/boost/intrusive/treap.hpp +++ b/include/boost/intrusive/treap.hpp @@ -13,6 +13,7 @@ #define BOOST_INTRUSIVE_TREAP_HPP #include +#include #include #include #include @@ -21,7 +22,6 @@ #include #include -#include #include #include #include @@ -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); } @@ -910,7 +909,7 @@ class treap_impl //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const template size_type count(const KeyType& key, KeyValueCompare comp) const; - + //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference) iterator lower_bound(const_reference value); @@ -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_algorithms.hpp b/include/boost/intrusive/treap_algorithms.hpp index 1bdd3b3..2b0704b 100644 --- a/include/boost/intrusive/treap_algorithms.hpp +++ b/include/boost/intrusive/treap_algorithms.hpp @@ -14,9 +14,9 @@ #define BOOST_INTRUSIVE_TREAP_ALGORITHMS_HPP #include +#include #include -#include #include #include @@ -110,16 +110,17 @@ class treap_algorithms static void rotate_up_n(const node_ptr header, const node_ptr p, std::size_t n) { - for( node_ptr p_parent = NodeTraits::get_parent(p) - ; n-- - ; p_parent = NodeTraits::get_parent(p)){ - //Check if left child - if(p == NodeTraits::get_left(p_parent)){ - bstree_algo::rotate_right(p_parent, header); + node_ptr p_parent(NodeTraits::get_parent(p)); + node_ptr p_grandparent(NodeTraits::get_parent(p_parent)); + while(n--){ + if(p == NodeTraits::get_left(p_parent)){ //p is left child + bstree_algo::rotate_right(p_parent, p, p_grandparent, header); } - else{ //Right child - bstree_algo::rotate_left(p_parent, header); + else{ //p is right child + bstree_algo::rotate_left(p_parent, p, p_grandparent, header); } + p_parent = p_grandparent; + p_grandparent = NodeTraits::get_parent(p_parent); } } @@ -248,6 +249,7 @@ class treap_algorithms //! @copydoc ::boost::intrusive::bstree_algorithms::count(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) template static std::size_t count(const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp); + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! Requires: "h" must be the header node of a tree. @@ -525,7 +527,7 @@ class treap_algorithms (const node_ptr & header, const node_ptr & new_node, const insert_commit_data &commit_data) { bstree_algo::insert_unique_commit(header, new_node, commit_data); - rebalance_after_insertion_commit(header, new_node, commit_data.rotations); + rotate_up_n(header, new_node, commit_data.rotations); } #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED @@ -546,11 +548,12 @@ class treap_algorithms node_ptr z_left = NodeTraits::get_left(z); node_ptr z_right = NodeTraits::get_right(z); while(z_left || z_right){ + const node_ptr z_parent(NodeTraits::get_parent(z)); if(!z_right || (z_left && pcomp(z_left, z_right))){ - bstree_algo::rotate_right(z, header); + bstree_algo::rotate_right(z, z_left, z_parent, header); } else{ - bstree_algo::rotate_left(z, header); + bstree_algo::rotate_left(z, z_right, z_parent, header); } ++n; z_left = NodeTraits::get_left(z); @@ -566,10 +569,9 @@ class treap_algorithms rebalance_after_insertion_check(h, commit_data.node, new_node, pcomp, commit_data.rotations); //No-throw bstree_algo::insert_unique_commit(h, new_node, commit_data); - rebalance_after_insertion_commit(h, new_node, commit_data.rotations); + rotate_up_n(h, new_node, commit_data.rotations); } - template static void rebalance_after_insertion_check (const const_node_ptr &header, const const_node_ptr & up, const Key &k @@ -586,22 +588,6 @@ class treap_algorithms num_rotations = n; } - static void rebalance_after_insertion_commit(const node_ptr & header, const node_ptr & p, std::size_t n) - { - // Now execute n rotations - for( node_ptr p_parent = NodeTraits::get_parent(p) - ; n-- - ; p_parent = NodeTraits::get_parent(p)){ - //Check if left child - if(p == NodeTraits::get_left(p_parent)){ - bstree_algo::rotate_right(p_parent, header); - } - else{ //Right child - bstree_algo::rotate_left(p_parent, header); - } - } - } - template static bool check_invariant(const const_node_ptr & header, NodePtrPriorityCompare pcomp) { diff --git a/include/boost/intrusive/treap_set.hpp b/include/boost/intrusive/treap_set.hpp index 739e56b..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) @@ -291,13 +292,19 @@ class treap_set_impl template void clear_and_dispose(Disposer disposer); + #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::treap::count(const_reference)const - size_type count(const_reference value) const; + size_type count(const_reference value) const + { return static_cast(this->tree_type::find(value) != this->tree_type::cend()); } //! @copydoc ::boost::intrusive::treap::count(const KeyType&,KeyValueCompare)const template - size_type count(const KeyType& key, KeyValueCompare comp) const; - + size_type count(const KeyType& key, KeyValueCompare comp) const + { return static_cast(this->tree_type::find(key, comp) != this->tree_type::cend()); } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::treap::lower_bound(const_reference) iterator lower_bound(const_reference value); @@ -340,21 +347,29 @@ class treap_set_impl template const_iterator find(const KeyType& key, KeyValueCompare comp) const; - //! @copydoc ::boost::intrusive::treap::equal_range(const_reference) - std::pair equal_range(const_reference value); + #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! @copydoc ::boost::intrusive::treap::equal_range(const KeyType&,KeyValueCompare) + //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference) + std::pair equal_range(const_reference value) + { return this->tree_type::lower_bound_range(value); } + + //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare) template - std::pair equal_range(const KeyType& key, KeyValueCompare comp); + std::pair equal_range(const KeyType& key, KeyValueCompare comp) + { return this->tree_type::lower_bound_range(key, comp); } - //! @copydoc ::boost::intrusive::treap::equal_range(const_reference)const + //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference)const std::pair - equal_range(const_reference value) const; + equal_range(const_reference value) const + { return this->tree_type::lower_bound_range(value); } - //! @copydoc ::boost::intrusive::treap::equal_range(const KeyType&,KeyValueCompare)const + //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare)const template std::pair - equal_range(const KeyType& key, KeyValueCompare comp) const; + equal_range(const KeyType& key, KeyValueCompare comp) const + { return this->tree_type::lower_bound_range(key, comp); } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! @copydoc ::boost::intrusive::treap::bounded_range(const_reference,const_reference,bool,bool) std::pair bounded_range diff --git a/include/boost/intrusive/trivial_value_traits.hpp b/include/boost/intrusive/trivial_value_traits.hpp index 0ea306d..2505e08 100644 --- a/include/boost/intrusive/trivial_value_traits.hpp +++ b/include/boost/intrusive/trivial_value_traits.hpp @@ -13,6 +13,9 @@ #ifndef BOOST_INTRUSIVE_TRIVIAL_VALUE_TRAITS_HPP #define BOOST_INTRUSIVE_TRIVIAL_VALUE_TRAITS_HPP +#include +#include + #include #include @@ -22,7 +25,11 @@ namespace intrusive { //!This value traits template is used to create value traits //!from user defined node traits where value_traits::value_type and //!node_traits::node should be equal -template +template struct trivial_value_traits { typedef NodeTraits node_traits; @@ -43,4 +50,6 @@ struct trivial_value_traits } //namespace intrusive } //namespace boost +#include + #endif //BOOST_INTRUSIVE_TRIVIAL_VALUE_TRAITS_HPP 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/include/boost/intrusive/unordered_set_hook.hpp b/include/boost/intrusive/unordered_set_hook.hpp index 64797e9..fb17a33 100644 --- a/include/boost/intrusive/unordered_set_hook.hpp +++ b/include/boost/intrusive/unordered_set_hook.hpp @@ -207,7 +207,7 @@ struct make_unordered_set_base_hook //! unique tag. //! //! \c void_pointer<> is the pointer type that will be used internally in the hook -//! and the the container configured to use this hook. +//! and the container configured to use this hook. //! //! \c link_mode<> will specify the linking mode of the hook (\c normal_link, //! \c auto_unlink or \c safe_link). @@ -341,7 +341,7 @@ struct make_unordered_set_member_hook //! \c link_mode<> and \c store_hash<>. //! //! \c void_pointer<> is the pointer type that will be used internally in the hook -//! and the the container configured to use this hook. +//! and the container configured to use this hook. //! //! \c link_mode<> will specify the linking mode of the hook (\c normal_link, //! \c auto_unlink or \c safe_link). diff --git a/proj/vc7ide/Intrusive.sln b/proj/vc7ide/Intrusive.sln index 54fcb68..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 @@ -115,6 +111,14 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "scary_iterators", "scary_it ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pack_options", "pack_options\pack_options.vcproj", "{77F4139B-281B-F694-7CB1-3495467B4D35}" + 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 @@ -155,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 @@ -239,6 +239,14 @@ Global {7679B41B-C1C5-FA34-9614-3547B3140346}.Debug.Build.0 = Debug|Win32 {7679B41B-C1C5-FA34-9614-3547B3140346}.Release.ActiveCfg = Release|Win32 {7679B41B-C1C5-FA34-9614-3547B3140346}.Release.Build.0 = Release|Win32 + {77F4139B-281B-F694-7CB1-3495467B4D35}.Debug.ActiveCfg = Debug|Win32 + {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 31c88f3..fc4e758 100644 --- a/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj +++ b/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj @@ -157,6 +157,9 @@ + + @@ -361,9 +364,6 @@ - - diff --git a/proj/vc7ide/external_value_traits/external_value_traits.vcproj b/proj/vc7ide/external_value_traits/external_value_traits.vcproj deleted file mode 100644 index 87ebd51..0000000 --- a/proj/vc7ide/external_value_traits/external_value_traits.vcproj +++ /dev/null @@ -1,133 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/proj/vc7ide/set/set.vcproj b/proj/vc7ide/set/set.vcproj index f7a9976..2fb2369 100644 --- a/proj/vc7ide/set/set.vcproj +++ b/proj/vc7ide/set/set.vcproj @@ -21,6 +21,7 @@ Optimization="0" AdditionalIncludeDirectories="../../../../../" PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE" + GeneratePreprocessedFile="0" MinimalRebuild="TRUE" BasicRuntimeChecks="3" RuntimeLibrary="5" diff --git a/test/common_functors.hpp b/test/common_functors.hpp index 03fbc65..a6af9fb 100644 --- a/test/common_functors.hpp +++ b/test/common_functors.hpp @@ -15,6 +15,7 @@ #include #include +#include namespace boost { namespace intrusive { @@ -28,7 +29,7 @@ class delete_disposer void operator()(Pointer p) { typedef typename std::iterator_traits::value_type value_type; - BOOST_INTRUSIVE_INVARIANT_ASSERT(( detail::is_same::value )); + BOOST_STATIC_ASSERT(( detail::is_same::value )); delete boost::intrusive::detail::to_raw_pointer(p); } }; 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; -} diff --git a/test/has_member_function_callable_with.cpp b/test/has_member_function_callable_with.cpp index 96b822e..7839bf9 100644 --- a/test/has_member_function_callable_with.cpp +++ b/test/has_member_function_callable_with.cpp @@ -68,7 +68,7 @@ class has_member_function_named_func }}} -#if !defined(BOOST_CONTAINER_PERFECT_FORWARDING) +#if !defined(BOOST_INTRUSIVE_PERFECT_FORWARDING) namespace boost{ namespace intrusive{ @@ -147,7 +147,7 @@ class has_member_function_named_func { template - static decltype(boost::move_detail::declval().func(), has_member_function_callable_with::yes_type()) Test(Fun* f); + static decltype(boost::move_detail::declval().func(), has_member_function_callable_with::yes_type()) Test(U* f); template static has_member_function_callable_with::no_type Test(...); @@ -259,7 +259,7 @@ class has_member_function_named_func }}} -#else +#else //#if !defined(BOOST_INTRUSIVE_PERFECT_FORWARDING) namespace boost{ namespace intrusive{ @@ -283,6 +283,7 @@ class has_member_function_named_func namespace intrusive{ namespace intrusive_detail{ + #ifdef BOOST_NO_CXX11_DECLTYPE template().func(), 0)> struct zeroarg_checker_func { @@ -299,12 +300,19 @@ class has_member_function_named_func zeroarg_checker_func(int); }; + #endif //BOOST_NO_CXX11_DECLTYPE + template struct has_member_function_callable_with_func_impl { - template - static zeroarg_checker_func Test(zeroarg_checker_func*); + #ifndef BOOST_NO_CXX11_DECLTYPE + template().func()) > + static boost_intrusive_has_member_function_callable_with::yes_type Test(U*); + #else + template + static zeroarg_checker_func Test(zeroarg_checker_func*); + #endif template static has_member_function_callable_with::no_type Test(...); @@ -356,7 +364,7 @@ class has_member_function_named_func }}} -#endif +#endif //#if !defined(BOOST_INTRUSIVE_PERFECT_FORWARDING) struct functor { diff --git a/test/make_functions_test.cpp b/test/make_functions_test.cpp index 89de0e9..dcb8bc4 100644 --- a/test/make_functions_test.cpp +++ b/test/make_functions_test.cpp @@ -183,12 +183,6 @@ int main() return 1; } - if(detail::is_same, link_mode >::type - ,make_splay_set_base_hook<>::type - >::value == false){ - return 1; - } - //Check defined types and implicitly defined types are unequal if(detail::is_same, link_mode >::type ,make_list_base_hook<>::type @@ -220,12 +214,6 @@ int main() return 1; } - if(detail::is_same, link_mode >::type - ,make_splay_set_base_hook<>::type - >::value == true){ - return 1; - } - if(detail::is_same, link_mode >::type ,make_bs_set_base_hook<>::type >::value == true){ diff --git a/test/smart_ptr.hpp b/test/smart_ptr.hpp index 3a98804..8387d14 100644 --- a/test/smart_ptr.hpp +++ b/test/smart_ptr.hpp @@ -16,7 +16,7 @@ #include #include -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if (defined _MSC_VER) # pragma once #endif diff --git a/test/splay_multiset_test.cpp b/test/splay_multiset_test.cpp index bf8cb8e..7a21f07 100644 --- a/test/splay_multiset_test.cpp +++ b/test/splay_multiset_test.cpp @@ -77,15 +77,15 @@ struct my_tag; template struct hooks { - typedef splay_set_base_hook > base_hook_type; - typedef splay_set_base_hook + typedef bs_set_base_hook > base_hook_type; + typedef bs_set_base_hook < link_mode , void_pointer - , tag > auto_base_hook_type; - typedef splay_set_member_hook > member_hook_type; - typedef splay_set_member_hook + , tag > auto_base_hook_type; + typedef bs_set_member_hook > member_hook_type; + typedef bs_set_member_hook < link_mode - , void_pointer > auto_member_hook_type; + , void_pointer > auto_member_hook_type; }; template< class ValueType diff --git a/test/splay_set_test.cpp b/test/splay_set_test.cpp index a22accd..8e62f2c 100644 --- a/test/splay_set_test.cpp +++ b/test/splay_set_test.cpp @@ -74,15 +74,15 @@ struct my_tag; template struct hooks { - typedef splay_set_base_hook > base_hook_type; - typedef splay_set_base_hook + typedef bs_set_base_hook > base_hook_type; + typedef bs_set_base_hook < link_mode , void_pointer - , tag > auto_base_hook_type; - typedef splay_set_member_hook > member_hook_type; - typedef splay_set_member_hook + , tag > auto_base_hook_type; + typedef bs_set_member_hook > member_hook_type; + typedef bs_set_member_hook < link_mode - , void_pointer > auto_member_hook_type; + , void_pointer > auto_member_hook_type; }; template< class ValueType diff --git a/test/test_container.hpp b/test/test_container.hpp index bb6444d..47ac9e6 100644 --- a/test/test_container.hpp +++ b/test/test_container.hpp @@ -219,7 +219,7 @@ void test_common_unordered_and_associative_container(Container & c, Data & d, bo c.erase(*da, c.key_comp()); BOOST_TEST( c.size() == old_size-1 ); - //This should not eras anyone + //This should not erase any size_type second_erase = c.erase_and_dispose( *da, c.key_comp(), detail::null_disposer() ); BOOST_TEST( second_erase == 0 );