From fbd8e26461afb9685c1aa2ec69a6217227fc4e76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sun, 28 Jul 2013 22:10:37 +0000 Subject: [PATCH] * Big refactoring in order to reduce template and debug symbol bloat. * Fixes #8698 * Implemented SCARY iterators [SVN r85165] --- doc/Jamfile.v2 | 50 +- doc/intrusive.qbk | 62 +- example/Jamfile.v2 | 2 +- example/doc_advanced_value_traits.cpp | 2 +- example/doc_advanced_value_traits2.cpp | 2 +- example/doc_any_hook.cpp | 2 +- example/doc_assoc_optimized_code.cpp | 2 +- example/doc_auto_unlink.cpp | 2 +- example/doc_avl_set.cpp | 2 +- example/doc_avltree_algorithms.cpp | 2 +- example/doc_bucket_traits.cpp | 2 +- example/doc_clone_from.cpp | 2 +- example/doc_entity.cpp | 2 +- example/doc_erasing_and_disposing.cpp | 2 +- example/doc_external_value_traits.cpp | 2 +- example/doc_function_hooks.cpp | 2 +- example/doc_how_to_use.cpp | 2 +- example/doc_iterator_from_value.cpp | 2 +- example/doc_list.cpp | 2 +- example/doc_list_algorithms.cpp | 2 +- example/doc_offset_ptr.cpp | 2 +- example/doc_positional_insertion.cpp | 2 +- example/doc_rbtree_algorithms.cpp | 2 +- example/doc_recursive.cpp | 2 +- example/doc_recursive_member.cpp | 2 +- example/doc_set.cpp | 2 +- example/doc_sg_set.cpp | 2 +- example/doc_slist.cpp | 2 +- example/doc_slist_algorithms.cpp | 2 +- example/doc_splay_algorithms.cpp | 2 +- example/doc_splay_set.cpp | 11 +- example/doc_splaytree_algorithms.cpp | 2 +- example/doc_stateful_value_traits.cpp | 2 +- example/doc_treap_algorithms.cpp | 2 +- example/doc_treap_set.cpp | 2 +- example/doc_unordered_set.cpp | 2 +- example/doc_value_traits.cpp | 2 +- example/doc_window.cpp | 2 +- include/boost/intrusive/any_hook.hpp | 27 +- include/boost/intrusive/avl_set.hpp | 2448 +++------------- include/boost/intrusive/avl_set_hook.hpp | 14 +- include/boost/intrusive/avltree.hpp | 1775 ++--------- .../boost/intrusive/avltree_algorithms.hpp | 665 +---- include/boost/intrusive/bs_set.hpp | 922 ++++++ include/boost/intrusive/bs_set_hook.hpp | 24 +- include/boost/intrusive/bstree.hpp | 2012 +++++++++++++ ...e_algorithms.hpp => bstree_algorithms.hpp} | 1240 ++++---- .../intrusive/circular_list_algorithms.hpp | 13 +- .../intrusive/circular_slist_algorithms.hpp | 13 +- .../intrusive/derivation_value_traits.hpp | 2 +- .../detail/any_node_and_algorithms.hpp | 2 +- include/boost/intrusive/detail/assert.hpp | 2 +- .../boost/intrusive/detail/avltree_node.hpp | 2 +- .../detail/clear_on_destructor_base.hpp | 2 +- .../detail/common_slist_algorithms.hpp | 2 +- .../boost/intrusive/detail/config_begin.hpp | 2 +- include/boost/intrusive/detail/config_end.hpp | 2 +- .../intrusive/detail/ebo_functor_holder.hpp | 2 +- .../intrusive/detail/function_detector.hpp | 2 +- .../boost/intrusive/detail/generic_hook.hpp | 153 +- .../has_member_function_callable_with.hpp | 2 +- .../boost/intrusive/detail/hashtable_node.hpp | 160 +- .../detail/is_stateful_value_traits.hpp | 2 +- include/boost/intrusive/detail/list_node.hpp | 92 +- .../boost/intrusive/detail/memory_util.hpp | 2 +- include/boost/intrusive/detail/mpl.hpp | 2 +- .../intrusive/detail/parent_from_member.hpp | 28 +- .../boost/intrusive/detail/preprocessor.hpp | 2 +- .../boost/intrusive/detail/rbtree_node.hpp | 4 +- include/boost/intrusive/detail/slist_node.hpp | 88 +- .../intrusive/detail/transform_iterator.hpp | 2 +- include/boost/intrusive/detail/tree_node.hpp | 83 +- include/boost/intrusive/detail/utilities.hpp | 698 +++-- include/boost/intrusive/detail/workaround.hpp | 6 +- include/boost/intrusive/hashtable.hpp | 1615 +++++----- include/boost/intrusive/intrusive_fwd.hpp | 360 +-- .../intrusive/linear_slist_algorithms.hpp | 13 +- include/boost/intrusive/link_mode.hpp | 2 +- include/boost/intrusive/list.hpp | 125 +- include/boost/intrusive/list_hook.hpp | 14 +- .../boost/intrusive/member_value_traits.hpp | 2 +- include/boost/intrusive/options.hpp | 144 +- .../boost/intrusive/parent_from_member.hpp | 2 +- include/boost/intrusive/pointer_plus_bits.hpp | 2 +- include/boost/intrusive/pointer_traits.hpp | 2 +- include/boost/intrusive/priority_compare.hpp | 17 + include/boost/intrusive/rbtree.hpp | 1748 ++--------- include/boost/intrusive/rbtree_algorithms.hpp | 707 +---- include/boost/intrusive/set.hpp | 2389 +++------------ include/boost/intrusive/set_hook.hpp | 14 +- include/boost/intrusive/sg_set.hpp | 2483 +++------------- include/boost/intrusive/sgtree.hpp | 1848 +++--------- include/boost/intrusive/sgtree_algorithms.hpp | 737 +---- include/boost/intrusive/slist.hpp | 179 +- include/boost/intrusive/slist_hook.hpp | 14 +- include/boost/intrusive/splay_set.hpp | 2597 ++++------------ include/boost/intrusive/splay_set_hook.hpp | 68 +- include/boost/intrusive/splaytree.hpp | 1884 +++--------- .../boost/intrusive/splaytree_algorithms.hpp | 925 ++---- include/boost/intrusive/treap.hpp | 1348 ++------- include/boost/intrusive/treap_algorithms.hpp | 479 +-- include/boost/intrusive/treap_set.hpp | 2608 +++-------------- .../boost/intrusive/trivial_value_traits.hpp | 2 +- include/boost/intrusive/unordered_set.hpp | 367 ++- .../boost/intrusive/unordered_set_hook.hpp | 20 +- perf/Jamfile.v2 | 2 +- perf/perf_list.cpp | 2 +- perf/tree_perf_test.cpp | 214 ++ proj/vc7ide/Intrusive.sln | 16 + .../vc7ide/_intrusivelib/_intrusivelib.vcproj | 24 +- .../scary_iterators/scary_iterators.vcproj | 133 + proj/vc7ide/to-do.txt | 5 +- .../tree_perf_test/tree_perf_test.vcproj | 128 + test/any_test.cpp | 3 +- test/avl_multiset_test.cpp | 8 +- test/avl_set_test.cpp | 8 +- test/common_functors.hpp | 2 +- test/custom_bucket_traits_test.cpp | 2 +- test/default_hook_test.cpp | 146 +- test/external_value_traits_test.cpp | 3 +- test/function_hook_test.cpp | 2 +- test/generic_assoc_test.hpp | 38 +- test/generic_multiset_test.hpp | 16 +- test/generic_set_test.hpp | 22 +- test/has_member_function_callable_with.cpp | 2 +- test/itestvalue.hpp | 2 +- test/list_test.cpp | 2 +- test/make_functions_test.cpp | 12 +- test/multiset_test.cpp | 8 +- test/pointer_traits_test.cpp | 2 +- test/recursive_test.cpp | 2 +- test/scary_iterators_test.cpp | 314 ++ test/set_test.cpp | 8 +- test/sg_multiset_test.cpp | 14 +- test/sg_set_test.cpp | 14 +- test/slist_test.cpp | 206 +- test/splay_multiset_test.cpp | 27 +- test/splay_set_test.cpp | 24 +- test/stateful_value_traits_test.cpp | 2 +- test/test_container.hpp | 38 +- test/test_macros.hpp | 2 +- test/treap_multiset_test.cpp | 8 +- test/treap_set_test.cpp | 8 +- test/unordered_multiset_test.cpp | 2 +- test/unordered_set_test.cpp | 2 +- test/virtual_base_test.cpp | 5 +- 146 files changed, 12087 insertions(+), 22796 deletions(-) create mode 100644 include/boost/intrusive/bs_set.hpp create mode 100644 include/boost/intrusive/bstree.hpp rename include/boost/intrusive/{detail/tree_algorithms.hpp => bstree_algorithms.hpp} (76%) create mode 100644 perf/tree_perf_test.cpp create mode 100644 proj/vc7ide/scary_iterators/scary_iterators.vcproj create mode 100644 proj/vc7ide/tree_perf_test/tree_perf_test.vcproj create mode 100644 test/scary_iterators_test.cpp diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index 15c7372..36fb46c 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -13,6 +13,8 @@ import doxygen ; import quickbook ; path-constant here : . ; + + doxygen autodoc : [ glob ../../../boost/intrusive/*.hpp ] @@ -23,27 +25,33 @@ doxygen autodoc EXTRACT_PRIVATE=NO ENABLE_PREPROCESSING=YES MACRO_EXPANSION=YES - "PREDEFINED=BOOST_INTRUSIVE_DOXYGEN_INVOKED \\ - "list_impl=list" \\ - "slist_impl=slist" \\ - "set_impl=set" \\ - "multiset_impl=multiset" \\ - "rbtree_impl=rbtree" \\ - "unordered_set_impl=unordered_set" \\ - "unordered_multiset_impl=unordered_multiset" \\ - "hashtable_impl=hashtable" \\ - "splay_set_impl=splay_set" \\ - "splay_multiset_impl=splay_multiset" \\ - "splaytree_impl=splaytree" \\ - "sg_set_impl=sg_set" \\ - "sg_multiset_impl=sg_multiset" \\ - "sgtree_impl=sgtree" \\ - "avl_set_impl=avl_set" \\ - "avl_multiset_impl=avl_multiset" \\ - "avltree_impl=avltree" \\ - "treap_set_impl=treap_set" \\ - "treap_multiset_impl=treap_multiset" \\ - "treap_impl=treap"" + "PREDEFINED=\"BOOST_INTRUSIVE_DOXYGEN_INVOKED\" \\ + \"BOOST_INTRUSIVE_IMPDEF(T)=implementation_defined\" \\ + \"BOOST_INTRUSIVE_SEEDOC(T)=see_documentation\" \\ + \"BOOST_RV_REF(T)=T &&\" \\ + \"BOOST_RV_REF_BEG=\" \\ + \"BOOST_RV_REF_END=&&\" \\ + \"list_impl=list\" \\ + \"slist_impl=slist\" \\ + \"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\" \\ + \"splay_set_impl=splay_set\" \\ + \"splay_multiset_impl=splay_multiset\" \\ + \"splaytree_impl=splaytree\" \\ + \"sg_set_impl=sg_set\" \\ + \"sg_multiset_impl=sg_multiset\" \\ + \"sgtree_impl=sgtree\" \\ + \"avl_set_impl=avl_set\" \\ + \"avl_multiset_impl=avl_multiset\" \\ + \"avltree_impl=avltree\" \\ + \"treap_set_impl=treap_set\" \\ + \"treap_multiset_impl=treap_multiset\" \\ + \"treap_impl=treap\"" ; xml intrusive : intrusive.qbk diff --git a/doc/intrusive.qbk b/doc/intrusive.qbk index d35b493..6910de1 100644 --- a/doc/intrusive.qbk +++ b/doc/intrusive.qbk @@ -1,5 +1,5 @@ [/ - / Copyright (c) 2006-2012 Ion Gaztanaga + / Copyright (c) 2006-2013 Ion Gaztanaga / / 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) @@ -8,7 +8,7 @@ [library Boost.Intrusive [quickbook 1.5] [authors [Krzikalla, Olaf], [Gaztanaga, Ion]] - [copyright 2005 Olaf Krzikalla, 2006-2012 Ion Gaztanaga] + [copyright 2005 Olaf Krzikalla, 2006-2013 Ion Gaztanaga] [id intrusive] [dirname intrusive] [purpose Intrusive containers] @@ -434,6 +434,14 @@ Now we can use the container: [endsect] +However, member hooks have some implementation limitations: If there is a virtual inheritance +relationship between the parent and the member hook, then the distance between the parent +and the hook is not a compile-time fixed value so obtaining the address of +the parent from the member hook is not possible without reverse engineering compiler +produced RTTI. Apart from this, the non-standard pointer to member implementation for classes +with complex inheritance relationships in MSVC ABI compatible-compilers is not supported +by member hooks since it also depends on compiler-produced RTTI information. + [section:usage_both_hooks Using both hooks] You can insert the same object in several intrusive containers at the same time, @@ -3357,6 +3365,36 @@ To analyze the thread safety, consider the following points: [endsect] +[section:scary_iterators Scary Iterators] + +The paper N2913, titled [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2913.pdf, +SCARY Iterator Assignment and Initialization], proposed a requirement that a standard container’s +iterator types have no dependency on any type argument apart from the container’s `value_type`, +`difference_type`, `pointer type`, and `const_pointer` type. In particular, according to the proposal, +the types of a standard container’s iterators should not depend on the container’s `key_compare`, +`hasher`, `key_equal`, or `allocator` types. + +That paper demonstrated that SCARY operations were crucial to the performant implementation of common +design patterns using STL components. It showed that implementations that support SCARY operations reduce +object code bloat by eliminating redundant specializations of iterator and algorithm templates. + +[*Boost.Intrusive] containers are a bit different from standard containers. In particular, they have no +allocator parameter and they can be configured with additional options not present in STL-like containers. +Thus [*Boost.Intrusive] offers its own `SCARY iterator` implementation, where iterator types don't +change when the container is configured with an option that does not alter the value <-> node transformation. +More concretely, the following options and conditions guarantee that iterator types are unchanged: + +* [*All containers]: `size_type<>`, `constant_time_size<>`, +* [*`slist`]: `cache_last<>`, `linear<>`, +* [*`unordered_[multi]set`]: `hash<>`, `equal<>`, `power_2_buckets<>`, `cache_begin<>`. +* [*All tree-like containers] (`[multi]set`, `avl_[multi]set`, `sg_[multi]set`, `bs_[multi]set`, + `splay_[multi]set`, `treap_[multi]set`): `compare<>`. +* [*`treap_[multi]set`]: `priority<>` +* [*`bs_[multi]set`, `sg_[multi]set`, `treap_[multi]set`, `splay_[multi]set`]: + They share the same iterator type when configured with the same options. + +[endsect] + [section:equal_range_stability Stability and insertion with hint in ordered associative containers with equivalent keys] [*Boost.Intrusive] ordered associative containers with equivalent keys offer stability guarantees, following @@ -3846,6 +3884,24 @@ to be inserted in intrusive containers are allocated using `std::vector` or `std [section:release_notes Release Notes] +[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. + 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 + (see [@https://svn.boost.org/trac/boost/ticket/8698 #8698]) causing severe bugs when values to be inserted + where allocated next to the bucket array. End iterator implementation was changed to point to the beginning + of the bucket array. + +* Big refactoring in order to reduce template and debug symbol bloat. Test object files have been slashed + to half in MSVC compilers in Debug mode. Toolchains without Identical COMDAT Folding (ICF) should notice size improvements. + +* Implemented [link intrusive.scary_iterators SCARY iterators]. + +[endsect] + [section:release_notes_boost_1_54_00 Boost 1.54 Release] * Added `BOOST_NO_EXCEPTIONS` support (bug [@https://svn.boost.org/trac/boost/ticket/7849 #7849]). @@ -3932,7 +3988,7 @@ to be inserted in intrusive containers are allocated using `std::vector` or `std [section:release_notes_boost_1_40_00 Boost 1.40 Release] -* Code cleanup in tree_algorithms.hpp and avl_tree_algorithms.hpp +* Code cleanup in bstree_algorithms.hpp and avl_tree_algorithms.hpp * Fixed bug [@https://svn.boost.org/trac/boost/ticket/3164 #3164]. diff --git a/example/Jamfile.v2 b/example/Jamfile.v2 index 4bafc5c..d6a465e 100644 --- a/example/Jamfile.v2 +++ b/example/Jamfile.v2 @@ -1,6 +1,6 @@ # Boost Intrusive Library Example Jamfile -# (C) Copyright Ion Gaztanaga 2006-2012. +# (C) Copyright Ion Gaztanaga 2006-2013. # Use, modification and distribution are subject to 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) diff --git a/example/doc_advanced_value_traits.cpp b/example/doc_advanced_value_traits.cpp index 5efdeea..a295901 100644 --- a/example/doc_advanced_value_traits.cpp +++ b/example/doc_advanced_value_traits.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 diff --git a/example/doc_advanced_value_traits2.cpp b/example/doc_advanced_value_traits2.cpp index f69d0ac..1104530 100644 --- a/example/doc_advanced_value_traits2.cpp +++ b/example/doc_advanced_value_traits2.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 diff --git a/example/doc_any_hook.cpp b/example/doc_any_hook.cpp index a04de14..03bd0d2 100644 --- a/example/doc_any_hook.cpp +++ b/example/doc_any_hook.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008-2012 +// (C) Copyright Ion Gaztanaga 2008-2013 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/example/doc_assoc_optimized_code.cpp b/example/doc_assoc_optimized_code.cpp index 931f3f4..530ad79 100644 --- a/example/doc_assoc_optimized_code.cpp +++ b/example/doc_assoc_optimized_code.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 diff --git a/example/doc_auto_unlink.cpp b/example/doc_auto_unlink.cpp index 9947172..5fb12f4 100644 --- a/example/doc_auto_unlink.cpp +++ b/example/doc_auto_unlink.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 diff --git a/example/doc_avl_set.cpp b/example/doc_avl_set.cpp index 1baba57..73d7b02 100644 --- a/example/doc_avl_set.cpp +++ b/example/doc_avl_set.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 diff --git a/example/doc_avltree_algorithms.cpp b/example/doc_avltree_algorithms.cpp index d606b8a..d5a71eb 100644 --- a/example/doc_avltree_algorithms.cpp +++ b/example/doc_avltree_algorithms.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 diff --git a/example/doc_bucket_traits.cpp b/example/doc_bucket_traits.cpp index 83dded5..20ce7be 100644 --- a/example/doc_bucket_traits.cpp +++ b/example/doc_bucket_traits.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 diff --git a/example/doc_clone_from.cpp b/example/doc_clone_from.cpp index d21bb85..eeb844d 100644 --- a/example/doc_clone_from.cpp +++ b/example/doc_clone_from.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 diff --git a/example/doc_entity.cpp b/example/doc_entity.cpp index 70f693d..02122a6 100644 --- a/example/doc_entity.cpp +++ b/example/doc_entity.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 diff --git a/example/doc_erasing_and_disposing.cpp b/example/doc_erasing_and_disposing.cpp index 8f0cf0f..7e0d27c 100644 --- a/example/doc_erasing_and_disposing.cpp +++ b/example/doc_erasing_and_disposing.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 diff --git a/example/doc_external_value_traits.cpp b/example/doc_external_value_traits.cpp index ea377ce..c8ec1ce 100644 --- a/example/doc_external_value_traits.cpp +++ b/example/doc_external_value_traits.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 diff --git a/example/doc_function_hooks.cpp b/example/doc_function_hooks.cpp index 640006c..9640fb3 100644 --- a/example/doc_function_hooks.cpp +++ b/example/doc_function_hooks.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2010-2012 +// (C) Copyright Ion Gaztanaga 2010-2013 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/example/doc_how_to_use.cpp b/example/doc_how_to_use.cpp index 834c4f8..dcd893e 100644 --- a/example/doc_how_to_use.cpp +++ b/example/doc_how_to_use.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 diff --git a/example/doc_iterator_from_value.cpp b/example/doc_iterator_from_value.cpp index 2ba1c6c..f9c1a9a 100644 --- a/example/doc_iterator_from_value.cpp +++ b/example/doc_iterator_from_value.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 diff --git a/example/doc_list.cpp b/example/doc_list.cpp index 3ec6876..629b682 100644 --- a/example/doc_list.cpp +++ b/example/doc_list.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 diff --git a/example/doc_list_algorithms.cpp b/example/doc_list_algorithms.cpp index 7f94f77..fbb600e 100644 --- a/example/doc_list_algorithms.cpp +++ b/example/doc_list_algorithms.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 diff --git a/example/doc_offset_ptr.cpp b/example/doc_offset_ptr.cpp index fb7854a..9d83816 100644 --- a/example/doc_offset_ptr.cpp +++ b/example/doc_offset_ptr.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 diff --git a/example/doc_positional_insertion.cpp b/example/doc_positional_insertion.cpp index 83ff279..c851fbd 100644 --- a/example/doc_positional_insertion.cpp +++ b/example/doc_positional_insertion.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2009-2012 +// (C) Copyright Ion Gaztanaga 2009-2013 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/example/doc_rbtree_algorithms.cpp b/example/doc_rbtree_algorithms.cpp index 62ec7ae..db5cb2a 100644 --- a/example/doc_rbtree_algorithms.cpp +++ b/example/doc_rbtree_algorithms.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 diff --git a/example/doc_recursive.cpp b/example/doc_recursive.cpp index fa8198e..def4b28 100644 --- a/example/doc_recursive.cpp +++ b/example/doc_recursive.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 diff --git a/example/doc_recursive_member.cpp b/example/doc_recursive_member.cpp index ff1e3ea..37126e6 100644 --- a/example/doc_recursive_member.cpp +++ b/example/doc_recursive_member.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2010-2012 +// (C) Copyright Ion Gaztanaga 2010-2013 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/example/doc_set.cpp b/example/doc_set.cpp index e5a1d51..22c69c8 100644 --- a/example/doc_set.cpp +++ b/example/doc_set.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 diff --git a/example/doc_sg_set.cpp b/example/doc_sg_set.cpp index 3ca3145..49b711d 100644 --- a/example/doc_sg_set.cpp +++ b/example/doc_sg_set.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 diff --git a/example/doc_slist.cpp b/example/doc_slist.cpp index be8398e..c513177 100644 --- a/example/doc_slist.cpp +++ b/example/doc_slist.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 diff --git a/example/doc_slist_algorithms.cpp b/example/doc_slist_algorithms.cpp index 94ddaaa..33c5ae3 100644 --- a/example/doc_slist_algorithms.cpp +++ b/example/doc_slist_algorithms.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 diff --git a/example/doc_splay_algorithms.cpp b/example/doc_splay_algorithms.cpp index 1c00035..99d5f0f 100644 --- a/example/doc_splay_algorithms.cpp +++ b/example/doc_splay_algorithms.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 diff --git a/example/doc_splay_set.cpp b/example/doc_splay_set.cpp index f3467f5..50f89e6 100644 --- a/example/doc_splay_set.cpp +++ b/example/doc_splay_set.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 @@ -17,10 +17,11 @@ using namespace boost::intrusive; -class MyClass - : public splay_set_base_hook<> //This is an splay tree base hook - , public bs_set_base_hook<> //This is a binary search tree base hook +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 { int int_; @@ -43,7 +44,7 @@ class MyClass typedef splay_set< MyClass, compare > > BaseSplaySet; //Define a set using the binary search tree hook -typedef splay_set< MyClass, base_hook > > BaseBsSplaySet; +typedef splay_set< MyClass, base_hook > > > BaseBsSplaySet; //Define an multiset using the member hook typedef member_hook, &MyClass::member_hook_> MemberOption; diff --git a/example/doc_splaytree_algorithms.cpp b/example/doc_splaytree_algorithms.cpp index 9e2cb3d..8268fa7 100644 --- a/example/doc_splaytree_algorithms.cpp +++ b/example/doc_splaytree_algorithms.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 diff --git a/example/doc_stateful_value_traits.cpp b/example/doc_stateful_value_traits.cpp index 376211a..d26e8b7 100644 --- a/example/doc_stateful_value_traits.cpp +++ b/example/doc_stateful_value_traits.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 diff --git a/example/doc_treap_algorithms.cpp b/example/doc_treap_algorithms.cpp index fa0b11e..96ce48a 100644 --- a/example/doc_treap_algorithms.cpp +++ b/example/doc_treap_algorithms.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 diff --git a/example/doc_treap_set.cpp b/example/doc_treap_set.cpp index ebba369..e82cede 100644 --- a/example/doc_treap_set.cpp +++ b/example/doc_treap_set.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 diff --git a/example/doc_unordered_set.cpp b/example/doc_unordered_set.cpp index fc3403f..f276a7d 100644 --- a/example/doc_unordered_set.cpp +++ b/example/doc_unordered_set.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 diff --git a/example/doc_value_traits.cpp b/example/doc_value_traits.cpp index be091cc..e8209a2 100644 --- a/example/doc_value_traits.cpp +++ b/example/doc_value_traits.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 diff --git a/example/doc_window.cpp b/example/doc_window.cpp index 67ff275..c033876 100644 --- a/example/doc_window.cpp +++ b/example/doc_window.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 diff --git a/include/boost/intrusive/any_hook.hpp b/include/boost/intrusive/any_hook.hpp index 7d60de0..03c299f 100644 --- a/include/boost/intrusive/any_hook.hpp +++ b/include/boost/intrusive/any_hook.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 @@ -37,7 +37,7 @@ struct get_any_node_algo #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else -template +template #endif struct make_any_base_hook { @@ -51,11 +51,11 @@ struct make_any_base_hook #endif >::type packed_options; - typedef detail::generic_hook + typedef generic_hook < get_any_node_algo , typename packed_options::tag , packed_options::link_mode - , detail::AnyBaseHook + , AnyBaseHookId > implementation_defined; /// @endcond typedef implementation_defined type; @@ -142,7 +142,7 @@ class any_base_hook #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else -template +template #endif struct make_any_member_hook { @@ -156,11 +156,11 @@ struct make_any_member_hook #endif >::type packed_options; - typedef detail::generic_hook + typedef generic_hook < get_any_node_algo , member_tag , packed_options::link_mode - , detail::NoBaseHook + , NoBaseHookId > implementation_defined; /// @endcond typedef implementation_defined type; @@ -244,7 +244,7 @@ namespace detail{ template struct any_to_get_base_pointer_type { - typedef typename pointer_traits::template + typedef typename pointer_traits::template rebind_pointer::type type; }; @@ -260,17 +260,18 @@ struct any_to_get_member_pointer_type template class NodeTraits> struct any_to_some_hook { - typedef typename BaseHook::template pack::value_traits old_value_traits; + typedef typename BaseHook::template pack::proto_value_traits old_proto_value_traits; + template struct pack : public Base { - struct value_traits : public old_value_traits + struct proto_value_traits : public old_proto_value_traits { static const bool is_any_hook = true; typedef typename detail::eval_if_c - < detail::internal_base_hook_bool_is_true::value - , any_to_get_base_pointer_type - , any_to_get_member_pointer_type + < detail::internal_base_hook_bool_is_true::value + , any_to_get_base_pointer_type + , any_to_get_member_pointer_type >::type void_pointer; typedef NodeTraits node_traits; }; diff --git a/include/boost/intrusive/avl_set.hpp b/include/boost/intrusive/avl_set.hpp index 9e17aa7..a4b8044 100644 --- a/include/boost/intrusive/avl_set.hpp +++ b/include/boost/intrusive/avl_set.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 @@ -36,14 +36,15 @@ namespace intrusive { #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class avl_set_impl +#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + : public bstree_impl +#endif { /// @cond - typedef avltree_impl tree_type; - //! This class is - //! movable + typedef bstree_impl tree_type; BOOST_MOVABLE_BUT_NOT_COPYABLE(avl_set_impl) typedef tree_type implementation_defined; @@ -71,1208 +72,367 @@ class avl_set_impl typedef typename implementation_defined::const_node_ptr const_node_ptr; typedef typename implementation_defined::node_algorithms node_algorithms; - static const bool constant_time_size = Config::constant_time_size; - - /// @cond - private: - tree_type tree_; - /// @endcond + static const bool constant_time_size = tree_type::constant_time_size; public: - //! Effects: Constructs an empty avl_set. - //! - //! Complexity: Constant. - //! - //! Throws: If value_traits::node_traits::node - //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) - //! or the copy constructor of the value_compare object throws. + + //! @copydoc ::boost::intrusive::avltree::avltree(const value_compare &,const value_traits &) explicit avl_set_impl( const value_compare &cmp = value_compare() - , const value_traits &v_traits = value_traits()) - : tree_(cmp, v_traits) + , const value_traits &v_traits = value_traits()) + : tree_type(cmp, v_traits) {} - //! Requires: Dereferencing iterator must yield an lvalue of type value_type. - //! cmp must be a comparison function that induces a strict weak ordering. - //! - //! Effects: Constructs an empty avl_set and inserts elements from - //! [b, e). - //! - //! Complexity: Linear in N if [b, e) is already sorted using - //! comp and otherwise N * log N, where N is std::distance(last, first). - //! - //! Throws: If value_traits::node_traits::node - //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) - //! or the copy constructor/operator() of the value_compare object throws. + //! @copydoc ::boost::intrusive::avltree::avltree(bool,Iterator,Iterator,const value_compare &,const value_traits &) template avl_set_impl( Iterator b, Iterator e , const value_compare &cmp = value_compare() , const value_traits &v_traits = value_traits()) - : tree_(true, b, e, cmp, v_traits) + : tree_type(true, b, e, cmp, v_traits) {} - //! Effects: to-do - //! + //! @copydoc ::boost::intrusive::avltree::avltree(avltree &&) avl_set_impl(BOOST_RV_REF(avl_set_impl) x) - : tree_(::boost::move(x.tree_)) + : tree_type(::boost::move(static_cast(x))) {} - //! Effects: to-do - //! + //! @copydoc ::boost::intrusive::avltree::operator=(avltree &&) avl_set_impl& operator=(BOOST_RV_REF(avl_set_impl) x) - { tree_ = ::boost::move(x.tree_); return *this; } + { return static_cast(tree_type::operator=(::boost::move(static_cast(x)))); } - //! Effects: Detaches all elements from this. The objects in the avl_set - //! are not deleted (i.e. no destructors are called). - //! - //! Complexity: Linear to the number of elements on the container. - //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. - //! - //! Throws: Nothing. - ~avl_set_impl() - {} + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! Effects: Returns an iterator pointing to the beginning of the avl_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator begin() - { return tree_.begin(); } + //! @copydoc ::boost::intrusive::avltree::~avltree() + ~avl_set_impl(); - //! Effects: Returns a const_iterator pointing to the beginning of the avl_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator begin() const - { return tree_.begin(); } + //! @copydoc ::boost::intrusive::avltree::begin() + iterator begin(); - //! Effects: Returns a const_iterator pointing to the beginning of the avl_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator cbegin() const - { return tree_.cbegin(); } + //! @copydoc ::boost::intrusive::avltree::begin()const + const_iterator begin() const; - //! Effects: Returns an iterator pointing to the end of the avl_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator end() - { return tree_.end(); } + //! @copydoc ::boost::intrusive::avltree::cbegin()const + const_iterator cbegin() const; - //! Effects: Returns a const_iterator pointing to the end of the avl_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator end() const - { return tree_.end(); } + //! @copydoc ::boost::intrusive::avltree::end() + iterator end(); - //! Effects: Returns a const_iterator pointing to the end of the avl_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator cend() const - { return tree_.cend(); } + //! @copydoc ::boost::intrusive::avltree::end()const + const_iterator end() const; - //! Effects: Returns a reverse_iterator pointing to the beginning of the - //! reversed avl_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - reverse_iterator rbegin() - { return tree_.rbegin(); } + //! @copydoc ::boost::intrusive::avltree::cend()const + const_iterator cend() const; - //! Effects: Returns a const_reverse_iterator pointing to the beginning - //! of the reversed avl_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator rbegin() const - { return tree_.rbegin(); } + //! @copydoc ::boost::intrusive::avltree::begin() + reverse_iterator avlegin(); - //! Effects: Returns a const_reverse_iterator pointing to the beginning - //! of the reversed avl_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator crbegin() const - { return tree_.crbegin(); } + //! @copydoc ::boost::intrusive::avltree::begin()const + const_reverse_iterator avlegin() const; - //! Effects: Returns a reverse_iterator pointing to the end - //! of the reversed avl_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - reverse_iterator rend() - { return tree_.rend(); } + //! @copydoc ::boost::intrusive::avltree::crbegin()const + const_reverse_iterator crbegin() const; - //! Effects: Returns a const_reverse_iterator pointing to the end - //! of the reversed avl_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator rend() const - { return tree_.rend(); } + //! @copydoc ::boost::intrusive::avltree::rend() + reverse_iterator rend(); - //! Effects: Returns a const_reverse_iterator pointing to the end - //! of the reversed avl_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator crend() const - { return tree_.crend(); } + //! @copydoc ::boost::intrusive::avltree::rend()const + const_reverse_iterator rend() const; - //! Precondition: end_iterator must be a valid end iterator - //! of avl_set. - //! - //! Effects: Returns a const reference to the avl_set associated to the end iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - static avl_set_impl &container_from_end_iterator(iterator end_iterator) - { - return *detail::parent_from_member - ( &tree_type::container_from_end_iterator(end_iterator) - , &avl_set_impl::tree_); - } + //! @copydoc ::boost::intrusive::avltree::crend()const + const_reverse_iterator crend() const; - //! Precondition: end_iterator must be a valid end const_iterator - //! of avl_set. - //! - //! Effects: Returns a const reference to the set associated to the end iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - static const avl_set_impl &container_from_end_iterator(const_iterator end_iterator) - { - return *detail::parent_from_member - ( &tree_type::container_from_end_iterator(end_iterator) - , &avl_set_impl::tree_); - } + //! @copydoc ::boost::intrusive::avltree::container_from_end_iterator(iterator) + static avl_set_impl &container_from_end_iterator(iterator end_iterator); - //! Precondition: it must be a valid iterator of set. - //! - //! Effects: Returns a reference to the set associated to the iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Logarithmic. - static avl_set_impl &container_from_iterator(iterator it) - { - return *detail::parent_from_member - ( &tree_type::container_from_iterator(it) - , &avl_set_impl::tree_); - } + //! @copydoc ::boost::intrusive::avltree::container_from_end_iterator(const_iterator) + static const avl_set_impl &container_from_end_iterator(const_iterator end_iterator); - //! Precondition: it must be a valid const_iterator of set. - //! - //! Effects: Returns a const reference to the set associated to the iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Logarithmic. - static const avl_set_impl &container_from_iterator(const_iterator it) - { - return *detail::parent_from_member - ( &tree_type::container_from_iterator(it) - , &avl_set_impl::tree_); - } + //! @copydoc ::boost::intrusive::avltree::container_from_iterator(iterator) + static avl_set_impl &container_from_iterator(iterator it); - //! Effects: Returns the key_compare object used by the avl_set. - //! - //! Complexity: Constant. - //! - //! Throws: If key_compare copy-constructor throws. - key_compare key_comp() const - { return tree_.value_comp(); } + //! @copydoc ::boost::intrusive::avltree::container_from_iterator(const_iterator) + static const avl_set_impl &container_from_iterator(const_iterator it); - //! Effects: Returns the value_compare object used by the avl_set. - //! - //! Complexity: Constant. - //! - //! Throws: If value_compare copy-constructor throws. - value_compare value_comp() const - { return tree_.value_comp(); } + //! @copydoc ::boost::intrusive::avltree::key_comp()const + key_compare key_comp() const; - //! Effects: Returns true is the container is empty. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - bool empty() const - { return tree_.empty(); } + //! @copydoc ::boost::intrusive::avltree::value_comp()const + value_compare value_comp() const; - //! Effects: Returns the number of elements stored in the avl_set. - //! - //! Complexity: Linear to elements contained in *this if, - //! constant-time size option is enabled. Constant-time otherwise. - //! - //! Throws: Nothing. - size_type size() const - { return tree_.size(); } + //! @copydoc ::boost::intrusive::avltree::empty()const + bool empty() const; - //! Effects: Swaps the contents of two sets. - //! - //! Complexity: Constant. - //! - //! Throws: If the swap() call for the comparison functor - //! found using ADL throws. Strong guarantee. - void swap(avl_set_impl& other) - { tree_.swap(other.tree_); } + //! @copydoc ::boost::intrusive::avltree::size()const + size_type size() const; - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! Cloner should yield to nodes equivalent to the original nodes. - //! - //! Effects: Erases all the elements from *this - //! calling Disposer::operator()(pointer), clones all the - //! elements from src calling Cloner::operator()(const_reference ) - //! and inserts them on *this. Copies the predicate from the source container. - //! - //! If cloner throws, all cloned elements are unlinked and disposed - //! calling Disposer::operator()(pointer). - //! - //! Complexity: Linear to erased plus inserted elements. - //! - //! Throws: If cloner throws or predicate copy assignment throws. Basic guarantee. + //! @copydoc ::boost::intrusive::avltree::swap + void swap(avl_set_impl& other); + + //! @copydoc ::boost::intrusive::avltree::clone_from template - void clone_from(const avl_set_impl &src, Cloner cloner, Disposer disposer) - { tree_.clone_from(src.tree_, cloner, disposer); } + void clone_from(const avl_set_impl &src, Cloner cloner, Disposer disposer); + + #endif //#ifdef BOOST_iNTRUSIVE_DOXYGEN_INVOKED - //! Requires: value must be an lvalue - //! - //! Effects: Treaps to inserts value into the avl_set. - //! - //! Returns: If the value - //! is not already present inserts it and returns a pair containing the - //! iterator to the new value and true. If there is an equivalent value - //! returns a pair containing an iterator to the already present value - //! and false. - //! - //! Complexity: Average complexity for insert element is at - //! most logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. Strong guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + //! @copydoc ::boost::intrusive::avltree::insert_unique(reference) std::pair insert(reference value) - { return tree_.insert_unique(value); } + { return tree_type::insert_unique(value); } - //! Requires: value must be an lvalue - //! - //! Effects: Treaps to to insert x into the avl_set, using "hint" - //! as a hint to where it will be inserted. - //! - //! Returns: An iterator that points to the position where the - //! new element was inserted into the avl_set. - //! - //! Complexity: Logarithmic in general, but it's amortized - //! constant time if t is inserted immediately before hint. - //! - //! Throws: If the internal value_compare ordering function throws. Strong guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + //! @copydoc ::boost::intrusive::avltree::insert_unique(const_iterator,reference) iterator insert(const_iterator hint, reference value) - { return tree_.insert_unique(hint, value); } + { return tree_type::insert_unique(hint, value); } - //! Requires: key_value_comp must be a comparison function that induces - //! the same strict weak ordering as value_compare. The difference is that - //! key_value_comp compares an arbitrary key with the contained values. - //! - //! Effects: Checks if a value can be inserted in the avl_set, using - //! a user provided key instead of the value itself. - //! - //! Returns: If there is an equivalent value - //! returns a pair containing an iterator to the already present value - //! and false. If the value can be inserted returns true in the returned - //! pair boolean and fills "commit_data" that is meant to be used with - //! the "insert_commit" function. - //! - //! Complexity: Average complexity is at most logarithmic. - //! - //! Throws: If the key_value_comp ordering function throws. Strong guarantee. - //! - //! Notes: This function is used to improve performance when constructing - //! a value_type is expensive: if there is an equivalent value - //! the constructed object must be discarded. Many times, the part of the - //! node that is used to impose the order is much cheaper to construct - //! than the value_type and this function offers the possibility to use that - //! part to check if the insertion will be successful. - //! - //! If the check is successful, the user can construct the value_type and use - //! "insert_commit" to insert the object in constant-time. This gives a total - //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)). - //! - //! "commit_data" remains valid for a subsequent "insert_commit" only if no more - //! objects are inserted or erased from the avl_set. + //! @copydoc ::boost::intrusive::avltree::insert_unique_check(const KeyType&,KeyValueCompare,insert_commit_data&) template std::pair insert_check (const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data) - { return tree_.insert_unique_check(key, key_value_comp, commit_data); } + { return tree_type::insert_unique_check(key, key_value_comp, commit_data); } - //! Requires: key_value_comp must be a comparison function that induces - //! the same strict weak ordering as value_compare. The difference is that - //! key_value_comp compares an arbitrary key with the contained values. - //! - //! Effects: Checks if a value can be inserted in the avl_set, using - //! a user provided key instead of the value itself, using "hint" - //! as a hint to where it will be inserted. - //! - //! Returns: If there is an equivalent value - //! returns a pair containing an iterator to the already present value - //! and false. If the value can be inserted returns true in the returned - //! pair boolean and fills "commit_data" that is meant to be used with - //! the "insert_commit" function. - //! - //! Complexity: Logarithmic in general, but it's amortized - //! constant time if t is inserted immediately before hint. - //! - //! Throws: If the key_value_comp ordering function throws. Strong guarantee. - //! - //! Notes: This function is used to improve performance when constructing - //! a value_type is expensive: if there is an equivalent value - //! the constructed object must be discarded. Many times, the part of the - //! constructing that is used to impose the order is much cheaper to construct - //! than the value_type and this function offers the possibility to use that key - //! to check if the insertion will be successful. - //! - //! If the check is successful, the user can construct the value_type and use - //! "insert_commit" to insert the object in constant-time. This can give a total - //! constant-time complexity to the insertion: check(O(1)) + commit(O(1)). - //! - //! "commit_data" remains valid for a subsequent "insert_commit" only if no more - //! objects are inserted or erased from the avl_set. + //! @copydoc ::boost::intrusive::avltree::insert_unique_check(const_iterator,const KeyType&,KeyValueCompare,insert_commit_data&) template std::pair insert_check (const_iterator hint, const KeyType &key ,KeyValueCompare key_value_comp, insert_commit_data &commit_data) - { return tree_.insert_unique_check(hint, key, key_value_comp, commit_data); } + { return tree_type::insert_unique_check(hint, key, key_value_comp, commit_data); } - //! Requires: value must be an lvalue of type value_type. commit_data - //! must have been obtained from a previous call to "insert_check". - //! No objects should have been inserted or erased from the avl_set between - //! the "insert_check" that filled "commit_data" and the call to "insert_commit". - //! - //! Effects: Inserts the value in the avl_set using the information obtained - //! from the "commit_data" that a previous "insert_check" filled. - //! - //! Returns: An iterator to the newly inserted object. - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Notes: This function has only sense if a "insert_check" has been - //! previously executed to fill "commit_data". No value should be inserted or - //! erased between the "insert_check" and "insert_commit" calls. - iterator insert_commit(reference value, const insert_commit_data &commit_data) - { return tree_.insert_unique_commit(value, commit_data); } - - //! Requires: Dereferencing iterator must yield an lvalue - //! of type value_type. - //! - //! Effects: Inserts a range into the avl_set. - //! - //! Complexity: Insert range is in general O(N * log(N)), where N is the - //! size of the range. However, it is linear in N if the range is already sorted - //! by value_comp(). - //! - //! Throws: If the internal value_compare ordering function throws. Basic guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + //! @copydoc ::boost::intrusive::avltree::insert_unique(Iterator,Iterator) template void insert(Iterator b, Iterator e) - { tree_.insert_unique(b, e); } + { tree_type::insert_unique(b, e); } - //! Requires: value must be an lvalue, "pos" must be - //! a valid iterator (or end) and must be the succesor of value - //! once inserted according to the predicate. "value" must not be equal to any - //! inserted key according to the predicate. - //! - //! Effects: Inserts x into the tree before "pos". - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Note: This function does not check preconditions so if "pos" is not - //! the successor of "value" or "value" is not unique tree ordering and uniqueness - //! invariants will be broken respectively. - //! This is a low-level function to be used only for performance reasons - //! by advanced users. - iterator insert_before(const_iterator pos, reference value) - { return tree_.insert_before(pos, value); } + //! @copydoc ::boost::intrusive::avltree::insert_unique_commit + iterator insert_commit(reference value, const insert_commit_data &commit_data) + { return tree_type::insert_unique_commit(value, commit_data); } - //! Requires: value must be an lvalue, and it must be greater than - //! any inserted key according to the predicate. - //! - //! Effects: Inserts x into the tree in the last position. - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Note: This function does not check preconditions so if value is - //! less than or equal to the greatest inserted key tree ordering invariant will be broken. - //! This function is slightly more efficient than using "insert_before". - //! This is a low-level function to be used only for performance reasons - //! by advanced users. - void push_back(reference value) - { tree_.push_back(value); } + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::avltree::insert_before + iterator insert_before(const_iterator pos, reference value); - //! Requires: value must be an lvalue, and it must be less - //! than any inserted key according to the predicate. - //! - //! Effects: Inserts x into the tree in the first position. - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Note: This function does not check preconditions so if value is - //! greater than or equal to the the mimum inserted key tree ordering or uniqueness - //! invariants will be broken. - //! This function is slightly more efficient than using "insert_before". - //! This is a low-level function to be used only for performance reasons - //! by advanced users. - void push_front(reference value) - { tree_.push_front(value); } + //! @copydoc ::boost::intrusive::avltree::push_back + void push_back(reference value); - //! Effects: Erases the element pointed to by pos. - //! - //! Complexity: Average complexity is constant time. - //! - //! Returns: An iterator to the element after the erased element. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - iterator erase(const_iterator i) - { return tree_.erase(i); } + //! @copydoc ::boost::intrusive::avltree::push_front + void push_front(reference value); - //! Effects: Erases the range pointed to by b end e. - //! - //! Complexity: Average complexity for erase range is at most - //! O(log(size() + N)), where N is the number of elements in the range. - //! - //! Returns: An iterator to the element after the erased elements. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - iterator erase(const_iterator b, const_iterator e) - { return tree_.erase(b, e); } + //! @copydoc ::boost::intrusive::avltree::erase(const_iterator) + iterator erase(const_iterator i); - //! Effects: Erases all the elements with the given value. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: O(log(size()) + this->count(value)). - //! - //! Throws: If the internal value_compare ordering function throws. Basic guarantee. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - size_type erase(const_reference value) - { return tree_.erase(value); } + //! @copydoc ::boost::intrusive::avltree::erase(const_iterator,const_iterator) + iterator erase(const_iterator b, const_iterator e); - //! Effects: Erases all the elements that compare equal with - //! the given key and the given comparison functor. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: O(log(size() + this->count(key, comp)). - //! - //! Throws: If the comp ordering function throws. Basic guarantee. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. + //! @copydoc ::boost::intrusive::avltree::erase(const_reference) + size_type erase(const_reference value); + + //! @copydoc ::boost::intrusive::avltree::erase(const KeyType&,KeyValueCompare) template - size_type erase(const KeyType& key, KeyValueCompare comp - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) - { return tree_.erase(key, comp); } + size_type erase(const KeyType& key, KeyValueCompare comp); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases the element pointed to by pos. - //! Disposer::operator()(pointer) is called for the removed element. - //! - //! Complexity: Average complexity for erase element is constant time. - //! - //! Returns: An iterator to the element after the erased element. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::avltree::erase_and_dispose(const_iterator,Disposer) template - iterator erase_and_dispose(const_iterator i, Disposer disposer) - { return tree_.erase_and_dispose(i, disposer); } + iterator erase_and_dispose(const_iterator i, Disposer disposer); - #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + //! @copydoc ::boost::intrusive::avltree::erase_and_dispose(const_iterator,const_iterator,Disposer) template - iterator erase_and_dispose(iterator i, Disposer disposer) - { return this->erase_and_dispose(const_iterator(i), disposer); } - #endif + iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases the range pointed to by b end e. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Complexity: Average complexity for erase range is at most - //! O(log(size() + N)), where N is the number of elements in the range. - //! - //! Returns: An iterator to the element after the erased elements. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::avltree::erase_and_dispose(const_reference, Disposer) template - iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer) - { return tree_.erase_and_dispose(b, e, disposer); } + size_type erase_and_dispose(const_reference value, Disposer disposer); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements with the given value. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Throws: If the internal value_compare ordering function throws. - //! - //! Complexity: O(log(size() + this->count(value)). Basic guarantee. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - template - size_type erase_and_dispose(const_reference value, Disposer disposer) - { return tree_.erase_and_dispose(value, disposer); } - - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements with the given key. - //! according to the comparison functor "comp". - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: O(log(size() + this->count(key, comp)). - //! - //! Throws: If comp ordering function throws. Basic guarantee. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::avltree::erase_and_dispose(const KeyType&,KeyValueCompare,Disposer) template - size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) - { return tree_.erase_and_dispose(key, comp, disposer); } + size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer); - //! Effects: Erases all the elements of the container. - //! - //! Complexity: Linear to the number of elements on the container. - //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - void clear() - { return tree_.clear(); } + //! @copydoc ::boost::intrusive::avltree::clear + void clear(); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements of the container. - //! - //! Complexity: Linear to the number of elements on the container. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. + //! @copydoc ::boost::intrusive::avltree::clear_and_dispose template - void clear_and_dispose(Disposer disposer) - { return tree_.clear_and_dispose(disposer); } + void clear_and_dispose(Disposer disposer); - //! Effects: Returns the number of contained elements with the given key - //! - //! Complexity: Logarithmic to the number of elements contained plus lineal - //! to number of objects with the given key. - //! - //! Throws: If the internal value_compare ordering function throws. - size_type count(const_reference value) const - { return tree_.find(value) != end(); } + //! @copydoc ::boost::intrusive::avltree::count(const_reference)const + size_type count(const_reference value) const; - //! Effects: Returns the number of contained elements with the same key - //! compared with the given comparison functor. - //! - //! Complexity: Logarithmic to the number of elements contained plus lineal - //! to number of objects with the given key. - //! - //! Throws: If comp ordering function throws. + //! @copydoc ::boost::intrusive::avltree::count(const KeyType&,KeyValueCompare)const template - size_type count(const KeyType& key, KeyValueCompare comp) const - { return tree_.find(key, comp) != end(); } - - //! Effects: Returns an iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - iterator lower_bound(const_reference value) - { return tree_.lower_bound(value); } - - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Returns an iterator to the first element whose - //! key according to the comparison functor is not less than k or - //! end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + size_type count(const KeyType& key, KeyValueCompare comp) const; + + //! @copydoc ::boost::intrusive::avltree::lower_bound(const_reference) + iterator lower_bound(const_reference value); + + //! @copydoc ::boost::intrusive::avltree::lower_bound(const KeyType&,KeyValueCompare) template - iterator lower_bound(const KeyType& key, KeyValueCompare comp) - { return tree_.lower_bound(key, comp); } + iterator lower_bound(const KeyType& key, KeyValueCompare comp); - //! Effects: Returns a const iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - const_iterator lower_bound(const_reference value) const - { return tree_.lower_bound(value); } + //! @copydoc ::boost::intrusive::avltree::lower_bound(const_reference)const + const_iterator lower_bound(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Returns a const_iterator to the first element whose - //! key according to the comparison functor is not less than k or - //! end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::avltree::lower_bound(const KeyType&,KeyValueCompare)const template - const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const - { return tree_.lower_bound(key, comp); } + const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Returns an iterator to the first element whose - //! key is greater than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - iterator upper_bound(const_reference value) - { return tree_.upper_bound(value); } + //! @copydoc ::boost::intrusive::avltree::upper_bound(const_reference) + iterator upper_bound(const_reference value); - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Returns an iterator to the first element whose - //! key according to the comparison functor is greater than key or - //! end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::avltree::upper_bound(const KeyType&,KeyValueCompare) template - iterator upper_bound(const KeyType& key, KeyValueCompare comp) - { return tree_.upper_bound(key, comp); } + iterator upper_bound(const KeyType& key, KeyValueCompare comp); - //! Effects: Returns an iterator to the first element whose - //! key is greater than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - const_iterator upper_bound(const_reference value) const - { return tree_.upper_bound(value); } + //! @copydoc ::boost::intrusive::avltree::upper_bound(const_reference)const + const_iterator upper_bound(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Returns a const_iterator to the first element whose - //! key according to the comparison functor is greater than key or - //! end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::avltree::upper_bound(const KeyType&,KeyValueCompare)const template - const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const - { return tree_.upper_bound(key, comp); } + const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Finds an iterator to the first element whose value is - //! "value" or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - iterator find(const_reference value) - { return tree_.find(value); } + //! @copydoc ::boost::intrusive::avltree::find(const_reference) + iterator find(const_reference value); - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Finds an iterator to the first element whose key is - //! "key" according to the comparison functor or end() if that element - //! does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::avltree::find(const KeyType&,KeyValueCompare) template - iterator find(const KeyType& key, KeyValueCompare comp) - { return tree_.find(key, comp); } + iterator find(const KeyType& key, KeyValueCompare comp); - //! Effects: Finds a const_iterator to the first element whose value is - //! "value" or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - const_iterator find(const_reference value) const - { return tree_.find(value); } + //! @copydoc ::boost::intrusive::avltree::find(const_reference)const + const_iterator find(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Finds a const_iterator to the first element whose key is - //! "key" according to the comparison functor or end() if that element - //! does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::avltree::find(const KeyType&,KeyValueCompare)const template - const_iterator find(const KeyType& key, KeyValueCompare comp) const - { return tree_.find(key, comp); } + const_iterator find(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - std::pair equal_range(const_reference value) - { return tree_.equal_range(value); } + //! @copydoc ::boost::intrusive::avltree::equal_range(const_reference) + std::pair equal_range(const_reference value); - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Finds a range containing all elements whose key is k - //! according to the comparison functor or an empty range - //! that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::avltree::equal_range(const KeyType&,KeyValueCompare) template - std::pair equal_range(const KeyType& key, KeyValueCompare comp) - { return tree_.equal_range(key, comp); } + std::pair equal_range(const KeyType& key, KeyValueCompare comp); - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. + //! @copydoc ::boost::intrusive::avltree::equal_range(const_reference)const std::pair - equal_range(const_reference value) const - { return tree_.equal_range(value); } + equal_range(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Finds a range containing all elements whose key is k - //! according to the comparison functor or an empty range - //! that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::avltree::equal_range(const KeyType&,KeyValueCompare)const template std::pair - equal_range(const KeyType& key, KeyValueCompare comp) const - { return tree_.equal_range(key, comp); } + equal_range(const KeyType& key, KeyValueCompare comp) const; - //! Requires: 'lower_value' must not be greater than 'upper_value'. If - //! 'lower_value' == 'upper_value', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise - //! - //! second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the predicate throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_value and upper_value. + //! @copydoc ::boost::intrusive::avltree::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) - { return tree_.bounded_range(lower_value, upper_value, left_closed, right_closed); } + (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); - //! Requires: KeyValueCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. - //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If - //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key, comp) if left_closed, upper_bound(lower_key, comp) otherwise - //! - //! second = upper_bound(upper_key, comp) if right_closed, lower_bound(upper_key, comp) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_key and upper_key. + //! @copydoc ::boost::intrusive::avltree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool) template std::pair bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) - { return tree_.bounded_range(lower_key, upper_key, comp, left_closed, right_closed); } + (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed); - //! Requires: 'lower_value' must not be greater than 'upper_value'. If - //! 'lower_value' == 'upper_value', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise - //! - //! second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the predicate throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_value and upper_value. + //! @copydoc ::boost::intrusive::avltree::bounded_range(const_reference,const_reference,bool,bool)const std::pair - bounded_range(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const - { return tree_.bounded_range(lower_value, upper_value, left_closed, right_closed); } + bounded_range(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; - //! Requires: KeyValueCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. - //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If - //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key, comp) if left_closed, upper_bound(lower_key, comp) otherwise - //! - //! second = upper_bound(upper_key, comp) if right_closed, lower_bound(upper_key, comp) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_key and upper_key. + //! @copydoc ::boost::intrusive::avltree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const template - std::pair - bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const - { return tree_.bounded_range(lower_key, upper_key, comp, left_closed, right_closed); } + std::pair bounded_range + (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; - //! Requires: value must be an lvalue and shall be in a avl_set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid iterator i belonging to the avl_set - //! that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This static function is available only if the value traits - //! is stateless. - static iterator s_iterator_to(reference value) - { return tree_type::s_iterator_to(value); } + //! @copydoc ::boost::intrusive::avltree::s_iterator_to(reference) + static iterator s_iterator_to(reference value); - //! Requires: value must be an lvalue and shall be in a avl_set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid const_iterator i belonging to the - //! avl_set that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This static function is available only if the value traits - //! is stateless. - static const_iterator s_iterator_to(const_reference value) - { return tree_type::s_iterator_to(value); } + //! @copydoc ::boost::intrusive::avltree::s_iterator_to(const_reference) + static const_iterator s_iterator_to(const_reference value); - //! Requires: value must be an lvalue and shall be in a avl_set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid iterator i belonging to the avl_set - //! that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator iterator_to(reference value) - { return tree_.iterator_to(value); } + //! @copydoc ::boost::intrusive::avltree::iterator_to(reference) + iterator iterator_to(reference value); - //! Requires: value must be an lvalue and shall be in a avl_set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid const_iterator i belonging to the - //! avl_set that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator iterator_to(const_reference value) const - { return tree_.iterator_to(value); } + //! @copydoc ::boost::intrusive::avltree::iterator_to(const_reference)const + const_iterator iterator_to(const_reference value) const; - //! Requires: value shall not be in a avl_set/avl_multiset. - //! - //! Effects: init_node puts the hook of a value in a well-known default - //! state. - //! - //! Throws: Nothing. - //! - //! Complexity: Constant time. - //! - //! Note: This function puts the hook in the well-known default state - //! used by auto_unlink and safe hooks. - static void init_node(reference value) - { tree_type::init_node(value); } + //! @copydoc ::boost::intrusive::avltree::init_node(reference) + static void init_node(reference value); - //! Effects: Unlinks the leftmost node from the tree. - //! - //! Complexity: Average complexity is constant time. - //! - //! Throws: Nothing. - //! - //! Notes: This function breaks the tree and the tree can - //! only be used for more unlink_leftmost_without_rebalance calls. - //! This function is normally used to achieve a step by step - //! controlled destruction of the tree. - pointer unlink_leftmost_without_rebalance() - { return tree_.unlink_leftmost_without_rebalance(); } + //! @copydoc ::boost::intrusive::avltree::unlink_leftmost_without_rebalance + pointer unlink_leftmost_without_rebalance(); - //! Requires: replace_this must be a valid iterator of *this - //! and with_this must not be inserted in any tree. - //! - //! Effects: Replaces replace_this in its position in the - //! tree with with_this. The tree does not need to be rebalanced. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This function will break container ordering invariants if - //! with_this is not equivalent to *replace_this according to the - //! ordering rules. This function is faster than erasing and inserting - //! the node, since no rebalancing or comparison is needed. - void replace_node(iterator replace_this, reference with_this) - { tree_.replace_node(replace_this, with_this); } + //! @copydoc ::boost::intrusive::avltree::replace_node + void replace_node(iterator replace_this, reference with_this); - /// @cond - friend bool operator==(const avl_set_impl &x, const avl_set_impl &y) - { return x.tree_ == y.tree_; } - - friend bool operator<(const avl_set_impl &x, const avl_set_impl &y) - { return x.tree_ < y.tree_; } - /// @endcond + //! @copydoc ::boost::intrusive::avltree::remove_node + void remove_node(reference value); + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED }; #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator!= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const avl_set_impl &x, const avl_set_impl &y) -#else -(const avl_set_impl &x, const avl_set_impl &y) -#endif -{ return !(x == y); } -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator> -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const avl_set_impl &x, const avl_set_impl &y) -#else -(const avl_set_impl &x, const avl_set_impl &y) -#endif -{ return y < x; } +bool operator!= (const avl_set_impl &x, const avl_set_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator<= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const avl_set_impl &x, const avl_set_impl &y) -#else -(const avl_set_impl &x, const avl_set_impl &y) -#endif -{ return !(y < x); } +bool operator>(const avl_set_impl &x, const avl_set_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator>= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const avl_set_impl &x, const avl_set_impl &y) -#else -(const avl_set_impl &x, const avl_set_impl &y) -#endif -{ return !(x < y); } +bool operator<=(const avl_set_impl &x, const avl_set_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline void swap -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(avl_set_impl &x, avl_set_impl &y) -#else -(avl_set_impl &x, avl_set_impl &y) -#endif -{ x.swap(y); } +bool operator>=(const avl_set_impl &x, const avl_set_impl &y); -//! Helper metafunction to define a \c avl_set that yields to the same type when the +template +void swap(avl_set_impl &x, avl_set_impl &y); + +#endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + +//! Helper metafunction to define a \c set that yields to the same type when the //! same options (either explicitly or implicitly) are used. #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else -template +template #endif struct make_avl_set { /// @cond - typedef avl_set_impl - < typename make_avltree_opt + typedef typename pack_options + < avltree_defaults, #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - + O1, O2, O3, O4 #else - + Options... #endif - ::type - > implementation_defined; + >::type packed_options; + + typedef typename detail::get_value_traits + ::type value_traits; + + typedef avl_set_impl + < value_traits + , typename packed_options::compare + , typename packed_options::size_type + , packed_options::constant_time_size + > implementation_defined; /// @endcond typedef implementation_defined type; }; #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED - #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else template #endif class avl_set - : public make_avl_set - #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - - #else - - #endif - ::type + : public make_avl_set::type { typedef typename make_avl_set + + O1, O2, O3, O4 #else - + Options... #endif - ::type Base; + >::type Base; BOOST_MOVABLE_BUT_NOT_COPYABLE(avl_set) public: @@ -1301,7 +461,7 @@ class avl_set {} avl_set& operator=(BOOST_RV_REF(avl_set) x) - { this->Base::operator=(::boost::move(static_cast(x))); return *this; } + { return static_cast(this->Base::operator=(::boost::move(static_cast(x)))); } static avl_set &container_from_end_iterator(iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } @@ -1309,17 +469,17 @@ class avl_set static const avl_set &container_from_end_iterator(const_iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } - static avl_set &container_from_iterator(iterator end_iterator) - { return static_cast(Base::container_from_iterator(end_iterator)); } + static avl_set &container_from_iterator(iterator it) + { return static_cast(Base::container_from_iterator(it)); } - static const avl_set &container_from_iterator(const_iterator end_iterator) - { return static_cast(Base::container_from_iterator(end_iterator)); } + static const avl_set &container_from_iterator(const_iterator it) + { return static_cast(Base::container_from_iterator(it)); } }; #endif //! The class template avl_multiset is an intrusive container, that mimics most of -//! the interface of std::avl_multiset as described in the C++ standard. +//! the interface of std::_multiset as described in the C++ standard. //! //! The template parameter \c T is the type to be managed by the container. //! The user can specify additional options and if no options are provided @@ -1332,14 +492,16 @@ class avl_set #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class avl_multiset_impl +#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + : public bstree_impl +#endif { /// @cond - typedef avltree_impl tree_type; + typedef bstree_impl tree_type; - //Movable BOOST_MOVABLE_BUT_NOT_COPYABLE(avl_multiset_impl) typedef tree_type implementation_defined; /// @endcond @@ -1366,1088 +528,321 @@ class avl_multiset_impl typedef typename implementation_defined::const_node_ptr const_node_ptr; typedef typename implementation_defined::node_algorithms node_algorithms; - static const bool constant_time_size = Config::constant_time_size; - - /// @cond - private: - tree_type tree_; - /// @endcond + static const bool constant_time_size = tree_type::constant_time_size; public: - //! Effects: Constructs an empty avl_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: If value_traits::node_traits::node - //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) - //! or the copy constructor/operator() of the value_compare object throws. + //! @copydoc ::boost::intrusive::avltree::avltree(const value_compare &,const value_traits &) explicit avl_multiset_impl( const value_compare &cmp = value_compare() - , const value_traits &v_traits = value_traits()) - : tree_(cmp, v_traits) + , const value_traits &v_traits = value_traits()) + : tree_type(cmp, v_traits) {} - //! Requires: Dereferencing iterator must yield an lvalue of type value_type. - //! cmp must be a comparison function that induces a strict weak ordering. - //! - //! Effects: Constructs an empty avl_multiset and inserts elements from - //! [b, e). - //! - //! Complexity: Linear in N if [b, e) is already sorted using - //! comp and otherwise N * log N, where N is the distance between first and last - //! - //! Throws: If value_traits::node_traits::node - //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) - //! or the copy constructor/operator() of the value_compare object throws. + //! @copydoc ::boost::intrusive::avltree::avltree(bool,Iterator,Iterator,const value_compare &,const value_traits &) template avl_multiset_impl( Iterator b, Iterator e , const value_compare &cmp = value_compare() , const value_traits &v_traits = value_traits()) - : tree_(false, b, e, cmp, v_traits) + : tree_type(false, b, e, cmp, v_traits) {} - //! Effects: to-do - //! + //! @copydoc ::boost::intrusive::avltree::avltree(avltree &&) avl_multiset_impl(BOOST_RV_REF(avl_multiset_impl) x) - : tree_(::boost::move(x.tree_)) + : tree_type(::boost::move(static_cast(x))) {} - //! Effects: to-do - //! + //! @copydoc ::boost::intrusive::avltree::operator=(avltree &&) avl_multiset_impl& operator=(BOOST_RV_REF(avl_multiset_impl) x) - { tree_ = ::boost::move(x.tree_); return *this; } + { return static_cast(tree_type::operator=(::boost::move(static_cast(x)))); } - //! Effects: Detaches all elements from this. The objects in the avl_multiset - //! are not deleted (i.e. no destructors are called). - //! - //! Complexity: Linear to the number of elements on the container. - //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. - //! - //! Throws: Nothing. - ~avl_multiset_impl() - {} + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::avltree::~avltree() + ~avl_multiset_impl(); - //! Effects: Returns an iterator pointing to the beginning of the avl_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator begin() - { return tree_.begin(); } + //! @copydoc ::boost::intrusive::avltree::begin() + iterator begin(); - //! Effects: Returns a const_iterator pointing to the beginning of the avl_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator begin() const - { return tree_.begin(); } + //! @copydoc ::boost::intrusive::avltree::begin()const + const_iterator begin() const; - //! Effects: Returns a const_iterator pointing to the beginning of the avl_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator cbegin() const - { return tree_.cbegin(); } + //! @copydoc ::boost::intrusive::avltree::cbegin()const + const_iterator cbegin() const; - //! Effects: Returns an iterator pointing to the end of the avl_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator end() - { return tree_.end(); } + //! @copydoc ::boost::intrusive::avltree::end() + iterator end(); - //! Effects: Returns a const_iterator pointing to the end of the avl_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator end() const - { return tree_.end(); } + //! @copydoc ::boost::intrusive::avltree::end()const + const_iterator end() const; - //! Effects: Returns a const_iterator pointing to the end of the avl_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator cend() const - { return tree_.cend(); } + //! @copydoc ::boost::intrusive::avltree::cend()const + const_iterator cend() const; - //! Effects: Returns a reverse_iterator pointing to the beginning of the - //! reversed avl_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - reverse_iterator rbegin() - { return tree_.rbegin(); } + //! @copydoc ::boost::intrusive::avltree::rbegin() + reverse_iterator rbegin(); - //! Effects: Returns a const_reverse_iterator pointing to the beginning - //! of the reversed avl_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator rbegin() const - { return tree_.rbegin(); } + //! @copydoc ::boost::intrusive::avltree::rbegin()const + const_reverse_iterator rbegin() const; - //! Effects: Returns a const_reverse_iterator pointing to the beginning - //! of the reversed avl_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator crbegin() const - { return tree_.crbegin(); } + //! @copydoc ::boost::intrusive::avltree::crbegin()const + const_reverse_iterator crbegin() const; - //! Effects: Returns a reverse_iterator pointing to the end - //! of the reversed avl_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - reverse_iterator rend() - { return tree_.rend(); } + //! @copydoc ::boost::intrusive::avltree::rend() + reverse_iterator rend(); - //! Effects: Returns a const_reverse_iterator pointing to the end - //! of the reversed avl_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator rend() const - { return tree_.rend(); } + //! @copydoc ::boost::intrusive::avltree::rend()const + const_reverse_iterator rend() const; - //! Effects: Returns a const_reverse_iterator pointing to the end - //! of the reversed avl_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator crend() const - { return tree_.crend(); } + //! @copydoc ::boost::intrusive::avltree::crend()const + const_reverse_iterator crend() const; - //! Precondition: end_iterator must be a valid end iterator - //! of avl_multiset. - //! - //! Effects: Returns a const reference to the avl_multiset associated to the end iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - static avl_multiset_impl &container_from_end_iterator(iterator end_iterator) - { - return *detail::parent_from_member - ( &tree_type::container_from_end_iterator(end_iterator) - , &avl_multiset_impl::tree_); - } + //! @copydoc ::boost::intrusive::avltree::container_from_end_iterator(iterator) + static avl_multiset_impl &container_from_end_iterator(iterator end_iterator); - //! Precondition: end_iterator must be a valid end const_iterator - //! of avl_multiset. - //! - //! Effects: Returns a const reference to the avl_multiset associated to the end iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - static const avl_multiset_impl &container_from_end_iterator(const_iterator end_iterator) - { - return *detail::parent_from_member - ( &tree_type::container_from_end_iterator(end_iterator) - , &avl_multiset_impl::tree_); - } + //! @copydoc ::boost::intrusive::avltree::container_from_end_iterator(const_iterator) + static const avl_multiset_impl &container_from_end_iterator(const_iterator end_iterator); - //! Precondition: it must be a valid iterator of multiset. - //! - //! Effects: Returns a const reference to the multiset associated to the iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Logarithmic. - static avl_multiset_impl &container_from_iterator(iterator it) - { - return *detail::parent_from_member - ( &tree_type::container_from_iterator(it) - , &avl_multiset_impl::tree_); - } + //! @copydoc ::boost::intrusive::avltree::container_from_iterator(iterator) + static avl_multiset_impl &container_from_iterator(iterator it); - //! Precondition: it must be a valid const_iterator of multiset. - //! - //! Effects: Returns a const reference to the multiset associated to the iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Logarithmic. - static const avl_multiset_impl &container_from_iterator(const_iterator it) - { - return *detail::parent_from_member - ( &tree_type::container_from_iterator(it) - , &avl_multiset_impl::tree_); - } + //! @copydoc ::boost::intrusive::avltree::container_from_iterator(const_iterator) + static const avl_multiset_impl &container_from_iterator(const_iterator it); - //! Effects: Returns the key_compare object used by the avl_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: If key_compare copy-constructor throws. - key_compare key_comp() const - { return tree_.value_comp(); } + //! @copydoc ::boost::intrusive::avltree::key_comp()const + key_compare key_comp() const; - //! Effects: Returns the value_compare object used by the avl_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: If value_compare copy-constructor throws. - value_compare value_comp() const - { return tree_.value_comp(); } + //! @copydoc ::boost::intrusive::avltree::value_comp()const + value_compare value_comp() const; - //! Effects: Returns true is the container is empty. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - bool empty() const - { return tree_.empty(); } + //! @copydoc ::boost::intrusive::avltree::empty()const + bool empty() const; - //! Effects: Returns the number of elements stored in the avl_multiset. - //! - //! Complexity: Linear to elements contained in *this if, - //! constant-time size option is enabled. Constant-time otherwise. - //! - //! Throws: Nothing. - size_type size() const - { return tree_.size(); } + //! @copydoc ::boost::intrusive::avltree::size()const + size_type size() const; - //! Effects: Swaps the contents of two avl_multisets. - //! - //! Complexity: Constant. - //! - //! Throws: If the swap() call for the comparison functor - //! found using ADL throws. Strong guarantee. - void swap(avl_multiset_impl& other) - { tree_.swap(other.tree_); } + //! @copydoc ::boost::intrusive::avltree::swap + void swap(avl_multiset_impl& other); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! Cloner should yield to nodes equivalent to the original nodes. - //! - //! Effects: Erases all the elements from *this - //! calling Disposer::operator()(pointer), clones all the - //! elements from src calling Cloner::operator()(const_reference ) - //! and inserts them on *this. Copies the predicate from the source container. - //! - //! If cloner throws, all cloned elements are unlinked and disposed - //! calling Disposer::operator()(pointer). - //! - //! Complexity: Linear to erased plus inserted elements. - //! - //! Throws: If cloner throws or predicate copy assignment throws. Basic guarantee. + //! @copydoc ::boost::intrusive::avltree::clone_from template - void clone_from(const avl_multiset_impl &src, Cloner cloner, Disposer disposer) - { tree_.clone_from(src.tree_, cloner, disposer); } + void clone_from(const avl_multiset_impl &src, Cloner cloner, Disposer disposer); + + #endif //#ifdef BOOST_iNTRUSIVE_DOXYGEN_INVOKED - //! Requires: value must be an lvalue - //! - //! Effects: Inserts value into the avl_multiset. - //! - //! Returns: An iterator that points to the position where the new - //! element was inserted. - //! - //! Complexity: Average complexity for insert element is at - //! most logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. Strong guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + //! @copydoc ::boost::intrusive::avltree::insert_equal(reference) iterator insert(reference value) - { return tree_.insert_equal(value); } + { return tree_type::insert_equal(value); } - //! Requires: value must be an lvalue - //! - //! Effects: Inserts x into the avl_multiset, using pos as a hint to - //! where it will be inserted. - //! - //! Returns: An iterator that points to the position where the new - //! element was inserted. - //! - //! Complexity: Logarithmic in general, but it is amortized - //! constant time if t is inserted immediately before hint. - //! - //! Throws: If the internal value_compare ordering function throws. Strong guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + //! @copydoc ::boost::intrusive::avltree::insert_equal(const_iterator,reference) iterator insert(const_iterator hint, reference value) - { return tree_.insert_equal(hint, value); } + { return tree_type::insert_equal(hint, value); } - //! Requires: Dereferencing iterator must yield an lvalue - //! of type value_type. - //! - //! Effects: Inserts a range into the avl_multiset. - //! - //! Returns: An iterator that points to the position where the new - //! element was inserted. - //! - //! Complexity: Insert range is in general O(N * log(N)), where N is the - //! size of the range. However, it is linear in N if the range is already sorted - //! by value_comp(). - //! - //! Throws: If the internal value_compare ordering function throws. Basic guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + //! @copydoc ::boost::intrusive::avltree::insert_equal(Iterator,Iterator) template void insert(Iterator b, Iterator e) - { tree_.insert_equal(b, e); } + { tree_type::insert_equal(b, e); } - //! Requires: value must be an lvalue, "pos" must be - //! a valid iterator (or end) and must be the succesor of value - //! once inserted according to the predicate. "value" must not be equal to any - //! inserted key according to the predicate. - //! - //! Effects: Inserts x into the tree before "pos". - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Note: This function does not check preconditions so if "pos" is not - //! the successor of "value" or "value" is not unique tree ordering and uniqueness - //! invariants will be broken respectively. - //! This is a low-level function to be used only for performance reasons - //! by advanced users. - iterator insert_before(const_iterator pos, reference value) - { return tree_.insert_before(pos, value); } + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::avltree::insert_before + iterator insert_before(const_iterator pos, reference value); - //! Requires: value must be an lvalue, and it must be greater than - //! any inserted key according to the predicate. - //! - //! Effects: Inserts x into the tree in the last position. - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Note: This function does not check preconditions so if value is - //! less than or equal to the greatest inserted key tree ordering invariant will be broken. - //! This function is slightly more efficient than using "insert_before". - //! This is a low-level function to be used only for performance reasons - //! by advanced users. - void push_back(reference value) - { tree_.push_back(value); } + //! @copydoc ::boost::intrusive::avltree::push_back + void push_back(reference value); - //! Requires: value must be an lvalue, and it must be less - //! than any inserted key according to the predicate. - //! - //! Effects: Inserts x into the tree in the first position. - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Note: This function does not check preconditions so if value is - //! greater than or equal to the the mimum inserted key tree ordering or uniqueness - //! invariants will be broken. - //! This function is slightly more efficient than using "insert_before". - //! This is a low-level function to be used only for performance reasons - //! by advanced users. - void push_front(reference value) - { tree_.push_front(value); } + //! @copydoc ::boost::intrusive::avltree::push_front + void push_front(reference value); - //! Effects: Erases the element pointed to by pos. - //! - //! Complexity: Average complexity is constant time. - //! - //! Returns: An iterator to the element after the erased element. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - iterator erase(const_iterator i) - { return tree_.erase(i); } + //! @copydoc ::boost::intrusive::avltree::erase(const_iterator) + iterator erase(const_iterator i); - //! Effects: Erases the range pointed to by b end e. - //! - //! Returns: An iterator to the element after the erased elements. - //! - //! Complexity: Average complexity for erase range is at most - //! O(log(size() + N)), where N is the number of elements in the range. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - iterator erase(const_iterator b, const_iterator e) - { return tree_.erase(b, e); } + //! @copydoc ::boost::intrusive::avltree::erase(const_iterator,const_iterator) + iterator erase(const_iterator b, const_iterator e); - //! Effects: Erases all the elements with the given value. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: O(log(size() + this->count(value)). - //! - //! Throws: If the internal value_compare ordering function throws. Basic guarantee. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - size_type erase(const_reference value) - { return tree_.erase(value); } + //! @copydoc ::boost::intrusive::avltree::erase(const_reference) + size_type erase(const_reference value); - //! Effects: Erases all the elements that compare equal with - //! the given key and the given comparison functor. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: O(log(size() + this->count(key, comp)). - //! - //! Throws: If comp ordering function throws. Basic guarantee. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. + //! @copydoc ::boost::intrusive::avltree::erase(const KeyType&,KeyValueCompare) template - size_type erase(const KeyType& key, KeyValueCompare comp - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) - { return tree_.erase(key, comp); } + size_type erase(const KeyType& key, KeyValueCompare comp); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Returns: An iterator to the element after the erased element. - //! - //! Effects: Erases the element pointed to by pos. - //! Disposer::operator()(pointer) is called for the removed element. - //! - //! Complexity: Average complexity for erase element is constant time. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::avltree::erase_and_dispose(const_iterator,Disposer) template - iterator erase_and_dispose(const_iterator i, Disposer disposer) - { return tree_.erase_and_dispose(i, disposer); } + iterator erase_and_dispose(const_iterator i, Disposer disposer); - #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + //! @copydoc ::boost::intrusive::avltree::erase_and_dispose(const_iterator,const_iterator,Disposer) template - iterator erase_and_dispose(iterator i, Disposer disposer) - { return this->erase_and_dispose(const_iterator(i), disposer); } - #endif + iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Returns: An iterator to the element after the erased elements. - //! - //! Effects: Erases the range pointed to by b end e. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Complexity: Average complexity for erase range is at most - //! O(log(size() + N)), where N is the number of elements in the range. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::avltree::erase_and_dispose(const_reference, Disposer) template - iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer) - { return tree_.erase_and_dispose(b, e, disposer); } + size_type erase_and_dispose(const_reference value, Disposer disposer); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements with the given value. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: O(log(size() + this->count(value)). - //! - //! Throws: If the internal value_compare ordering function throws. Basic guarantee. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - template - size_type erase_and_dispose(const_reference value, Disposer disposer) - { return tree_.erase_and_dispose(value, disposer); } - - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements with the given key. - //! according to the comparison functor "comp". - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: O(log(size() + this->count(key, comp)). - //! - //! Throws: If comp ordering function throws. Basic guarantee. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::avltree::erase_and_dispose(const KeyType&,KeyValueCompare,Disposer) template - size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) - { return tree_.erase_and_dispose(key, comp, disposer); } + size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer); - //! Effects: Erases all the elements of the container. - //! - //! Complexity: Linear to the number of elements on the container. - //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - void clear() - { return tree_.clear(); } + //! @copydoc ::boost::intrusive::avltree::clear + void clear(); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements of the container. - //! - //! Complexity: Linear to the number of elements on the container. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. + //! @copydoc ::boost::intrusive::avltree::clear_and_dispose template - void clear_and_dispose(Disposer disposer) - { return tree_.clear_and_dispose(disposer); } + void clear_and_dispose(Disposer disposer); - //! Effects: Returns the number of contained elements with the given key - //! - //! Complexity: Logarithmic to the number of elements contained plus lineal - //! to number of objects with the given key. - //! - //! Throws: If the internal value_compare ordering function throws. - size_type count(const_reference value) const - { return tree_.count(value); } + //! @copydoc ::boost::intrusive::avltree::count(const_reference)const + size_type count(const_reference value) const; - //! Effects: Returns the number of contained elements with the same key - //! compared with the given comparison functor. - //! - //! Complexity: Logarithmic to the number of elements contained plus lineal - //! to number of objects with the given key. - //! - //! Throws: If comp ordering function throws. + //! @copydoc ::boost::intrusive::avltree::count(const KeyType&,KeyValueCompare)const template - size_type count(const KeyType& key, KeyValueCompare comp) const - { return tree_.count(key, comp); } - - //! Effects: Returns an iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - iterator lower_bound(const_reference value) - { return tree_.lower_bound(value); } - - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Returns an iterator to the first element whose - //! key according to the comparison functor is not less than k or - //! end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + size_type count(const KeyType& key, KeyValueCompare comp) const; + + //! @copydoc ::boost::intrusive::avltree::lower_bound(const_reference) + iterator lower_bound(const_reference value); + + //! @copydoc ::boost::intrusive::avltree::lower_bound(const KeyType&,KeyValueCompare) template - iterator lower_bound(const KeyType& key, KeyValueCompare comp) - { return tree_.lower_bound(key, comp); } + iterator lower_bound(const KeyType& key, KeyValueCompare comp); - //! Effects: Returns a const iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - const_iterator lower_bound(const_reference value) const - { return tree_.lower_bound(value); } + //! @copydoc ::boost::intrusive::avltree::lower_bound(const_reference)const + const_iterator lower_bound(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Returns a const_iterator to the first element whose - //! key according to the comparison functor is not less than k or - //! end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::avltree::lower_bound(const KeyType&,KeyValueCompare)const template - const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const - { return tree_.lower_bound(key, comp); } + const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Returns an iterator to the first element whose - //! key is greater than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - iterator upper_bound(const_reference value) - { return tree_.upper_bound(value); } + //! @copydoc ::boost::intrusive::avltree::upper_bound(const_reference) + iterator upper_bound(const_reference value); - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Returns an iterator to the first element whose - //! key according to the comparison functor is greater than key or - //! end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::avltree::upper_bound(const KeyType&,KeyValueCompare) template - iterator upper_bound(const KeyType& key, KeyValueCompare comp) - { return tree_.upper_bound(key, comp); } + iterator upper_bound(const KeyType& key, KeyValueCompare comp); - //! Effects: Returns an iterator to the first element whose - //! key is greater than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - const_iterator upper_bound(const_reference value) const - { return tree_.upper_bound(value); } + //! @copydoc ::boost::intrusive::avltree::upper_bound(const_reference)const + const_iterator upper_bound(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Returns a const_iterator to the first element whose - //! key according to the comparison functor is greater than key or - //! end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::avltree::upper_bound(const KeyType&,KeyValueCompare)const template - const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const - { return tree_.upper_bound(key, comp); } + const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Finds an iterator to the first element whose value is - //! "value" or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - iterator find(const_reference value) - { return tree_.find(value); } + //! @copydoc ::boost::intrusive::avltree::find(const_reference) + iterator find(const_reference value); - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Finds an iterator to the first element whose key is - //! "key" according to the comparison functor or end() if that element - //! does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::avltree::find(const KeyType&,KeyValueCompare) template - iterator find(const KeyType& key, KeyValueCompare comp) - { return tree_.find(key, comp); } + iterator find(const KeyType& key, KeyValueCompare comp); - //! Effects: Finds a const_iterator to the first element whose value is - //! "value" or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - const_iterator find(const_reference value) const - { return tree_.find(value); } + //! @copydoc ::boost::intrusive::avltree::find(const_reference)const + const_iterator find(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Finds a const_iterator to the first element whose key is - //! "key" according to the comparison functor or end() if that element - //! does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::avltree::find(const KeyType&,KeyValueCompare)const template - const_iterator find(const KeyType& key, KeyValueCompare comp) const - { return tree_.find(key, comp); } + const_iterator find(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - std::pair equal_range(const_reference value) - { return tree_.equal_range(value); } + //! @copydoc ::boost::intrusive::avltree::equal_range(const_reference) + std::pair equal_range(const_reference value); - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Finds a range containing all elements whose key is k - //! according to the comparison functor or an empty range - //! that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::avltree::equal_range(const KeyType&,KeyValueCompare) template - std::pair equal_range(const KeyType& key, KeyValueCompare comp) - { return tree_.equal_range(key, comp); } + std::pair equal_range(const KeyType& key, KeyValueCompare comp); - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. + //! @copydoc ::boost::intrusive::avltree::equal_range(const_reference)const std::pair - equal_range(const_reference value) const - { return tree_.equal_range(value); } + equal_range(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Finds a range containing all elements whose key is k - //! according to the comparison functor or an empty range - //! that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::avltree::equal_range(const KeyType&,KeyValueCompare)const template std::pair - equal_range(const KeyType& key, KeyValueCompare comp) const - { return tree_.equal_range(key, comp); } + equal_range(const KeyType& key, KeyValueCompare comp) const; - //! Requires: 'lower_value' must not be greater than 'upper_value'. If - //! 'lower_value' == 'upper_value', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise - //! - //! second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the predicate throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_value and upper_value. + //! @copydoc ::boost::intrusive::avltree::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) - { return tree_.bounded_range(lower_value, upper_value, left_closed, right_closed); } + (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); - //! Requires: KeyValueCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. - //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If - //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key, comp) if left_closed, upper_bound(lower_key, comp) otherwise - //! - //! second = upper_bound(upper_key, comp) if right_closed, lower_bound(upper_key, comp) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_key and upper_key. + //! @copydoc ::boost::intrusive::avltree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool) template std::pair bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) - { return tree_.bounded_range(lower_key, upper_key, comp, left_closed, right_closed); } + (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed); - //! Requires: 'lower_value' must not be greater than 'upper_value'. If - //! 'lower_value' == 'upper_value', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise - //! - //! second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the predicate throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_value and upper_value. + //! @copydoc ::boost::intrusive::avltree::bounded_range(const_reference,const_reference,bool,bool)const std::pair - bounded_range(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const - { return tree_.bounded_range(lower_value, upper_value, left_closed, right_closed); } + bounded_range(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; - //! Requires: KeyValueCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. - //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If - //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key, comp) if left_closed, upper_bound(lower_key, comp) otherwise - //! - //! second = upper_bound(upper_key, comp) if right_closed, lower_bound(upper_key, comp) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_key and upper_key. + //! @copydoc ::boost::intrusive::avltree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const template - std::pair - bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const - { return tree_.bounded_range(lower_key, upper_key, comp, left_closed, right_closed); } + std::pair bounded_range + (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; - //! Requires: value must be an lvalue and shall be in a avl_multiset of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid iterator i belonging to the avl_multiset - //! that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This static function is available only if the value traits - //! is stateless. - static iterator s_iterator_to(reference value) - { return tree_type::s_iterator_to(value); } + //! @copydoc ::boost::intrusive::avltree::s_iterator_to(reference) + static iterator s_iterator_to(reference value); - //! Requires: value must be an lvalue and shall be in a avl_multiset of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid const_iterator i belonging to the - //! avl_multiset that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This static function is available only if the value traits - //! is stateless. - static const_iterator s_iterator_to(const_reference value) - { return tree_type::s_iterator_to(value); } + //! @copydoc ::boost::intrusive::avltree::s_iterator_to(const_reference) + static const_iterator s_iterator_to(const_reference value); - //! Requires: value must be an lvalue and shall be in a avl_multiset of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid iterator i belonging to the avl_multiset - //! that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator iterator_to(reference value) - { return tree_.iterator_to(value); } + //! @copydoc ::boost::intrusive::avltree::iterator_to(reference) + iterator iterator_to(reference value); - //! Requires: value must be an lvalue and shall be in a avl_multiset of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid const_iterator i belonging to the - //! avl_multiset that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator iterator_to(const_reference value) const - { return tree_.iterator_to(value); } + //! @copydoc ::boost::intrusive::avltree::iterator_to(const_reference)const + const_iterator iterator_to(const_reference value) const; - //! Requires: value shall not be in a avl_multiset/avl_multiset. - //! - //! Effects: init_node puts the hook of a value in a well-known default - //! state. - //! - //! Throws: Nothing. - //! - //! Complexity: Constant time. - //! - //! Note: This function puts the hook in the well-known default state - //! used by auto_unlink and safe hooks. - static void init_node(reference value) - { tree_type::init_node(value); } + //! @copydoc ::boost::intrusive::avltree::init_node(reference) + static void init_node(reference value); - //! Effects: Unlinks the leftmost node from the tree. - //! - //! Complexity: Average complexity is constant time. - //! - //! Throws: Nothing. - //! - //! Notes: This function breaks the tree and the tree can - //! only be used for more unlink_leftmost_without_rebalance calls. - //! This function is normally used to achieve a step by step - //! controlled destruction of the tree. - pointer unlink_leftmost_without_rebalance() - { return tree_.unlink_leftmost_without_rebalance(); } + //! @copydoc ::boost::intrusive::avltree::unlink_leftmost_without_rebalance + pointer unlink_leftmost_without_rebalance(); - //! Requires: replace_this must be a valid iterator of *this - //! and with_this must not be inserted in any tree. - //! - //! Effects: Replaces replace_this in its position in the - //! tree with with_this. The tree does not need to be rebalanced. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This function will break container ordering invariants if - //! with_this is not equivalent to *replace_this according to the - //! ordering rules. This function is faster than erasing and inserting - //! the node, since no rebalancing or comparison is needed. - void replace_node(iterator replace_this, reference with_this) - { tree_.replace_node(replace_this, with_this); } + //! @copydoc ::boost::intrusive::avltree::replace_node + void replace_node(iterator replace_this, reference with_this); - /// @cond - friend bool operator==(const avl_multiset_impl &x, const avl_multiset_impl &y) - { return x.tree_ == y.tree_; } - - friend bool operator<(const avl_multiset_impl &x, const avl_multiset_impl &y) - { return x.tree_ < y.tree_; } - /// @endcond + //! @copydoc ::boost::intrusive::avltree::remove_node + void remove_node(reference value); + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED }; #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator!= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const avl_multiset_impl &x, const avl_multiset_impl &y) -#else -(const avl_multiset_impl &x, const avl_multiset_impl &y) -#endif -{ return !(x == y); } -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator> -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const avl_multiset_impl &x, const avl_multiset_impl &y) -#else -(const avl_multiset_impl &x, const avl_multiset_impl &y) -#endif -{ return y < x; } +bool operator!= (const avl_multiset_impl &x, const avl_multiset_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator<= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const avl_multiset_impl &x, const avl_multiset_impl &y) -#else -(const avl_multiset_impl &x, const avl_multiset_impl &y) -#endif -{ return !(y < x); } +bool operator>(const avl_multiset_impl &x, const avl_multiset_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator>= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const avl_multiset_impl &x, const avl_multiset_impl &y) -#else -(const avl_multiset_impl &x, const avl_multiset_impl &y) -#endif -{ return !(x < y); } +bool operator<=(const avl_multiset_impl &x, const avl_multiset_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline void swap -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(avl_multiset_impl &x, avl_multiset_impl &y) -#else -(avl_multiset_impl &x, avl_multiset_impl &y) -#endif -{ x.swap(y); } +bool operator>=(const avl_multiset_impl &x, const avl_multiset_impl &y); + +template +void swap(avl_multiset_impl &x, avl_multiset_impl &y); + +#endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Helper metafunction to define a \c avl_multiset that yields to the same type when the //! same options (either explicitly or implicitly) are used. #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else -template +template #endif struct make_avl_multiset { /// @cond + typedef typename pack_options + < avltree_defaults, + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3, O4 + #else + Options... + #endif + >::type packed_options; + + typedef typename detail::get_value_traits + ::type value_traits; + typedef avl_multiset_impl - < typename make_avltree_opt - #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - - #else - - #endif - ::type - > implementation_defined; + < value_traits + , typename packed_options::compare + , typename packed_options::size_type + , packed_options::constant_time_size + > implementation_defined; /// @endcond typedef implementation_defined type; }; @@ -2461,22 +856,23 @@ template #endif class avl_multiset : public make_avl_multiset::type -{ - typedef typename make_avl_multiset #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - + O1, O2, O3, O4 #else - + Options... #endif - ::type Base; + >::type +{ + typedef typename make_avl_multiset::type Base; BOOST_MOVABLE_BUT_NOT_COPYABLE(avl_multiset) + public: typedef typename Base::value_compare value_compare; typedef typename Base::value_traits value_traits; @@ -2503,7 +899,7 @@ class avl_multiset {} avl_multiset& operator=(BOOST_RV_REF(avl_multiset) x) - { this->Base::operator=(::boost::move(static_cast(x))); return *this; } + { return static_cast(this->Base::operator=(::boost::move(static_cast(x)))); } static avl_multiset &container_from_end_iterator(iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } @@ -2511,11 +907,11 @@ class avl_multiset static const avl_multiset &container_from_end_iterator(const_iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } - static avl_multiset &container_from_iterator(iterator end_iterator) - { return static_cast(Base::container_from_iterator(end_iterator)); } + static avl_multiset &container_from_iterator(iterator it) + { return static_cast(Base::container_from_iterator(it)); } - static const avl_multiset &container_from_iterator(const_iterator end_iterator) - { return static_cast(Base::container_from_iterator(end_iterator)); } + static const avl_multiset &container_from_iterator(const_iterator it) + { return static_cast(Base::container_from_iterator(it)); } }; #endif diff --git a/include/boost/intrusive/avl_set_hook.hpp b/include/boost/intrusive/avl_set_hook.hpp index 825921f..cd0478d 100644 --- a/include/boost/intrusive/avl_set_hook.hpp +++ b/include/boost/intrusive/avl_set_hook.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 @@ -37,7 +37,7 @@ struct get_avl_set_node_algo #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else -template +template #endif struct make_avl_set_base_hook { @@ -50,12 +50,12 @@ struct make_avl_set_base_hook #endif ::type packed_options; - typedef detail::generic_hook + typedef generic_hook < get_avl_set_node_algo , typename packed_options::tag , packed_options::link_mode - , detail::AvlSetBaseHook + , AvlTreeBaseHookId > implementation_defined; /// @endcond typedef implementation_defined type; @@ -168,7 +168,7 @@ class avl_set_base_hook #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else -template +template #endif struct make_avl_set_member_hook { @@ -181,12 +181,12 @@ struct make_avl_set_member_hook #endif ::type packed_options; - typedef detail::generic_hook + typedef generic_hook < get_avl_set_node_algo , member_tag , packed_options::link_mode - , detail::NoBaseHook + , NoBaseHookId > implementation_defined; /// @endcond typedef implementation_defined type; diff --git a/include/boost/intrusive/avltree.hpp b/include/boost/intrusive/avltree.hpp index b6311c4..a9362b9 100644 --- a/include/boost/intrusive/avltree.hpp +++ b/include/boost/intrusive/avltree.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -41,26 +42,14 @@ namespace intrusive { /// @cond -template -struct avl_setopt +struct avltree_defaults { - typedef ValueTraits value_traits; - typedef Compare compare; - typedef SizeType size_type; - static const bool constant_time_size = ConstantTimeSize; + typedef detail::default_avltree_hook proto_value_traits; + static const bool constant_time_size = true; + typedef std::size_t size_type; + typedef void compare; }; -template -struct avl_set_defaults - : pack_options - < none - , base_hook - , constant_time_size - , size_type - , compare > - >::type -{}; - /// @endcond //! The class template avltree is an intrusive AVL tree container, that @@ -79,1636 +68,397 @@ struct avl_set_defaults #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class avltree_impl - : private detail::clear_on_destructor_base > -{ - template friend class detail::clear_on_destructor_base; - public: - typedef typename Config::value_traits value_traits; /// @cond - static const bool external_value_traits = - detail::external_value_traits_bool_is_true::value; - typedef typename detail::eval_if_c - < external_value_traits - , detail::eval_value_traits - , detail::identity - >::type real_value_traits; + : public bstree_impl + /// @endcond +{ + public: + typedef ValueTraits value_traits; + /// @cond + typedef bstree_impl< ValueTraits, VoidOrKeyComp, SizeType + , ConstantTimeSize, AvlTreeAlgorithms> tree_type; + typedef tree_type implementation_defined; /// @endcond - typedef typename real_value_traits::pointer pointer; - typedef typename real_value_traits::const_pointer const_pointer; - typedef typename boost::intrusive:: - pointer_traits::element_type value_type; - typedef value_type key_type; - typedef typename boost::intrusive:: - pointer_traits::reference reference; - typedef typename boost::intrusive:: - pointer_traits::reference const_reference; - typedef typename boost::intrusive:: - pointer_traits::difference_type difference_type; - typedef typename Config::size_type size_type; - typedef typename Config::compare value_compare; - typedef value_compare key_compare; - typedef tree_iterator iterator; - typedef tree_iterator const_iterator; - typedef boost::intrusive::detail::reverse_iterator reverse_iterator; - typedef boost::intrusive::detail::reverse_iteratorconst_reverse_iterator; - typedef typename real_value_traits::node_traits node_traits; - typedef typename node_traits::node node; - typedef typename pointer_traits - ::template rebind_pointer - ::type node_ptr; - typedef typename pointer_traits - ::template rebind_pointer - ::type const_node_ptr; - typedef avltree_algorithms node_algorithms; - static const bool constant_time_size = Config::constant_time_size; - static const bool stateful_value_traits = detail::store_cont_ptr_on_it::value; + typedef typename implementation_defined::pointer pointer; + typedef typename implementation_defined::const_pointer const_pointer; + typedef typename implementation_defined::value_type value_type; + typedef typename implementation_defined::key_type key_type; + typedef typename implementation_defined::reference reference; + typedef typename implementation_defined::const_reference const_reference; + typedef typename implementation_defined::difference_type difference_type; + typedef typename implementation_defined::size_type size_type; + typedef typename implementation_defined::value_compare value_compare; + typedef typename implementation_defined::key_compare key_compare; + typedef typename implementation_defined::iterator iterator; + typedef typename implementation_defined::const_iterator const_iterator; + typedef typename implementation_defined::reverse_iterator reverse_iterator; + typedef typename implementation_defined::const_reverse_iterator const_reverse_iterator; + typedef typename implementation_defined::node_traits node_traits; + typedef typename implementation_defined::node node; + typedef typename implementation_defined::node_ptr node_ptr; + typedef typename implementation_defined::const_node_ptr const_node_ptr; + typedef typename implementation_defined::node_algorithms node_algorithms; + static const bool constant_time_size = implementation_defined::constant_time_size; /// @cond private: - typedef detail::size_holder size_traits; - //noncopyable, movable + //noncopyable BOOST_MOVABLE_BUT_NOT_COPYABLE(avltree_impl) - enum { safemode_or_autounlink = - (int)real_value_traits::link_mode == (int)auto_unlink || - (int)real_value_traits::link_mode == (int)safe_link }; - - //Constant-time size is incompatible with auto-unlink hooks! - BOOST_STATIC_ASSERT(!(constant_time_size && ((int)real_value_traits::link_mode == (int)auto_unlink))); - - struct header_plus_size : public size_traits - { node header_; }; - - struct node_plus_pred_t : public detail::ebo_functor_holder - { - node_plus_pred_t(const value_compare &comp) - : detail::ebo_functor_holder(comp) - {} - header_plus_size header_plus_size_; - }; - - struct data_t : public avltree_impl::value_traits - { - typedef typename avltree_impl::value_traits value_traits; - data_t(const value_compare & comp, const value_traits &val_traits) - : value_traits(val_traits), node_plus_pred_(comp) - {} - node_plus_pred_t node_plus_pred_; - } data_; - - const value_compare &priv_comp() const - { return data_.node_plus_pred_.get(); } - - value_compare &priv_comp() - { return data_.node_plus_pred_.get(); } - - const value_traits &priv_value_traits() const - { return data_; } - - value_traits &priv_value_traits() - { return data_; } - - node_ptr priv_header_ptr() - { return pointer_traits::pointer_to(data_.node_plus_pred_.header_plus_size_.header_); } - - const_node_ptr priv_header_ptr() const - { return pointer_traits::pointer_to(data_.node_plus_pred_.header_plus_size_.header_); } - - static node_ptr uncast(const const_node_ptr & ptr) - { return pointer_traits::const_cast_from(ptr); } - - size_traits &priv_size_traits() - { return data_.node_plus_pred_.header_plus_size_; } - - const size_traits &priv_size_traits() const - { return data_.node_plus_pred_.header_plus_size_; } - - const real_value_traits &get_real_value_traits(detail::bool_) const - { return data_; } - - const real_value_traits &get_real_value_traits(detail::bool_) const - { return data_.get_value_traits(*this); } - - real_value_traits &get_real_value_traits(detail::bool_) - { return data_; } - - real_value_traits &get_real_value_traits(detail::bool_) - { return data_.get_value_traits(*this); } - /// @endcond public: - const real_value_traits &get_real_value_traits() const - { return this->get_real_value_traits(detail::bool_()); } + typedef typename implementation_defined::insert_commit_data insert_commit_data; - real_value_traits &get_real_value_traits() - { return this->get_real_value_traits(detail::bool_()); } - typedef typename node_algorithms::insert_commit_data insert_commit_data; - - //! Effects: Constructs an empty tree. - //! - //! Complexity: Constant. - //! - //! Throws: If value_traits::node_traits::node - //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) - //! or the copy constructor of the value_compare object throws. Basic guarantee. + //! @copydoc ::boost::intrusive::bstree::bstree(const value_compare &,const value_traits &) explicit avltree_impl( const value_compare &cmp = value_compare() - , const value_traits &v_traits = value_traits()) - : data_(cmp, v_traits) - { - node_algorithms::init_header(this->priv_header_ptr()); - this->priv_size_traits().set_size(size_type(0)); - } + , const value_traits &v_traits = value_traits()) + : tree_type(cmp, v_traits) + {} - //! Requires: Dereferencing iterator must yield an lvalue of type value_type. - //! cmp must be a comparison function that induces a strict weak ordering. - //! - //! Effects: Constructs an empty tree and inserts elements from - //! [b, e). - //! - //! Complexity: Linear in N if [b, e) is already sorted using - //! comp and otherwise N * log N, where N is the distance between first and last. - //! - //! Throws: If value_traits::node_traits::node - //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) - //! or the copy constructor/operator() of the value_compare object throws. Basic guarantee. + //! @copydoc ::boost::intrusive::bstree::bstree(bool,Iterator,Iterator,const value_compare &,const value_traits &) template avltree_impl( bool unique, Iterator b, Iterator e , const value_compare &cmp = value_compare() , const value_traits &v_traits = value_traits()) - : data_(cmp, v_traits) - { - node_algorithms::init_header(this->priv_header_ptr()); - this->priv_size_traits().set_size(size_type(0)); - if(unique) - this->insert_unique(b, e); - else - this->insert_equal(b, e); - } - - //! Effects: to-do - //! - avltree_impl(BOOST_RV_REF(avltree_impl) x) - : data_(::boost::move(x.priv_comp()), ::boost::move(x.priv_value_traits())) - { - node_algorithms::init_header(this->priv_header_ptr()); - this->priv_size_traits().set_size(size_type(0)); - this->swap(x); - } - - //! Effects: to-do - //! - avltree_impl& operator=(BOOST_RV_REF(avltree_impl) x) - { this->swap(x); return *this; } - - //! Effects: Detaches all elements from this. The objects in the set - //! are not deleted (i.e. no destructors are called), but the nodes according to - //! the value_traits template parameter are reinitialized and thus can be reused. - //! - //! Complexity: Linear to elements contained in *this. - //! - //! Throws: Nothing. - ~avltree_impl() + : tree_type(unique, b, e, cmp, v_traits) {} - //! Effects: Returns an iterator pointing to the beginning of the tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator begin() - { return iterator (node_traits::get_left(this->priv_header_ptr()), this); } + //! @copydoc ::boost::intrusive::bstree::bstree(bstree &&) + avltree_impl(BOOST_RV_REF(avltree_impl) x) + : tree_type(::boost::move(static_cast(x))) + {} - //! Effects: Returns a const_iterator pointing to the beginning of the tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator begin() const - { return cbegin(); } + //! @copydoc ::boost::intrusive::bstree::operator=(bstree &&) + avltree_impl& operator=(BOOST_RV_REF(avltree_impl) x) + { return static_cast(tree_type::operator=(::boost::move(static_cast(x)))); } - //! Effects: Returns a const_iterator pointing to the beginning of the tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator cbegin() const - { return const_iterator (node_traits::get_left(this->priv_header_ptr()), this); } + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! Effects: Returns an iterator pointing to the end of the tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator end() - { return iterator (this->priv_header_ptr(), this); } + //! @copydoc ::boost::intrusive::bstree::~bstree() + ~avltree_impl(); - //! Effects: Returns a const_iterator pointing to the end of the tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator end() const - { return cend(); } + //! @copydoc ::boost::intrusive::bstree::begin() + iterator begin(); - //! Effects: Returns a const_iterator pointing to the end of the tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator cend() const - { return const_iterator (uncast(this->priv_header_ptr()), this); } + //! @copydoc ::boost::intrusive::bstree::begin()const + const_iterator begin() const; - //! Effects: Returns a reverse_iterator pointing to the beginning of the - //! reversed tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - reverse_iterator rbegin() - { return reverse_iterator(end()); } + //! @copydoc ::boost::intrusive::bstree::cbegin()const + const_iterator cbegin() const; - //! Effects: Returns a const_reverse_iterator pointing to the beginning - //! of the reversed tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator rbegin() const - { return const_reverse_iterator(end()); } + //! @copydoc ::boost::intrusive::bstree::end() + iterator end(); - //! Effects: Returns a const_reverse_iterator pointing to the beginning - //! of the reversed tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator crbegin() const - { return const_reverse_iterator(end()); } + //! @copydoc ::boost::intrusive::bstree::end()const + const_iterator end() const; - //! Effects: Returns a reverse_iterator pointing to the end - //! of the reversed tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - reverse_iterator rend() - { return reverse_iterator(begin()); } + //! @copydoc ::boost::intrusive::bstree::cend()const + const_iterator cend() const; - //! Effects: Returns a const_reverse_iterator pointing to the end - //! of the reversed tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator rend() const - { return const_reverse_iterator(begin()); } + //! @copydoc ::boost::intrusive::bstree::rbegin() + reverse_iterator rbegin(); - //! Effects: Returns a const_reverse_iterator pointing to the end - //! of the reversed tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator crend() const - { return const_reverse_iterator(begin()); } + //! @copydoc ::boost::intrusive::bstree::rbegin()const + const_reverse_iterator rbegin() const; - //! Precondition: end_iterator must be a valid end iterator - //! of avltree. - //! - //! Effects: Returns a const reference to the avltree associated to the end iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - static avltree_impl &container_from_end_iterator(iterator end_iterator) - { return priv_container_from_end_iterator(end_iterator); } + //! @copydoc ::boost::intrusive::bstree::crbegin()const + const_reverse_iterator crbegin() const; - //! Precondition: end_iterator must be a valid end const_iterator - //! of avltree. - //! - //! Effects: Returns a const reference to the avltree associated to the end iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - static const avltree_impl &container_from_end_iterator(const_iterator end_iterator) - { return priv_container_from_end_iterator(end_iterator); } + //! @copydoc ::boost::intrusive::bstree::rend() + reverse_iterator rend(); - //! Precondition: it must be a valid iterator - //! of rbtree. - //! - //! Effects: Returns a const reference to the tree associated to the iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Logarithmic. - static avltree_impl &container_from_iterator(iterator it) - { return priv_container_from_iterator(it); } + //! @copydoc ::boost::intrusive::bstree::rend()const + const_reverse_iterator rend() const; - //! Precondition: it must be a valid end const_iterator - //! of rbtree. - //! - //! Effects: Returns a const reference to the tree associated to the iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Logarithmic. - static const avltree_impl &container_from_iterator(const_iterator it) - { return priv_container_from_iterator(it); } + //! @copydoc ::boost::intrusive::bstree::crend()const + const_reverse_iterator crend() const; - //! Effects: Returns the value_compare object used by the tree. - //! - //! Complexity: Constant. - //! - //! Throws: If value_compare copy-constructor throws. - value_compare value_comp() const - { return priv_comp(); } + //! @copydoc ::boost::intrusive::bstree::container_from_end_iterator(iterator) + static avltree_impl &container_from_end_iterator(iterator end_iterator); - //! Effects: Returns true if the container is empty. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - bool empty() const - { return node_algorithms::unique(this->priv_header_ptr()); } + //! @copydoc ::boost::intrusive::bstree::container_from_end_iterator(const_iterator) + static const avltree_impl &container_from_end_iterator(const_iterator end_iterator); - //! Effects: Returns the number of elements stored in the tree. - //! - //! Complexity: Linear to elements contained in *this - //! if constant-time size option is disabled. Constant time otherwise. - //! - //! Throws: Nothing. - size_type size() const - { - if(constant_time_size) - return this->priv_size_traits().get_size(); - else{ - return (size_type)node_algorithms::size(this->priv_header_ptr()); - } - } + //! @copydoc ::boost::intrusive::bstree::container_from_iterator(iterator) + static avltree_impl &container_from_iterator(iterator it); - //! Effects: Swaps the contents of two avltrees. - //! - //! Complexity: Constant. - //! - //! Throws: If the comparison functor's swap call throws. - void swap(avltree_impl& other) - { - //This can throw - using std::swap; - swap(priv_comp(), priv_comp()); - //These can't throw - node_algorithms::swap_tree(this->priv_header_ptr(), other.priv_header_ptr()); - if(constant_time_size){ - size_type backup = this->priv_size_traits().get_size(); - this->priv_size_traits().set_size(other.priv_size_traits().get_size()); - other.priv_size_traits().set_size(backup); - } - } + //! @copydoc ::boost::intrusive::bstree::container_from_iterator(const_iterator) + static const avltree_impl &container_from_iterator(const_iterator it); - //! Requires: value must be an lvalue - //! - //! Effects: Inserts value into the tree before the upper bound. - //! - //! Complexity: Average complexity for insert element is at - //! most logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. Strong guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. - iterator insert_equal(reference value) - { - detail::key_nodeptr_comp - key_node_comp(priv_comp(), this); - node_ptr to_insert(get_real_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->priv_header_ptr(), to_insert, key_node_comp), this); - this->priv_size_traits().increment(); - return ret; - } + //! @copydoc ::boost::intrusive::bstree::key_comp()const + key_compare key_comp() const; - //! Requires: value must be an lvalue, and "hint" must be - //! a valid iterator. - //! - //! Effects: Inserts x into the tree, using "hint" as a hint to - //! where it will be inserted. If "hint" is the upper_bound - //! the insertion takes constant time (two comparisons in the worst case) - //! - //! Complexity: Logarithmic in general, but it is amortized - //! constant time if t is inserted immediately before hint. - //! - //! Throws: If the internal value_compare ordering function throws. Strong guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. - iterator insert_equal(const_iterator hint, reference value) - { - detail::key_nodeptr_comp - key_node_comp(priv_comp(), this); - node_ptr to_insert(get_real_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->priv_header_ptr(), hint.pointed_node(), to_insert, key_node_comp), this); - this->priv_size_traits().increment(); - return ret; - } + //! @copydoc ::boost::intrusive::bstree::value_comp()const + value_compare value_comp() const; - //! Requires: Dereferencing iterator must yield an lvalue - //! of type value_type. - //! - //! Effects: Inserts a each element of a range into the tree - //! before the upper bound of the key of each element. - //! - //! Complexity: Insert range is in general O(N * log(N)), where N is the - //! size of the range. However, it is linear in N if the range is already sorted - //! by value_comp(). - //! - //! Throws: Nothing. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + //! @copydoc ::boost::intrusive::bstree::empty()const + bool empty() const; + + //! @copydoc ::boost::intrusive::bstree::size()const + size_type size() const; + + //! @copydoc ::boost::intrusive::bstree::swap + void swap(avltree_impl& other); + + //! @copydoc ::boost::intrusive::bstree::clone_from + template + void clone_from(const avltree_impl &src, Cloner cloner, Disposer disposer); + + //! @copydoc ::boost::intrusive::bstree::insert_equal(reference) + iterator insert_equal(reference value); + + //! @copydoc ::boost::intrusive::bstree::insert_equal(const_iterator,reference) + iterator insert_equal(const_iterator hint, reference value); + + //! @copydoc ::boost::intrusive::bstree::insert_equal(Iterator,Iterator) template - void insert_equal(Iterator b, Iterator e) - { - iterator iend(this->end()); - for (; b != e; ++b) - this->insert_equal(iend, *b); - } + void insert_equal(Iterator b, Iterator e); - //! Requires: value must be an lvalue - //! - //! Effects: Inserts value into the tree if the value - //! is not already present. - //! - //! Complexity: Average complexity for insert element is at - //! most logarithmic. - //! - //! Throws: Nothing. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. - std::pair insert_unique(reference value) - { - insert_commit_data commit_data; - std::pair ret = insert_unique_check(value, priv_comp(), commit_data); - if(!ret.second) - return ret; - return std::pair (insert_unique_commit(value, commit_data), true); - } + //! @copydoc ::boost::intrusive::bstree::insert_unique(reference) + std::pair insert_unique(reference value); - //! Requires: value must be an lvalue, and "hint" must be - //! a valid iterator - //! - //! Effects: Tries to insert x into the tree, using "hint" as a hint - //! to where it will be inserted. - //! - //! Complexity: Logarithmic in general, but it is amortized - //! constant time (two comparisons in the worst case) - //! if t is inserted immediately before hint. - //! - //! Throws: Nothing. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. - iterator insert_unique(const_iterator hint, reference value) - { - insert_commit_data commit_data; - std::pair ret = insert_unique_check(hint, value, priv_comp(), commit_data); - if(!ret.second) - return ret.first; - return insert_unique_commit(value, commit_data); - } + //! @copydoc ::boost::intrusive::bstree::insert_unique(const_iterator,reference) + iterator insert_unique(const_iterator hint, reference value); - //! Requires: Dereferencing iterator must yield an lvalue - //! of type value_type. - //! - //! Effects: Tries to insert each element of a range into the tree. - //! - //! Complexity: Insert range is in general O(N * log(N)), where N is the - //! size of the range. However, it is linear in N if the range is already sorted - //! by value_comp(). - //! - //! Throws: Nothing. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. - template - void insert_unique(Iterator b, Iterator e) - { - if(this->empty()){ - iterator iend(this->end()); - for (; b != e; ++b) - this->insert_unique(iend, *b); - } - else{ - for (; b != e; ++b) - this->insert_unique(*b); - } - } - - //! Requires: key_value_comp must be a comparison function that induces - //! the same strict weak ordering as value_compare. The difference is that - //! key_value_comp compares an arbitrary key with the contained values. - //! - //! Effects: Checks if a value can be inserted in the container, using - //! a user provided key instead of the value itself. - //! - //! Returns: If there is an equivalent value - //! returns a pair containing an iterator to the already present value - //! and false. If the value can be inserted returns true in the returned - //! pair boolean and fills "commit_data" that is meant to be used with - //! the "insert_commit" function. - //! - //! Complexity: Average complexity is at most logarithmic. - //! - //! Throws: If the key_value_comp ordering function throws. Strong guarantee. - //! - //! Notes: This function is used to improve performance when constructing - //! a value_type is expensive: if there is an equivalent value - //! the constructed object must be discarded. Many times, the part of the - //! node that is used to impose the order is much cheaper to construct - //! than the value_type and this function offers the possibility to use that - //! part to check if the insertion will be successful. - //! - //! If the check is successful, the user can construct the value_type and use - //! "insert_commit" to insert the object in constant-time. This gives a total - //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)). - //! - //! "commit_data" remains valid for a subsequent "insert_commit" only if no more - //! objects are inserted or erased from the container. + //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const KeyType&,KeyValueCompare,insert_commit_data&) template 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); - std::pair ret = - (node_algorithms::insert_unique_check - (this->priv_header_ptr(), key, comp, commit_data)); - return std::pair(iterator(ret.first, this), ret.second); - } + (const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data); - //! Requires: key_value_comp must be a comparison function that induces - //! the same strict weak ordering as value_compare. The difference is that - //! key_value_comp compares an arbitrary key with the contained values. - //! - //! Effects: Checks if a value can be inserted in the container, using - //! a user provided key instead of the value itself, using "hint" - //! as a hint to where it will be inserted. - //! - //! Returns: If there is an equivalent value - //! returns a pair containing an iterator to the already present value - //! and false. If the value can be inserted returns true in the returned - //! pair boolean and fills "commit_data" that is meant to be used with - //! the "insert_commit" function. - //! - //! Complexity: Logarithmic in general, but it's amortized - //! constant time if t is inserted immediately before hint. - //! - //! Throws: If the key_value_comp ordering function throws. Strong guarantee. - //! - //! Notes: This function is used to improve performance when constructing - //! a value_type is expensive: if there is an equivalent value - //! the constructed object must be discarded. Many times, the part of the - //! constructing that is used to impose the order is much cheaper to construct - //! than the value_type and this function offers the possibility to use that key - //! to check if the insertion will be successful. - //! - //! If the check is successful, the user can construct the value_type and use - //! "insert_commit" to insert the object in constant-time. This can give a total - //! constant-time complexity to the insertion: check(O(1)) + commit(O(1)). - //! - //! "commit_data" remains valid for a subsequent "insert_commit" only if no more - //! objects are inserted or erased from the container. + //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const_iterator,const KeyType&,KeyValueCompare,insert_commit_data&) template std::pair insert_unique_check (const_iterator hint, const KeyType &key - ,KeyValueCompare key_value_comp, insert_commit_data &commit_data) - { - detail::key_nodeptr_comp - comp(key_value_comp, this); - std::pair ret = - (node_algorithms::insert_unique_check - (this->priv_header_ptr(), hint.pointed_node(), key, comp, commit_data)); - return std::pair(iterator(ret.first, this), ret.second); - } + ,KeyValueCompare key_value_comp, insert_commit_data &commit_data); - //! Requires: value must be an lvalue of type value_type. commit_data - //! must have been obtained from a previous call to "insert_check". - //! No objects should have been inserted or erased from the container between - //! the "insert_check" that filled "commit_data" and the call to "insert_commit". - //! - //! Effects: Inserts the value in the avl_set using the information obtained - //! from the "commit_data" that a previous "insert_check" filled. - //! - //! Returns: An iterator to the newly inserted object. - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Notes: This function has only sense if a "insert_check" has been - //! previously executed to fill "commit_data". No value should be inserted or - //! 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(get_real_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->priv_header_ptr(), to_insert, commit_data); - this->priv_size_traits().increment(); - return iterator(to_insert, this); - } + //! @copydoc ::boost::intrusive::bstree::insert_unique_commit + iterator insert_unique_commit(reference value, const insert_commit_data &commit_data); - //! Requires: value must be an lvalue, "pos" must be - //! a valid iterator (or end) and must be the succesor of value - //! once inserted according to the predicate - //! - //! Effects: Inserts x into the tree before "pos". - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Note: This function does not check preconditions so if "pos" is not - //! the successor of "value" tree ordering invariant will be broken. - //! This is a low-level function to be used only for performance reasons - //! by advanced users. - iterator insert_before(const_iterator pos, reference value) - { - node_ptr to_insert(get_real_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_before - (this->priv_header_ptr(), pos.pointed_node(), to_insert), this); - this->priv_size_traits().increment(); - return ret; - } + //! @copydoc ::boost::intrusive::bstree::insert_unique(Iterator,Iterator) + template + void insert_unique(Iterator b, Iterator e); - //! Requires: value must be an lvalue, and it must be no less - //! than the greatest inserted key - //! - //! Effects: Inserts x into the tree in the last position. - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Note: This function does not check preconditions so if value is - //! less than the greatest inserted key tree ordering invariant will be broken. - //! This function is slightly more efficient than using "insert_before". - //! This is a low-level function to be used only for performance reasons - //! by advanced users. - void push_back(reference value) - { - node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); - if(safemode_or_autounlink) - BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); - node_algorithms::push_back(this->priv_header_ptr(), to_insert); - this->priv_size_traits().increment(); - } + //! @copydoc ::boost::intrusive::bstree::insert_before + iterator insert_before(const_iterator pos, reference value); - //! Requires: value must be an lvalue, and it must be no greater - //! than the minimum inserted key - //! - //! Effects: Inserts x into the tree in the first position. - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Note: This function does not check preconditions so if value is - //! greater than the minimum inserted key tree ordering invariant will be broken. - //! This function is slightly more efficient than using "insert_before". - //! This is a low-level function to be used only for performance reasons - //! by advanced users. - void push_front(reference value) - { - node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); - if(safemode_or_autounlink) - BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); - node_algorithms::push_front(this->priv_header_ptr(), to_insert); - this->priv_size_traits().increment(); - } + //! @copydoc ::boost::intrusive::bstree::push_back + void push_back(reference value); - //! Effects: Erases the element pointed to by pos. - //! - //! Complexity: Average complexity for erase element is constant time. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - iterator erase(const_iterator i) - { - const_iterator ret(i); - ++ret; - node_ptr to_erase(i.pointed_node()); - if(safemode_or_autounlink) - BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!node_algorithms::unique(to_erase)); - node_algorithms::erase(this->priv_header_ptr(), to_erase); - this->priv_size_traits().decrement(); - if(safemode_or_autounlink) - node_algorithms::init(to_erase); - return ret.unconst(); - } + //! @copydoc ::boost::intrusive::bstree::push_front + void push_front(reference value); - //! Effects: Erases the range pointed to by b end e. - //! - //! Complexity: Average complexity for erase range is at most - //! O(log(size() + N)), where N is the number of elements in the range. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - iterator erase(const_iterator b, const_iterator e) - { size_type n; return private_erase(b, e, n); } + //! @copydoc ::boost::intrusive::bstree::erase(const_iterator) + iterator erase(const_iterator i); - //! Effects: Erases all the elements with the given value. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: O(log(size() + N). - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - size_type erase(const_reference value) - { return this->erase(value, priv_comp()); } + //! @copydoc ::boost::intrusive::bstree::erase(const_iterator,const_iterator) + iterator erase(const_iterator b, const_iterator e); - //! Effects: Erases all the elements with the given key. - //! according to the comparison functor "comp". - //! - //! Returns: The number of erased elements. - //! - //! Complexity: O(log(size() + N). - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. + //! @copydoc ::boost::intrusive::bstree::erase(const_reference) + size_type erase(const_reference value); + + //! @copydoc ::boost::intrusive::bstree::erase(const KeyType&,KeyValueCompare) template - size_type erase(const KeyType& key, KeyValueCompare comp - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) - { - std::pair p = this->equal_range(key, comp); - size_type n; - private_erase(p.first, p.second, n); - return n; - } + size_type erase(const KeyType& key, KeyValueCompare comp); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases the element pointed to by pos. - //! Disposer::operator()(pointer) is called for the removed element. - //! - //! Complexity: Average complexity for erase element is constant time. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_iterator,Disposer) template - iterator erase_and_dispose(const_iterator i, Disposer disposer) - { - node_ptr to_erase(i.pointed_node()); - iterator ret(this->erase(i)); - disposer(get_real_value_traits().to_value_ptr(to_erase)); - return ret; - } + iterator erase_and_dispose(const_iterator i, Disposer disposer); - #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_iterator,const_iterator,Disposer) template - iterator erase_and_dispose(iterator i, Disposer disposer) - { return this->erase_and_dispose(const_iterator(i), disposer); } - #endif + iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases the range pointed to by b end e. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Complexity: Average complexity for erase range is at most - //! O(log(size() + N)), where N is the number of elements in the range. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_reference, Disposer) template - iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer) - { size_type n; return private_erase(b, e, n, disposer); } + size_type erase_and_dispose(const_reference value, Disposer disposer); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements with the given value. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: O(log(size() + N). - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - template - size_type erase_and_dispose(const_reference value, Disposer disposer) - { - std::pair p = this->equal_range(value); - size_type n; - private_erase(p.first, p.second, n, disposer); - return n; - } - - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements with the given key. - //! according to the comparison functor "comp". - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: O(log(size() + N). - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const KeyType&,KeyValueCompare,Disposer) template - size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) - { - std::pair p = this->equal_range(key, comp); - size_type n; - private_erase(p.first, p.second, n, disposer); - return n; - } + size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer); - //! Effects: Erases all of the elements. - //! - //! Complexity: Linear to the number of elements on the container. - //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - void clear() - { - if(safemode_or_autounlink){ - this->clear_and_dispose(detail::null_disposer()); - } - else{ - node_algorithms::init_header(this->priv_header_ptr()); - this->priv_size_traits().set_size(0); - } - } + //! @copydoc ::boost::intrusive::bstree::clear + void clear(); - //! Effects: Erases all of the elements calling disposer(p) for - //! each node to be erased. - //! Complexity: Average complexity for is at most O(log(size() + N)), - //! where N is the number of elements in the container. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. Calls N times to disposer functor. + //! @copydoc ::boost::intrusive::bstree::clear_and_dispose template - void clear_and_dispose(Disposer disposer) - { - node_algorithms::clear_and_dispose(this->priv_header_ptr() - , detail::node_disposer(disposer, this)); - node_algorithms::init_header(this->priv_header_ptr()); - this->priv_size_traits().set_size(0); - } + void clear_and_dispose(Disposer disposer); - //! Effects: Returns the number of contained elements with the given value - //! - //! Complexity: Logarithmic to the number of elements contained plus lineal - //! to number of objects with the given value. - //! - //! Throws: Nothing. - size_type count(const_reference value) const - { return this->count(value, priv_comp()); } + //! @copydoc ::boost::intrusive::bstree::count(const_reference)const + size_type count(const_reference value) const; - //! Effects: Returns the number of contained elements with the given key - //! - //! Complexity: Logarithmic to the number of elements contained plus lineal - //! to number of objects with the given key. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const template - size_type count(const KeyType &key, KeyValueCompare comp) const - { - std::pair ret = this->equal_range(key, comp); - return std::distance(ret.first, ret.second); - } - - //! Effects: Returns an iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - iterator lower_bound(const_reference value) - { return this->lower_bound(value, priv_comp()); } - - //! Effects: Returns an iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - const_iterator lower_bound(const_reference value) const - { return this->lower_bound(value, priv_comp()); } - - //! Effects: Returns an iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + size_type count(const KeyType& key, KeyValueCompare comp) const; + + //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference) + iterator lower_bound(const_reference value); + + //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare) template - iterator lower_bound(const KeyType &key, KeyValueCompare comp) - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - return iterator(node_algorithms::lower_bound - (this->priv_header_ptr(), key, key_node_comp), this); - } + iterator lower_bound(const KeyType& key, KeyValueCompare comp); - //! Effects: Returns a const iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference)const + const_iterator lower_bound(const_reference value) const; + + //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare)const template - const_iterator lower_bound(const KeyType &key, KeyValueCompare comp) const - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - return const_iterator(node_algorithms::lower_bound - (this->priv_header_ptr(), key, key_node_comp), this); - } + const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Returns an iterator to the first element whose - //! key is greater than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - iterator upper_bound(const_reference value) - { return this->upper_bound(value, priv_comp()); } + //! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference) + iterator upper_bound(const_reference value); - //! Effects: Returns an iterator to the first element whose - //! key is greater than k according to comp or end() if that element - //! does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare) template - iterator upper_bound(const KeyType &key, KeyValueCompare comp) - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - return iterator(node_algorithms::upper_bound - (this->priv_header_ptr(), key, key_node_comp), this); - } + iterator upper_bound(const KeyType& key, KeyValueCompare comp); - //! Effects: Returns an iterator to the first element whose - //! key is greater than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - const_iterator upper_bound(const_reference value) const - { return this->upper_bound(value, priv_comp()); } + //! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference)const + const_iterator upper_bound(const_reference value) const; - //! Effects: Returns an iterator to the first element whose - //! key is greater than k according to comp or end() if that element - //! does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare)const template - const_iterator upper_bound(const KeyType &key, KeyValueCompare comp) const - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - return const_iterator(node_algorithms::upper_bound - (this->priv_header_ptr(), key, key_node_comp), this); - } + const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Finds an iterator to the first element whose key is - //! k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - iterator find(const_reference value) - { return this->find(value, priv_comp()); } + //! @copydoc ::boost::intrusive::bstree::find(const_reference) + iterator find(const_reference value); - //! Effects: Finds an iterator to the first element whose key is - //! k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare) template - iterator find(const KeyType &key, KeyValueCompare comp) - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - return iterator - (node_algorithms::find(this->priv_header_ptr(), key, key_node_comp), this); - } + iterator find(const KeyType& key, KeyValueCompare comp); - //! Effects: Finds a const_iterator to the first element whose key is - //! k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - const_iterator find(const_reference value) const - { return this->find(value, priv_comp()); } + //! @copydoc ::boost::intrusive::bstree::find(const_reference)const + const_iterator find(const_reference value) const; - //! Effects: Finds a const_iterator to the first element whose key is - //! k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare)const template - const_iterator find(const KeyType &key, KeyValueCompare comp) const - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - return const_iterator - (node_algorithms::find(this->priv_header_ptr(), key, key_node_comp), this); - } + const_iterator find(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - std::pair equal_range(const_reference value) - { return this->equal_range(value, priv_comp()); } + //! @copydoc ::boost::intrusive::bstree::equal_range(const_reference) + std::pair equal_range(const_reference value); - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare) template - std::pair equal_range(const KeyType &key, KeyValueCompare comp) - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - std::pair ret - (node_algorithms::equal_range(this->priv_header_ptr(), key, key_node_comp)); - return std::pair(iterator(ret.first, this), iterator(ret.second, this)); - } + std::pair equal_range(const KeyType& key, KeyValueCompare comp); - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::equal_range(const_reference)const std::pair - equal_range(const_reference value) const - { return this->equal_range(value, priv_comp()); } + equal_range(const_reference value) const; - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare)const template std::pair - equal_range(const KeyType &key, KeyValueCompare comp) const - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - std::pair ret - (node_algorithms::equal_range(this->priv_header_ptr(), key, key_node_comp)); - return std::pair(const_iterator(ret.first, this), const_iterator(ret.second, this)); - } + equal_range(const KeyType& key, KeyValueCompare comp) const; - //! Requires: 'lower_value' must not be greater than 'upper_value'. If - //! 'lower_value' == 'upper_value', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise - //! - //! second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the predicate throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_value and upper_value. + //! @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) - { return this->bounded_range(lower_value, upper_value, priv_comp(), left_closed, right_closed); } + (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); - //! Requires: KeyValueCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. - //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If - //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key, comp) if left_closed, upper_bound(lower_key, comp) otherwise - //! - //! second = upper_bound(upper_key, comp) if right_closed, lower_bound(upper_key, comp) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_key and upper_key. + //! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool) template std::pair bounded_range - (const KeyType &lower_key, const KeyType &upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - std::pair ret - (node_algorithms::bounded_range - (this->priv_header_ptr(), lower_key, upper_key, key_node_comp, left_closed, right_closed)); - return std::pair(iterator(ret.first, this), iterator(ret.second, this)); - } + (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed); - //! Requires: 'lower_value' must not be greater than 'upper_value'. If - //! 'lower_value' == 'upper_value', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise - //! - //! second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the predicate throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_value and upper_value. - std::pair bounded_range - (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const - { return this->bounded_range(lower_value, upper_value, priv_comp(), left_closed, right_closed); } + //! @copydoc ::boost::intrusive::bstree::bounded_range(const_reference,const_reference,bool,bool)const + std::pair + bounded_range(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; - //! Requires: KeyValueCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. - //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If - //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key, comp) if left_closed, upper_bound(lower_key, comp) otherwise - //! - //! second = upper_bound(upper_key, comp) if right_closed, lower_bound(upper_key, comp) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_key and upper_key. + //! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const template - std::pair bounded_range - (const KeyType &lower_key, const KeyType &upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - std::pair ret - (node_algorithms::bounded_range - (this->priv_header_ptr(), lower_key, upper_key, key_node_comp, left_closed, right_closed)); - return std::pair(const_iterator(ret.first, this), const_iterator(ret.second, this)); - } + std::pair bounded_range + (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! Cloner should yield to nodes equivalent to the original nodes. - //! - //! Effects: Erases all the elements from *this - //! calling Disposer::operator()(pointer), clones all the - //! elements from src calling Cloner::operator()(const_reference ) - //! and inserts them on *this. Copies the predicate from the source container. - //! - //! If cloner throws, all cloned elements are unlinked and disposed - //! calling Disposer::operator()(pointer). - //! - //! Complexity: Linear to erased plus inserted elements. - //! - //! Throws: If cloner throws or predicate copy assignment throws. Basic guarantee. - template - void clone_from(const avltree_impl &src, Cloner cloner, Disposer disposer) - { - this->clear_and_dispose(disposer); - if(!src.empty()){ - detail::exception_disposer - rollback(*this, disposer); - node_algorithms::clone - (src.priv_header_ptr() - ,this->priv_header_ptr() - ,detail::node_cloner(cloner, this) - ,detail::node_disposer(disposer, this)); - this->priv_size_traits().set_size(src.priv_size_traits().get_size()); - this->priv_comp() = src.priv_comp(); - rollback.release(); - } - } + //! @copydoc ::boost::intrusive::bstree::s_iterator_to(reference) + static iterator s_iterator_to(reference value); - //! Effects: Unlinks the leftmost node from the tree. - //! - //! Complexity: Average complexity is constant time. - //! - //! Throws: Nothing. - //! - //! Notes: This function breaks the tree and the tree can - //! only be used for more unlink_leftmost_without_rebalance calls. - //! This function is normally used to achieve a step by step - //! controlled destruction of the tree. - pointer unlink_leftmost_without_rebalance() - { - node_ptr to_be_disposed(node_algorithms::unlink_leftmost_without_rebalance - (this->priv_header_ptr())); - if(!to_be_disposed) - return 0; - this->priv_size_traits().decrement(); - if(safemode_or_autounlink)//If this is commented does not work with normal_link - node_algorithms::init(to_be_disposed); - return get_real_value_traits().to_value_ptr(to_be_disposed); - } + //! @copydoc ::boost::intrusive::bstree::s_iterator_to(const_reference) + static const_iterator s_iterator_to(const_reference value); - //! Requires: replace_this must be a valid iterator of *this - //! and with_this must not be inserted in any tree. - //! - //! Effects: Replaces replace_this in its position in the - //! tree with with_this. The tree does not need to be rebalanced. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This function will break container ordering invariants if - //! with_this is not equivalent to *replace_this according to the - //! ordering rules. This function is faster than erasing and inserting - //! the node, since no rebalancing or comparison is needed. - void replace_node(iterator replace_this, reference with_this) - { - node_algorithms::replace_node( get_real_value_traits().to_node_ptr(*replace_this) - , this->priv_header_ptr() - , get_real_value_traits().to_node_ptr(with_this)); - if(safemode_or_autounlink) - node_algorithms::init(replace_this.pointed_node()); - } + //! @copydoc ::boost::intrusive::bstree::iterator_to(reference) + iterator iterator_to(reference value); - //! Requires: value must be an lvalue and shall be in a set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid iterator i belonging to the set - //! that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This static function is available only if the value traits - //! is stateless. - static iterator s_iterator_to(reference value) - { - BOOST_STATIC_ASSERT((!stateful_value_traits)); - return iterator (value_traits::to_node_ptr(value), 0); - } + //! @copydoc ::boost::intrusive::bstree::iterator_to(const_reference)const + const_iterator iterator_to(const_reference value) const; - //! Requires: value must be an lvalue and shall be in a set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid const_iterator i belonging to the - //! set that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This static function is available only if the value traits - //! is stateless. - static const_iterator s_iterator_to(const_reference value) - { - BOOST_STATIC_ASSERT((!stateful_value_traits)); - return const_iterator (value_traits::to_node_ptr(const_cast (value)), 0); - } + //! @copydoc ::boost::intrusive::bstree::init_node(reference) + static void init_node(reference value); - //! Requires: value must be an lvalue and shall be in a set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid iterator i belonging to the set - //! that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator iterator_to(reference value) - { return iterator (value_traits::to_node_ptr(value), this); } + //! @copydoc ::boost::intrusive::bstree::unlink_leftmost_without_rebalance + pointer unlink_leftmost_without_rebalance(); - //! Requires: value must be an lvalue and shall be in a set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid const_iterator i belonging to the - //! set that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator iterator_to(const_reference value) const - { return const_iterator (value_traits::to_node_ptr(const_cast (value)), this); } + //! @copydoc ::boost::intrusive::bstree::replace_node + void replace_node(iterator replace_this, reference with_this); - //! Requires: value shall not be in a tree. - //! - //! Effects: init_node puts the hook of a value in a well-known default - //! state. - //! - //! Throws: Nothing. - //! - //! Complexity: Constant time. - //! - //! Note: This function puts the hook in the well-known default state - //! used by auto_unlink and safe hooks. - static void init_node(reference value) - { node_algorithms::init(value_traits::to_node_ptr(value)); } - -/* - //! Effects: removes x from a tree of the appropriate type. It has no effect, - //! if x is not in such a tree. - //! - //! Throws: Nothing. - //! - //! Complexity: Constant time. - //! - //! Note: This static function is only usable with the "safe mode" - //! hook and non-constant time size lists. Otherwise, the user must use - //! the non-static "erase(reference )" member. If the user calls - //! this function with a non "safe mode" or constant time size list - //! a compilation error will be issued. - template - static void remove_node(T& value) - { - //This function is only usable for safe mode hooks and non-constant - //time lists. - //BOOST_STATIC_ASSERT((!(safemode_or_autounlink && constant_time_size))); - BOOST_STATIC_ASSERT((!constant_time_size)); - BOOST_STATIC_ASSERT((boost::is_convertible::value)); - node_ptr to_remove(value_traits::to_node_ptr(value)); - node_algorithms::unlink_and_rebalance(to_remove); - if(safemode_or_autounlink) - node_algorithms::init(to_remove); - } -*/ - - /// @cond - - private: - template - iterator private_erase(const_iterator b, const_iterator e, size_type &n, Disposer disposer) - { - for(n = 0; b != e; ++n) - this->erase_and_dispose(b++, disposer); - return b.unconst(); - } - - iterator private_erase(const_iterator b, const_iterator e, size_type &n) - { - for(n = 0; b != e; ++n) - this->erase(b++); - return b.unconst(); - } - /// @endcond - - private: - static avltree_impl &priv_container_from_end_iterator(const const_iterator &end_iterator) - { - header_plus_size *r = detail::parent_from_member - ( boost::intrusive::detail::to_raw_pointer(end_iterator.pointed_node()), &header_plus_size::header_); - node_plus_pred_t *n = detail::parent_from_member - (r, &node_plus_pred_t::header_plus_size_); - data_t *d = detail::parent_from_member(n, &data_t::node_plus_pred_); - avltree_impl *avl = detail::parent_from_member(d, &avltree_impl::data_); - return *avl; - } - - static avltree_impl &priv_container_from_iterator(const const_iterator &it) - { return priv_container_from_end_iterator(it.end_iterator_from_it()); } + //! @copydoc ::boost::intrusive::bstree::remove_node + void remove_node(reference value); + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED }; #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + template -#else -template -#endif -inline bool operator< -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const avltree_impl &x, const avltree_impl &y) -#else -(const avltree_impl &x, const avltree_impl &y) -#endif -{ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } +bool operator< (const avltree_impl &x, const avltree_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -bool operator== -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const avltree_impl &x, const avltree_impl &y) -#else -(const avltree_impl &x, const avltree_impl &y) -#endif -{ - typedef avltree_impl tree_type; - typedef typename tree_type::const_iterator const_iterator; +bool operator==(const avltree_impl &x, const avltree_impl &y); - if(tree_type::constant_time_size && x.size() != y.size()){ - return false; - } - const_iterator end1 = x.end(); - const_iterator i1 = x.begin(); - const_iterator i2 = y.begin(); - if(tree_type::constant_time_size){ - while (i1 != end1 && *i1 == *i2) { - ++i1; - ++i2; - } - return i1 == end1; - } - else{ - const_iterator end2 = y.end(); - while (i1 != end1 && i2 != end2 && *i1 == *i2) { - ++i1; - ++i2; - } - return i1 == end1 && i2 == end2; - } -} - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator!= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const avltree_impl &x, const avltree_impl &y) -#else -(const avltree_impl &x, const avltree_impl &y) -#endif -{ return !(x == y); } +bool operator!= (const avltree_impl &x, const avltree_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator> -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const avltree_impl &x, const avltree_impl &y) -#else -(const avltree_impl &x, const avltree_impl &y) -#endif -{ return y < x; } +bool operator>(const avltree_impl &x, const avltree_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator<= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const avltree_impl &x, const avltree_impl &y) -#else -(const avltree_impl &x, const avltree_impl &y) -#endif -{ return !(y < x); } +bool operator<=(const avltree_impl &x, const avltree_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator>= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const avltree_impl &x, const avltree_impl &y) -#else -(const avltree_impl &x, const avltree_impl &y) -#endif -{ return !(x < y); } +bool operator>=(const avltree_impl &x, const avltree_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline void swap -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(avltree_impl &x, avltree_impl &y) -#else -(avltree_impl &x, avltree_impl &y) -#endif -{ x.swap(y); } +void swap(avltree_impl &x, avltree_impl &y); -/// @cond - -#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) -template -#else -template -#endif -struct make_avltree_opt -{ - typedef typename pack_options - #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - < avl_set_defaults, O1, O2, O3, O4> - #else - < avl_set_defaults, Options...> - #endif - ::type packed_options; - - typedef typename detail::get_value_traits - ::type value_traits; - - typedef avl_setopt - < value_traits - , typename packed_options::compare - , typename packed_options::size_type - , packed_options::constant_time_size - > type; -}; -/// @endcond +#endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Helper metafunction to define a \c avltree that yields to the same type when the //! same options (either explicitly or implicitly) are used. #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else -template +template #endif struct make_avltree { /// @cond - typedef avltree_impl + typedef typename pack_options + < avltree_defaults, #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - < typename make_avltree_opt::type + O1, O2, O3, O4 #else - < typename make_avltree_opt::type + Options... #endif - > implementation_defined; + >::type packed_options; + + typedef typename detail::get_value_traits + ::type value_traits; + + typedef avltree_impl + < value_traits + , typename packed_options::compare + , typename packed_options::size_type + , packed_options::constant_time_size + > implementation_defined; /// @endcond typedef implementation_defined type; }; + #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) @@ -1717,20 +467,22 @@ template template #endif class avltree - #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - : public make_avltree::type - #else - : public make_avltree::type - #endif + : public make_avltree::type { typedef typename make_avltree - #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - - #else - - #endif - ::type Base; - + ::type Base; BOOST_MOVABLE_BUT_NOT_COPYABLE(avltree) public: @@ -1739,12 +491,14 @@ class avltree 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)); - avltree( const value_compare &cmp = value_compare() - , const value_traits &v_traits = value_traits()) + avltree( const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) : Base(cmp, v_traits) {} @@ -1760,7 +514,7 @@ class avltree {} avltree& operator=(BOOST_RV_REF(avltree) x) - { this->Base::operator=(::boost::move(static_cast(x))); return *this; } + { return static_cast(this->Base::operator=(::boost::move(static_cast(x)))); } static avltree &container_from_end_iterator(iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } @@ -1777,7 +531,6 @@ class avltree #endif - } //namespace intrusive } //namespace boost diff --git a/include/boost/intrusive/avltree_algorithms.hpp b/include/boost/intrusive/avltree_algorithms.hpp index 11463c7..3622658 100644 --- a/include/boost/intrusive/avltree_algorithms.hpp +++ b/include/boost/intrusive/avltree_algorithms.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Daniel K. O. 2005. -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 @@ -21,20 +21,52 @@ #include #include -#include +#include #include namespace boost { namespace intrusive { +/// @cond + +template +struct avltree_node_cloner + : private detail::ebo_functor_holder +{ + typedef typename NodeTraits::node_ptr node_ptr; + typedef detail::ebo_functor_holder base_t; + + avltree_node_cloner(F f) + : base_t(f) + {} + + node_ptr operator()(const node_ptr & p) + { + node_ptr n = base_t::get()(p); + NodeTraits::set_balance(n, NodeTraits::get_balance(p)); + return n; + } +}; + +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 //! information about the node to be manipulated. NodeTraits must support the //! following interface: //! //! Typedefs: //! -//! node: The type of the node that forms the circular list +//! node: The type of the node that forms the binary search tree //! //! node_ptr: A pointer to a node //! @@ -67,6 +99,9 @@ namespace intrusive { //! static balance positive(); template class avltree_algorithms + #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + : public bstree_algorithms + #endif { public: typedef typename NodeTraits::node node; @@ -77,161 +112,69 @@ class avltree_algorithms /// @cond private: - typedef detail::tree_algorithms tree_algorithms; + typedef bstree_algorithms bstree_algorithms; - template - struct avltree_node_cloner - : private detail::ebo_functor_holder - { - typedef detail::ebo_functor_holder base_t; - - avltree_node_cloner(F f) - : base_t(f) - {} - - node_ptr operator()(const node_ptr &p) - { - node_ptr n = base_t::get()(p); - NodeTraits::set_balance(n, NodeTraits::get_balance(p)); - return n; - } - }; - - struct avltree_erase_fixup - { - void operator()(const node_ptr &to_erase, const node_ptr &successor) - { NodeTraits::set_balance(successor, NodeTraits::get_balance(to_erase)); } - }; - - static node_ptr uncast(const const_node_ptr & ptr) - { return pointer_traits::const_cast_from(ptr); } /// @endcond public: - static node_ptr begin_node(const const_node_ptr & header) - { return tree_algorithms::begin_node(header); } - - static node_ptr end_node(const const_node_ptr & header) - { return tree_algorithms::end_node(header); } - //! This type is the information that will be //! filled by insert_unique_check - typedef typename tree_algorithms::insert_commit_data insert_commit_data; + typedef typename bstree_algorithms::insert_commit_data insert_commit_data; - //! Requires: header1 and header2 must be the header nodes - //! of two trees. - //! - //! Effects: Swaps two trees. After the function header1 will contain - //! links to the second tree and header2 will have links to the first tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - static void swap_tree(const node_ptr & header1, const node_ptr & header2) - { return tree_algorithms::swap_tree(header1, header2); } + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! Requires: node1 and node2 can't be header nodes - //! of two trees. - //! - //! Effects: Swaps two nodes. After the function node1 will be inserted - //! in the position node2 before the function. node2 will be inserted in the - //! position node1 had before the function. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - //! - //! Note: This function will break container ordering invariants if - //! node1 and node2 are not equivalent according to the ordering rules. - //! - //!Experimental function + //! @copydoc ::boost::intrusive::bstree_algorithms::get_header(const const_node_ptr&) + static node_ptr get_header(const const_node_ptr & n); + + //! @copydoc ::boost::intrusive::bstree_algorithms::begin_node + static node_ptr begin_node(const const_node_ptr & header); + + //! @copydoc ::boost::intrusive::bstree_algorithms::end_node + static node_ptr end_node(const const_node_ptr & header); + + //! @copydoc ::boost::intrusive::bstree_algorithms::swap_tree + static void swap_tree(const node_ptr & header1, const node_ptr & header2); + + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + + //! @copydoc ::boost::intrusive::bstree_algorithms::swap_nodes(const node_ptr&,const node_ptr&) static void swap_nodes(const node_ptr & node1, const node_ptr & node2) { if(node1 == node2) return; - node_ptr header1(tree_algorithms::get_header(node1)), header2(tree_algorithms::get_header(node2)); + node_ptr header1(bstree_algorithms::get_header(node1)), header2(bstree_algorithms::get_header(node2)); swap_nodes(node1, header1, node2, header2); } - //! Requires: node1 and node2 can't be header nodes - //! of two trees with header header1 and header2. - //! - //! Effects: Swaps two nodes. After the function node1 will be inserted - //! in the position node2 before the function. node2 will be inserted in the - //! position node1 had before the function. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This function will break container ordering invariants if - //! node1 and node2 are not equivalent according to the ordering rules. - //! - //!Experimental function + //! @copydoc ::boost::intrusive::bstree_algorithms::swap_nodes(const node_ptr&,const node_ptr&,const node_ptr&,const node_ptr&) static void swap_nodes(const node_ptr & node1, const node_ptr & header1, const node_ptr & node2, const node_ptr & header2) { if(node1 == node2) return; - tree_algorithms::swap_nodes(node1, header1, node2, header2); + bstree_algorithms::swap_nodes(node1, header1, node2, header2); //Swap balance balance c = NodeTraits::get_balance(node1); NodeTraits::set_balance(node1, NodeTraits::get_balance(node2)); NodeTraits::set_balance(node2, c); } - //! Requires: node_to_be_replaced must be inserted in a tree - //! and new_node must not be inserted in a tree. - //! - //! Effects: Replaces node_to_be_replaced in its position in the - //! tree with new_node. The tree does not need to be rebalanced - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - //! - //! Note: This function will break container ordering invariants if - //! new_node is not equivalent to node_to_be_replaced according to the - //! ordering rules. This function is faster than erasing and inserting - //! the node, since no rebalancing and comparison is needed. - //! - //!Experimental function + //! @copydoc ::boost::intrusive::bstree_algorithms::replace_node(const node_ptr&,const node_ptr&) static void replace_node(const node_ptr & node_to_be_replaced, const node_ptr & new_node) { if(node_to_be_replaced == new_node) return; - replace_node(node_to_be_replaced, tree_algorithms::get_header(node_to_be_replaced), new_node); + replace_node(node_to_be_replaced, bstree_algorithms::get_header(node_to_be_replaced), new_node); } - //! Requires: node_to_be_replaced must be inserted in a tree - //! with header "header" and new_node must not be inserted in a tree. - //! - //! Effects: Replaces node_to_be_replaced in its position in the - //! tree with new_node. The tree does not need to be rebalanced - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This function will break container ordering invariants if - //! new_node is not equivalent to node_to_be_replaced according to the - //! ordering rules. This function is faster than erasing and inserting - //! the node, since no rebalancing or comparison is needed. - //! - //!Experimental function + //! @copydoc ::boost::intrusive::bstree_algorithms::replace_node(const node_ptr&,const node_ptr&,const node_ptr&) static void replace_node(const node_ptr & node_to_be_replaced, const node_ptr & header, const node_ptr & new_node) { - tree_algorithms::replace_node(node_to_be_replaced, header, new_node); + bstree_algorithms::replace_node(node_to_be_replaced, header, new_node); NodeTraits::set_balance(new_node, NodeTraits::get_balance(node_to_be_replaced)); } - //! Requires: node is a tree node but not the header. - //! - //! Effects: Unlinks the node and rebalances the tree. - //! - //! Complexity: Average complexity is constant time. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree_algorithms::unlink(const node_ptr&) static void unlink(const node_ptr & node) { node_ptr x = NodeTraits::get_parent(node); @@ -242,84 +185,25 @@ class avltree_algorithms } } - //! Requires: header is the header of a tree. - //! - //! Effects: Unlinks the leftmost node from the tree, and - //! updates the header link to the new leftmost node. - //! - //! Complexity: Average complexity is constant time. - //! - //! Throws: Nothing. - //! - //! Notes: This function breaks the tree and the tree can - //! only be used for more unlink_leftmost_without_rebalance calls. - //! This function is normally used to achieve a step by step - //! controlled destruction of the tree. - static node_ptr unlink_leftmost_without_rebalance(const node_ptr & header) - { return tree_algorithms::unlink_leftmost_without_rebalance(header); } + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::bstree_algorithms::unlink_leftmost_without_rebalance + static node_ptr unlink_leftmost_without_rebalance(const node_ptr & header); - //! Requires: node is a node of the tree or an node initialized - //! by init(...). - //! - //! Effects: Returns true if the node is initialized by init(). - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - static bool unique(const const_node_ptr & node) - { return tree_algorithms::unique(node); } + //! @copydoc ::boost::intrusive::bstree_algorithms::unique(const const_node_ptr&) + static bool unique(const const_node_ptr & node); - //! Requires: node is a node of the tree but it's not the header. - //! - //! Effects: Returns the number of nodes of the subtree. - //! - //! Complexity: Linear time. - //! - //! Throws: Nothing. - static std::size_t count(const const_node_ptr & node) - { return tree_algorithms::count(node); } + //! @copydoc ::boost::intrusive::bstree_algorithms::size(const const_node_ptr&) + static std::size_t size(const const_node_ptr & header); - //! Requires: header is the header node of the tree. - //! - //! Effects: Returns the number of nodes above the header. - //! - //! Complexity: Linear time. - //! - //! Throws: Nothing. - static std::size_t size(const const_node_ptr & header) - { return tree_algorithms::size(header); } + //! @copydoc ::boost::intrusive::bstree_algorithms::next_node(const node_ptr&) + static node_ptr next_node(const node_ptr & node); - //! Requires: p is a node from the tree except the header. - //! - //! Effects: Returns the next node of the tree. - //! - //! Complexity: Average constant time. - //! - //! Throws: Nothing. - static node_ptr next_node(const node_ptr & p) - { return tree_algorithms::next_node(p); } + //! @copydoc ::boost::intrusive::bstree_algorithms::prev_node(const node_ptr&) + static node_ptr prev_node(const node_ptr & node); - //! Requires: p is a node from the tree except the leftmost node. - //! - //! Effects: Returns the previous node of the tree. - //! - //! Complexity: Average constant time. - //! - //! Throws: Nothing. - static node_ptr prev_node(const node_ptr & p) - { return tree_algorithms::prev_node(p); } - - //! Requires: node must not be part of any tree. - //! - //! Effects: After the function unique(node) == true. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Nodes: If node is inserted in a tree, this function corrupts the tree. - static void init(const node_ptr & node) - { tree_algorithms::init(node); } + //! @copydoc ::boost::intrusive::bstree_algorithms::init(const node_ptr&) + static void init(const node_ptr & node); + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! Requires: node must not be part of any tree. //! @@ -333,419 +217,148 @@ class avltree_algorithms //! Nodes: If node is inserted in a tree, this function corrupts the tree. static void init_header(const node_ptr & header) { - tree_algorithms::init_header(header); + bstree_algorithms::init_header(header); NodeTraits::set_balance(header, NodeTraits::zero()); } - //! Requires: header must be the header of a tree, z a node - //! of that tree and z != header. - //! - //! Effects: Erases node "z" from the tree with header "header". - //! - //! Complexity: Amortized constant time. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree_algorithms::erase(const node_ptr&,const node_ptr&) static node_ptr erase(const node_ptr & header, const node_ptr & z) { - typename tree_algorithms::data_for_rebalance info; - tree_algorithms::erase(header, z, avltree_erase_fixup(), info); - node_ptr x = info.x; - node_ptr x_parent = info.x_parent; - + typename bstree_algorithms::data_for_rebalance info; + bstree_algorithms::erase(header, z, avltree_erase_fixup(), info); //Rebalance avltree - rebalance_after_erasure(header, x, x_parent); + rebalance_after_erasure(header, info.x, info.x_parent); return z; } - //! Requires: "cloner" must be a function - //! object taking a node_ptr and returning a new cloned node of it. "disposer" must - //! take a node_ptr and shouldn't throw. - //! - //! Effects: First empties target tree calling - //! void disposer::operator()(const node_ptr &) for every node of the tree - //! except the header. - //! - //! Then, duplicates the entire tree pointed by "source_header" cloning each - //! source node with node_ptr Cloner::operator()(const node_ptr &) to obtain - //! the nodes of the target tree. If "cloner" throws, the cloned target nodes - //! are disposed using void disposer(const node_ptr &). - //! - //! Complexity: Linear to the number of element of the source tree plus the. - //! number of elements of tree target tree when calling this function. - //! - //! Throws: If cloner functor throws. If this happens target nodes are disposed. + //! @copydoc ::boost::intrusive::bstree_algorithms::clone(const const_node_ptr&,const node_ptr&,Cloner,Disposer) template static void clone (const const_node_ptr & source_header, const node_ptr & target_header, Cloner cloner, Disposer disposer) { - avltree_node_cloner new_cloner(cloner); - tree_algorithms::clone(source_header, target_header, new_cloner, disposer); + avltree_node_cloner new_cloner(cloner); + bstree_algorithms::clone(source_header, target_header, new_cloner, disposer); } - //! Requires: "disposer" must be an object function - //! taking a node_ptr parameter and shouldn't throw. - //! - //! Effects: Empties the target tree calling - //! void disposer::operator()(const node_ptr &) for every node of the tree - //! except the header. - //! - //! Complexity: Linear to the number of element of the source tree plus the. - //! number of elements of tree target tree when calling this function. - //! - //! Throws: If cloner functor throws. If this happens target nodes are disposed. + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::bstree_algorithms::clear_and_dispose(const node_ptr&,Disposer) template - static void clear_and_dispose(const node_ptr & header, Disposer disposer) - { tree_algorithms::clear_and_dispose(header, disposer); } + static void clear_and_dispose(const node_ptr & header, Disposer disposer); - //! 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 an node_ptr to the first element that is - //! not less than "key" according to "comp" or "header" if that element does - //! not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. + //! @copydoc ::boost::intrusive::bstree_algorithms::lower_bound(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) template static node_ptr lower_bound - (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) - { return tree_algorithms::lower_bound(header, key, comp); } + (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp); - //! 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 an node_ptr to the first element that is greater - //! than "key" according to "comp" or "header" if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. + //! @copydoc ::boost::intrusive::bstree_algorithms::upper_bound(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) template static node_ptr upper_bound - (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) - { return tree_algorithms::upper_bound(header, key, comp); } + (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp); - //! 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 an node_ptr to the element that is equivalent to - //! "key" according to "comp" or "header" if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. + //! @copydoc ::boost::intrusive::bstree_algorithms::find(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) template static node_ptr find - (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) - { return tree_algorithms::find(header, key, comp); } + (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp); - //! 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 an a pair of node_ptr delimiting a range containing - //! all elements that are equivalent to "key" according to "comp" or an - //! empty range that indicates the position where those elements would be - //! if they there are no equivalent elements. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. + //! @copydoc ::boost::intrusive::bstree_algorithms::equal_range(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) template static std::pair equal_range - (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) - { return tree_algorithms::equal_range(header, key, comp); } + (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp); - //! 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. - //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If - //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise - //! - //! second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_key and upper_key. + //! @copydoc ::boost::intrusive::bstree_algorithms::bounded_range(const const_node_ptr&,const KeyType&,const KeyType&,KeyNodePtrCompare,bool,bool) template static std::pair bounded_range (const const_node_ptr & header, const KeyType &lower_key, const KeyType &upper_key, KeyNodePtrCompare comp - , bool left_closed, bool right_closed) - { return tree_algorithms::bounded_range(header, lower_key, upper_key, comp, left_closed, right_closed); } + , bool left_closed, bool right_closed); - //! Requires: "h" must be the header node of a tree. - //! NodePtrCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. NodePtrCompare compares two node_ptrs. - //! - //! Effects: Inserts new_node into the tree before the upper bound - //! according to "comp". - //! - //! Complexity: Average complexity for insert element is at - //! most logarithmic. - //! - //! Throws: If "comp" throws. + //! @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) template static node_ptr insert_equal_upper_bound (const node_ptr & h, const node_ptr & new_node, NodePtrCompare comp) { - tree_algorithms::insert_equal_upper_bound(h, new_node, comp); + bstree_algorithms::insert_equal_upper_bound(h, new_node, comp); rebalance_after_insertion(h, new_node); return new_node; } - //! Requires: "h" must be the header node of a tree. - //! NodePtrCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. NodePtrCompare compares two node_ptrs. - //! - //! Effects: Inserts new_node into the tree before the lower bound - //! according to "comp". - //! - //! Complexity: Average complexity for insert element is at - //! most logarithmic. - //! - //! Throws: If "comp" throws. + //! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal_lower_bound(const node_ptr&,const node_ptr&,NodePtrCompare) template static node_ptr insert_equal_lower_bound (const node_ptr & h, const node_ptr & new_node, NodePtrCompare comp) { - tree_algorithms::insert_equal_lower_bound(h, new_node, comp); + bstree_algorithms::insert_equal_lower_bound(h, new_node, comp); rebalance_after_insertion(h, new_node); return new_node; } - //! Requires: "header" must be the header node of a tree. - //! NodePtrCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. NodePtrCompare compares two node_ptrs. "hint" is node from - //! the "header"'s tree. - //! - //! Effects: Inserts new_node into the tree, using "hint" as a hint to - //! where it will be inserted. If "hint" is the upper_bound - //! the insertion takes constant time (two comparisons in the worst case). - //! - //! Complexity: Logarithmic in general, but it is amortized - //! constant time if new_node is inserted immediately before "hint". - //! - //! Throws: If "comp" throws. + //! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal(const node_ptr&,const node_ptr&,const node_ptr&,NodePtrCompare) template static node_ptr insert_equal (const node_ptr & header, const node_ptr & hint, const node_ptr & new_node, NodePtrCompare comp) { - tree_algorithms::insert_equal(header, hint, new_node, comp); + bstree_algorithms::insert_equal(header, hint, new_node, comp); rebalance_after_insertion(header, new_node); return new_node; } - //! Requires: "header" must be the header node of a tree. - //! "pos" must be a valid iterator or header (end) node. - //! "pos" must be an iterator pointing to the successor to "new_node" - //! once inserted according to the order of already inserted nodes. This function does not - //! check "pos" and this precondition must be guaranteed by the caller. - //! - //! Effects: Inserts new_node into the tree before "pos". - //! - //! Complexity: Constant-time. - //! - //! Throws: Nothing. - //! - //! Note: If "pos" is not the successor of the newly inserted "new_node" - //! tree invariants might be broken. + //! @copydoc ::boost::intrusive::bstree_algorithms::insert_before(const node_ptr&,const node_ptr&,const node_ptr&) static node_ptr insert_before (const node_ptr & header, const node_ptr & pos, const node_ptr & new_node) { - tree_algorithms::insert_before(header, pos, new_node); + bstree_algorithms::insert_before(header, pos, new_node); rebalance_after_insertion(header, new_node); return new_node; } - //! Requires: "header" must be the header node of a tree. - //! "new_node" must be, according to the used ordering no less than the - //! greatest inserted key. - //! - //! Effects: Inserts new_node into the tree before "pos". - //! - //! Complexity: Constant-time. - //! - //! Throws: Nothing. - //! - //! Note: If "new_node" is less than the greatest inserted key - //! tree invariants are broken. This function is slightly faster than - //! using "insert_before". + //! @copydoc ::boost::intrusive::bstree_algorithms::push_back(const node_ptr&,const node_ptr&) static void push_back(const node_ptr & header, const node_ptr & new_node) { - tree_algorithms::push_back(header, new_node); + bstree_algorithms::push_back(header, new_node); rebalance_after_insertion(header, new_node); } - //! Requires: "header" must be the header node of a tree. - //! "new_node" must be, according to the used ordering, no greater than the - //! lowest inserted key. - //! - //! Effects: Inserts new_node into the tree before "pos". - //! - //! Complexity: Constant-time. - //! - //! Throws: Nothing. - //! - //! Note: If "new_node" is greater than the lowest inserted key - //! tree invariants are broken. This function is slightly faster than - //! using "insert_before". + //! @copydoc ::boost::intrusive::bstree_algorithms::push_front(const node_ptr&,const node_ptr&) static void push_front(const node_ptr & header, const node_ptr & new_node) { - tree_algorithms::push_front(header, new_node); + bstree_algorithms::push_front(header, new_node); rebalance_after_insertion(header, new_node); } - //! 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. NodePtrCompare compares KeyType with a node_ptr. - //! - //! Effects: Checks if there is an equivalent node to "key" in the - //! tree according to "comp" and obtains the needed information to realize - //! a constant-time node insertion if there is no equivalent node. - //! - //! Returns: If there is an equivalent value - //! returns a pair containing a node_ptr to the already present node - //! and false. If there is not equivalent key can be inserted returns true - //! in the returned pair's boolean and fills "commit_data" that is meant to - //! be used with the "insert_commit" function to achieve a constant-time - //! insertion function. - //! - //! Complexity: Average complexity is at most logarithmic. - //! - //! Throws: If "comp" throws. - //! - //! Notes: This function is used to improve performance when constructing - //! a node is expensive and the user does not want to have two equivalent nodes - //! in the tree: if there is an equivalent value - //! the constructed object must be discarded. Many times, the part of the - //! node that is used to impose the order is much cheaper to construct - //! than the node and this function offers the possibility to use that part - //! to check if the insertion will be successful. - //! - //! If the check is successful, the user can construct the node and use - //! "insert_commit" to insert the node in constant-time. This gives a total - //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)). - //! - //! "commit_data" remains valid for a subsequent "insert_unique_commit" only - //! if no more objects are inserted or erased from the set. + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::bstree_algorithms::insert_unique_check(const const_node_ptr&,const KeyType&,KeyNodePtrCompare,insert_commit_data&) template static std::pair insert_unique_check (const const_node_ptr & header, const KeyType &key - ,KeyNodePtrCompare comp, insert_commit_data &commit_data) - { return tree_algorithms::insert_unique_check(header, key, comp, commit_data); } + ,KeyNodePtrCompare comp, insert_commit_data &commit_data); - //! 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. NodePtrCompare compares KeyType with a node_ptr. - //! "hint" is node from the "header"'s tree. - //! - //! Effects: Checks if there is an equivalent node to "key" in the - //! tree according to "comp" using "hint" as a hint to where it should be - //! inserted and obtains the needed information to realize - //! a constant-time node insertion if there is no equivalent node. - //! If "hint" is the upper_bound the function has constant time - //! complexity (two comparisons in the worst case). - //! - //! Returns: If there is an equivalent value - //! returns a pair containing a node_ptr to the already present node - //! and false. If there is not equivalent key can be inserted returns true - //! in the returned pair's boolean and fills "commit_data" that is meant to - //! be used with the "insert_commit" function to achieve a constant-time - //! insertion function. - //! - //! Complexity: Average complexity is at most logarithmic, but it is - //! amortized constant time if new_node should be inserted immediately before "hint". - //! - //! Throws: If "comp" throws. - //! - //! Notes: This function is used to improve performance when constructing - //! a node is expensive and the user does not want to have two equivalent nodes - //! in the tree: if there is an equivalent value - //! the constructed object must be discarded. Many times, the part of the - //! node that is used to impose the order is much cheaper to construct - //! than the node and this function offers the possibility to use that part - //! to check if the insertion will be successful. - //! - //! If the check is successful, the user can construct the node and use - //! "insert_commit" to insert the node in constant-time. This gives a total - //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)). - //! - //! "commit_data" remains valid for a subsequent "insert_unique_commit" only - //! if no more objects are inserted or erased from the set. + //! @copydoc ::boost::intrusive::bstree_algorithms::insert_unique_check(const const_node_ptr&,const node_ptr&,const KeyType&,KeyNodePtrCompare,insert_commit_data&) template static std::pair insert_unique_check (const const_node_ptr & header, const node_ptr &hint, const KeyType &key - ,KeyNodePtrCompare comp, insert_commit_data &commit_data) - { return tree_algorithms::insert_unique_check(header, hint, key, comp, commit_data); } + ,KeyNodePtrCompare comp, insert_commit_data &commit_data); + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! Requires: "header" must be the header node of a tree. - //! "commit_data" must have been obtained from a previous call to - //! "insert_unique_check". No objects should have been inserted or erased - //! from the set between the "insert_unique_check" that filled "commit_data" - //! and the call to "insert_commit". - //! - //! - //! Effects: Inserts new_node in the set using the information obtained - //! from the "commit_data" that a previous "insert_check" filled. - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Notes: This function has only sense if a "insert_unique_check" has been - //! previously executed to fill "commit_data". No value should be inserted or - //! erased between the "insert_check" and "insert_commit" calls. + //! @copydoc ::boost::intrusive::bstree_algorithms::insert_unique_commit(const node_ptr&,const node_ptr&,const insert_commit_data &) static void insert_unique_commit (const node_ptr & header, const node_ptr & new_value, const insert_commit_data &commit_data) { - tree_algorithms::insert_unique_commit(header, new_value, commit_data); + bstree_algorithms::insert_unique_commit(header, new_value, commit_data); rebalance_after_insertion(header, new_value); } - //! Requires: "n" must be a node inserted in a tree. - //! - //! Effects: Returns a pointer to the header node of the tree. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - static node_ptr get_header(const node_ptr & n) - { return tree_algorithms::get_header(n); } + //! @copydoc ::boost::intrusive::bstree_algorithms::is_header + static bool is_header(const const_node_ptr & p) + { return NodeTraits::get_balance(p) == NodeTraits::zero() && bstree_algorithms::is_header(p); } + /// @cond private: - //! Requires: p is a node of a tree. - //! - //! Effects: Returns true if p is the header of the tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - static bool is_header(const const_node_ptr & p) - { return NodeTraits::get_balance(p) == NodeTraits::zero() && tree_algorithms::is_header(p); } - static void rebalance_after_erasure(const node_ptr & header, const node_ptr & xnode, const node_ptr & xnode_parent) { node_ptr x(xnode), x_parent(xnode_parent); @@ -903,8 +516,8 @@ class avltree_algorithms // / \ // // e f // node_ptr b = NodeTraits::get_left(a), c = NodeTraits::get_right(b); - tree_algorithms::rotate_left(b, hdr); - tree_algorithms::rotate_right(a, hdr); + bstree_algorithms::rotate_left(b, hdr); + bstree_algorithms::rotate_right(a, hdr); left_right_balancing(a, b, c); } @@ -920,15 +533,15 @@ class avltree_algorithms // / \ // // e f // node_ptr b = NodeTraits::get_right(a), c = NodeTraits::get_left(b); - tree_algorithms::rotate_right(b, hdr); - tree_algorithms::rotate_left(a, hdr); + bstree_algorithms::rotate_right(b, hdr); + bstree_algorithms::rotate_left(a, hdr); left_right_balancing(b, a, c); } static void rotate_left(const node_ptr x, const node_ptr & hdr) { const node_ptr y = NodeTraits::get_right(x); - tree_algorithms::rotate_left(x, hdr); + bstree_algorithms::rotate_left(x, hdr); // reset the balancing factor if (NodeTraits::get_balance(y) == NodeTraits::positive()) { @@ -944,7 +557,7 @@ class avltree_algorithms static void rotate_right(const node_ptr x, const node_ptr & hdr) { const node_ptr y = NodeTraits::get_left(x); - tree_algorithms::rotate_right(x, hdr); + bstree_algorithms::rotate_right(x, hdr); // reset the balancing factor if (NodeTraits::get_balance(y) == NodeTraits::negative()) { @@ -960,6 +573,16 @@ class avltree_algorithms /// @endcond }; +/// @cond + +template +struct get_algo +{ + typedef avltree_algorithms type; +}; + +/// @endcond + } //namespace intrusive } //namespace boost diff --git a/include/boost/intrusive/bs_set.hpp b/include/boost/intrusive/bs_set.hpp new file mode 100644 index 0000000..4b2cdc6 --- /dev/null +++ b/include/boost/intrusive/bs_set.hpp @@ -0,0 +1,922 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2013-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_BS_SET_HPP +#define BOOST_INTRUSIVE_BS_SET_HPP + +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace intrusive { + +//! The class template bs_set is an intrusive container, that mimics most of +//! the interface of std::set as described in the C++ standard. +//! +//! The template parameter \c T is the type to be managed by the container. +//! The user can specify additional options and if no options are provided +//! default options are used. +//! +//! The container supports the following options: +//! \c base_hook<>/member_hook<>/value_traits<>, +//! \c constant_time_size<>, \c size_type<> and +//! \c compare<>. +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) +template +#else +template +#endif +class bs_set_impl +#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + : public bstree_impl +#endif +{ + /// @cond + typedef bstree_impl tree_type; + BOOST_MOVABLE_BUT_NOT_COPYABLE(bs_set_impl) + + typedef tree_type implementation_defined; + /// @endcond + + public: + typedef typename implementation_defined::value_type value_type; + typedef typename implementation_defined::value_traits value_traits; + typedef typename implementation_defined::pointer pointer; + typedef typename implementation_defined::const_pointer const_pointer; + typedef typename implementation_defined::reference reference; + typedef typename implementation_defined::const_reference const_reference; + typedef typename implementation_defined::difference_type difference_type; + typedef typename implementation_defined::size_type size_type; + typedef typename implementation_defined::value_compare value_compare; + typedef typename implementation_defined::key_compare key_compare; + typedef typename implementation_defined::iterator iterator; + typedef typename implementation_defined::const_iterator const_iterator; + typedef typename implementation_defined::reverse_iterator reverse_iterator; + typedef typename implementation_defined::const_reverse_iterator const_reverse_iterator; + typedef typename implementation_defined::insert_commit_data insert_commit_data; + typedef typename implementation_defined::node_traits node_traits; + typedef typename implementation_defined::node node; + typedef typename implementation_defined::node_ptr node_ptr; + typedef typename implementation_defined::const_node_ptr const_node_ptr; + typedef typename implementation_defined::node_algorithms node_algorithms; + + static const bool constant_time_size = tree_type::constant_time_size; + + public: + //! @copydoc ::boost::intrusive::bstree::bstree(const value_compare &,const value_traits &) + explicit bs_set_impl( const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : tree_type(cmp, v_traits) + {} + + //! @copydoc ::boost::intrusive::bstree::bstree(bool,Iterator,Iterator,const value_compare &,const value_traits &) + template + bs_set_impl( Iterator b, Iterator e + , const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : tree_type(true, b, e, cmp, v_traits) + {} + + //! @copydoc ::boost::intrusive::bstree::bstree(bstree &&) + bs_set_impl(BOOST_RV_REF(bs_set_impl) x) + : tree_type(::boost::move(static_cast(x))) + {} + + //! @copydoc ::boost::intrusive::bstree::operator=(bstree &&) + bs_set_impl& operator=(BOOST_RV_REF(bs_set_impl) x) + { return static_cast(tree_type::operator=(::boost::move(static_cast(x)))); } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::bstree::~bstree() + ~bs_set_impl(); + + //! @copydoc ::boost::intrusive::bstree::begin() + iterator begin(); + + //! @copydoc ::boost::intrusive::bstree::begin()const + const_iterator begin() const; + + //! @copydoc ::boost::intrusive::bstree::cbegin()const + const_iterator cbegin() const; + + //! @copydoc ::boost::intrusive::bstree::end() + iterator end(); + + //! @copydoc ::boost::intrusive::bstree::end()const + const_iterator end() const; + + //! @copydoc ::boost::intrusive::bstree::cend()const + const_iterator cend() const; + + //! @copydoc ::boost::intrusive::bstree::rbegin() + reverse_iterator rbegin(); + + //! @copydoc ::boost::intrusive::bstree::rbegin()const + const_reverse_iterator rbegin() const; + + //! @copydoc ::boost::intrusive::bstree::crbegin()const + const_reverse_iterator crbegin() const; + + //! @copydoc ::boost::intrusive::bstree::rend() + reverse_iterator rend(); + + //! @copydoc ::boost::intrusive::bstree::rend()const + const_reverse_iterator rend() const; + + //! @copydoc ::boost::intrusive::bstree::crend()const + const_reverse_iterator crend() const; + + //! @copydoc ::boost::intrusive::bstree::container_from_end_iterator(iterator) + static bs_set_impl &container_from_end_iterator(iterator end_iterator); + + //! @copydoc ::boost::intrusive::bstree::container_from_end_iterator(const_iterator) + static const bs_set_impl &container_from_end_iterator(const_iterator end_iterator); + + //! @copydoc ::boost::intrusive::bstree::container_from_iterator(iterator) + static bs_set_impl &container_from_iterator(iterator it); + + //! @copydoc ::boost::intrusive::bstree::container_from_iterator(const_iterator) + static const bs_set_impl &container_from_iterator(const_iterator it); + + //! @copydoc ::boost::intrusive::bstree::key_comp()const + key_compare key_comp() const; + + //! @copydoc ::boost::intrusive::bstree::value_comp()const + value_compare value_comp() const; + + //! @copydoc ::boost::intrusive::bstree::empty()const + bool empty() const; + + //! @copydoc ::boost::intrusive::bstree::size()const + size_type size() const; + + //! @copydoc ::boost::intrusive::bstree::swap + void swap(bs_set_impl& other); + + //! @copydoc ::boost::intrusive::bstree::clone_from + template + void clone_from(const bs_set_impl &src, Cloner cloner, Disposer disposer); + + #endif //#ifdef BOOST_iNTRUSIVE_DOXYGEN_INVOKED + + //! @copydoc ::boost::intrusive::bstree::insert_unique(reference) + std::pair insert(reference value) + { return tree_type::insert_unique(value); } + + //! @copydoc ::boost::intrusive::bstree::insert_unique(const_iterator,reference) + iterator insert(const_iterator hint, reference value) + { return tree_type::insert_unique(hint, value); } + + //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const KeyType&,KeyValueCompare,insert_commit_data&) + template + std::pair insert_check + (const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data) + { return tree_type::insert_unique_check(key, key_value_comp, commit_data); } + + //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const_iterator,const KeyType&,KeyValueCompare,insert_commit_data&) + template + std::pair insert_check + (const_iterator hint, const KeyType &key + ,KeyValueCompare key_value_comp, insert_commit_data &commit_data) + { return tree_type::insert_unique_check(hint, key, key_value_comp, commit_data); } + + //! @copydoc ::boost::intrusive::bstree::insert_unique(Iterator,Iterator) + template + void insert(Iterator b, Iterator e) + { tree_type::insert_unique(b, e); } + + //! @copydoc ::boost::intrusive::bstree::insert_unique_commit + iterator insert_commit(reference value, const insert_commit_data &commit_data) + { return tree_type::insert_unique_commit(value, commit_data); } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::bstree::insert_before + iterator insert_before(const_iterator pos, reference value); + + //! @copydoc ::boost::intrusive::bstree::push_back + void push_back(reference value); + + //! @copydoc ::boost::intrusive::bstree::push_front + void push_front(reference value); + + //! @copydoc ::boost::intrusive::bstree::erase(const_iterator) + iterator erase(const_iterator i); + + //! @copydoc ::boost::intrusive::bstree::erase(const_iterator,const_iterator) + iterator erase(const_iterator b, const_iterator e); + + //! @copydoc ::boost::intrusive::bstree::erase(const_reference) + size_type erase(const_reference value); + + //! @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) + template + iterator erase_and_dispose(const_iterator i, Disposer disposer); + + //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_iterator,const_iterator,Disposer) + template + iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer); + + //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_reference, Disposer) + template + size_type erase_and_dispose(const_reference value, Disposer disposer); + + //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const KeyType&,KeyValueCompare,Disposer) + template + size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer); + + //! @copydoc ::boost::intrusive::bstree::clear + void clear(); + + //! @copydoc ::boost::intrusive::bstree::clear_and_dispose + template + void clear_and_dispose(Disposer disposer); + + //! @copydoc ::boost::intrusive::bstree::count(const_reference)const + size_type count(const_reference value) const; + + //! @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); + + //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare) + template + iterator lower_bound(const KeyType& key, KeyValueCompare comp); + + //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference)const + const_iterator lower_bound(const_reference value) const; + + //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare)const + template + const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const; + + //! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference) + iterator upper_bound(const_reference value); + + //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare) + template + iterator upper_bound(const KeyType& key, KeyValueCompare comp); + + //! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference)const + const_iterator upper_bound(const_reference value) const; + + //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare)const + template + const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const; + + //! @copydoc ::boost::intrusive::bstree::find(const_reference) + iterator find(const_reference value); + + //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare) + template + iterator find(const KeyType& key, KeyValueCompare comp); + + //! @copydoc ::boost::intrusive::bstree::find(const_reference)const + const_iterator find(const_reference value) const; + + //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare)const + 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); + + //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare) + template + std::pair equal_range(const KeyType& key, KeyValueCompare comp); + + //! @copydoc ::boost::intrusive::bstree::equal_range(const_reference)const + std::pair + equal_range(const_reference value) const; + + //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare)const + template + std::pair + equal_range(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); + + //! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool) + template + std::pair bounded_range + (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed); + + //! @copydoc ::boost::intrusive::bstree::bounded_range(const_reference,const_reference,bool,bool)const + std::pair + bounded_range(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 + template + 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::s_iterator_to(reference) + static iterator s_iterator_to(reference value); + + //! @copydoc ::boost::intrusive::bstree::s_iterator_to(const_reference) + static const_iterator s_iterator_to(const_reference value); + + //! @copydoc ::boost::intrusive::bstree::iterator_to(reference) + iterator iterator_to(reference value); + + //! @copydoc ::boost::intrusive::bstree::iterator_to(const_reference)const + const_iterator iterator_to(const_reference value) const; + + //! @copydoc ::boost::intrusive::bstree::init_node(reference) + static void init_node(reference value); + + //! @copydoc ::boost::intrusive::bstree::unlink_leftmost_without_rebalance + pointer unlink_leftmost_without_rebalance(); + + //! @copydoc ::boost::intrusive::bstree::replace_node + void replace_node(iterator replace_this, reference with_this); + + //! @copydoc ::boost::intrusive::bstree::remove_node + void remove_node(reference value); + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +}; + +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + +template +bool operator!= (const bs_set_impl &x, const bs_set_impl &y); + +template +bool operator>(const bs_set_impl &x, const bs_set_impl &y); + +template +bool operator<=(const bs_set_impl &x, const bs_set_impl &y); + +template +bool operator>=(const bs_set_impl &x, const bs_set_impl &y); + +template +void swap(bs_set_impl &x, bs_set_impl &y); + +#endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + +//! Helper metafunction to define a \c bs_set that yields to the same type when the +//! same options (either explicitly or implicitly) are used. +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +template +#else +template +#endif +struct make_bs_set +{ + /// @cond + typedef typename pack_options + < bstree_defaults, + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3, O4 + #else + Options... + #endif + >::type packed_options; + + typedef typename detail::get_value_traits + ::type value_traits; + + typedef bs_set_impl + < value_traits + , typename packed_options::compare + , typename packed_options::size_type + , packed_options::constant_time_size + > implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + +#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +template +#else +template +#endif +class bs_set + : public make_bs_set::type +{ + typedef typename make_bs_set + ::type Base; + + BOOST_MOVABLE_BUT_NOT_COPYABLE(bs_set) + public: + typedef typename Base::value_compare value_compare; + typedef typename Base::value_traits value_traits; + typedef typename Base::iterator iterator; + typedef typename Base::const_iterator const_iterator; + + //Assert if passed value traits are compatible with the type + BOOST_STATIC_ASSERT((detail::is_same::value)); + + bs_set( const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : Base(cmp, v_traits) + {} + + template + bs_set( Iterator b, Iterator e + , const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : Base(b, e, cmp, v_traits) + {} + + bs_set(BOOST_RV_REF(bs_set) x) + : Base(::boost::move(static_cast(x))) + {} + + bs_set& operator=(BOOST_RV_REF(bs_set) x) + { return static_cast(this->Base::operator=(::boost::move(static_cast(x)))); } + + static bs_set &container_from_end_iterator(iterator end_iterator) + { return static_cast(Base::container_from_end_iterator(end_iterator)); } + + static const bs_set &container_from_end_iterator(const_iterator end_iterator) + { return static_cast(Base::container_from_end_iterator(end_iterator)); } + + static bs_set &container_from_iterator(iterator it) + { return static_cast(Base::container_from_iterator(it)); } + + static const bs_set &container_from_iterator(const_iterator it) + { return static_cast(Base::container_from_iterator(it)); } +}; + +#endif + +//! The class template bs_multiset is an intrusive container, that mimics most of +//! the interface of std::multiset as described in the C++ standard. +//! +//! The template parameter \c T is the type to be managed by the container. +//! The user can specify additional options and if no options are provided +//! default options are used. +//! +//! The container supports the following options: +//! \c base_hook<>/member_hook<>/value_traits<>, +//! \c constant_time_size<>, \c size_type<> and +//! \c compare<>. +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) +template +#else +template +#endif +class bs_multiset_impl +#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + : public bstree_impl +#endif +{ + /// @cond + typedef bstree_impl tree_type; + + BOOST_MOVABLE_BUT_NOT_COPYABLE(bs_multiset_impl) + typedef tree_type implementation_defined; + /// @endcond + + public: + typedef typename implementation_defined::value_type value_type; + typedef typename implementation_defined::value_traits value_traits; + typedef typename implementation_defined::pointer pointer; + typedef typename implementation_defined::const_pointer const_pointer; + typedef typename implementation_defined::reference reference; + typedef typename implementation_defined::const_reference const_reference; + typedef typename implementation_defined::difference_type difference_type; + typedef typename implementation_defined::size_type size_type; + typedef typename implementation_defined::value_compare value_compare; + typedef typename implementation_defined::key_compare key_compare; + typedef typename implementation_defined::iterator iterator; + typedef typename implementation_defined::const_iterator const_iterator; + typedef typename implementation_defined::reverse_iterator reverse_iterator; + typedef typename implementation_defined::const_reverse_iterator const_reverse_iterator; + typedef typename implementation_defined::insert_commit_data insert_commit_data; + typedef typename implementation_defined::node_traits node_traits; + typedef typename implementation_defined::node node; + typedef typename implementation_defined::node_ptr node_ptr; + typedef typename implementation_defined::const_node_ptr const_node_ptr; + typedef typename implementation_defined::node_algorithms node_algorithms; + + static const bool constant_time_size = tree_type::constant_time_size; + + public: + //! @copydoc ::boost::intrusive::bstree::bstree(const value_compare &,const value_traits &) + explicit bs_multiset_impl( const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : tree_type(cmp, v_traits) + {} + + //! @copydoc ::boost::intrusive::bstree::bstree(bool,Iterator,Iterator,const value_compare &,const value_traits &) + template + bs_multiset_impl( Iterator b, Iterator e + , const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : tree_type(false, b, e, cmp, v_traits) + {} + + //! @copydoc ::boost::intrusive::bstree::bstree(bstree &&) + bs_multiset_impl(BOOST_RV_REF(bs_multiset_impl) x) + : tree_type(::boost::move(static_cast(x))) + {} + + //! @copydoc ::boost::intrusive::bstree::operator=(bstree &&) + bs_multiset_impl& operator=(BOOST_RV_REF(bs_multiset_impl) x) + { return static_cast(tree_type::operator=(::boost::move(static_cast(x)))); } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::bstree::~bstree() + ~bs_multiset_impl(); + + //! @copydoc ::boost::intrusive::bstree::begin() + iterator begin(); + + //! @copydoc ::boost::intrusive::bstree::begin()const + const_iterator begin() const; + + //! @copydoc ::boost::intrusive::bstree::cbegin()const + const_iterator cbegin() const; + + //! @copydoc ::boost::intrusive::bstree::end() + iterator end(); + + //! @copydoc ::boost::intrusive::bstree::end()const + const_iterator end() const; + + //! @copydoc ::boost::intrusive::bstree::cend()const + const_iterator cend() const; + + //! @copydoc ::boost::intrusive::bstree::rbegin() + reverse_iterator rbegin(); + + //! @copydoc ::boost::intrusive::bstree::rbegin()const + const_reverse_iterator rbegin() const; + + //! @copydoc ::boost::intrusive::bstree::crbegin()const + const_reverse_iterator crbegin() const; + + //! @copydoc ::boost::intrusive::bstree::rend() + reverse_iterator rend(); + + //! @copydoc ::boost::intrusive::bstree::rend()const + const_reverse_iterator rend() const; + + //! @copydoc ::boost::intrusive::bstree::crend()const + const_reverse_iterator crend() const; + + //! @copydoc ::boost::intrusive::bstree::container_from_end_iterator(iterator) + static bs_multiset_impl &container_from_end_iterator(iterator end_iterator); + + //! @copydoc ::boost::intrusive::bstree::container_from_end_iterator(const_iterator) + static const bs_multiset_impl &container_from_end_iterator(const_iterator end_iterator); + + //! @copydoc ::boost::intrusive::bstree::container_from_iterator(iterator) + static bs_multiset_impl &container_from_iterator(iterator it); + + //! @copydoc ::boost::intrusive::bstree::container_from_iterator(const_iterator) + static const bs_multiset_impl &container_from_iterator(const_iterator it); + + //! @copydoc ::boost::intrusive::bstree::key_comp()const + key_compare key_comp() const; + + //! @copydoc ::boost::intrusive::bstree::value_comp()const + value_compare value_comp() const; + + //! @copydoc ::boost::intrusive::bstree::empty()const + bool empty() const; + + //! @copydoc ::boost::intrusive::bstree::size()const + size_type size() const; + + //! @copydoc ::boost::intrusive::bstree::swap + void swap(bs_multiset_impl& other); + + //! @copydoc ::boost::intrusive::bstree::clone_from + template + void clone_from(const bs_multiset_impl &src, Cloner cloner, Disposer disposer); + + #endif //#ifdef BOOST_iNTRUSIVE_DOXYGEN_INVOKED + + //! @copydoc ::boost::intrusive::bstree::insert_equal(reference) + iterator insert(reference value) + { return tree_type::insert_equal(value); } + + //! @copydoc ::boost::intrusive::bstree::insert_equal(const_iterator,reference) + iterator insert(const_iterator hint, reference value) + { return tree_type::insert_equal(hint, value); } + + //! @copydoc ::boost::intrusive::bstree::insert_equal(Iterator,Iterator) + template + void insert(Iterator b, Iterator e) + { tree_type::insert_equal(b, e); } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::bstree::insert_before + iterator insert_before(const_iterator pos, reference value); + + //! @copydoc ::boost::intrusive::bstree::push_back + void push_back(reference value); + + //! @copydoc ::boost::intrusive::bstree::push_front + void push_front(reference value); + + //! @copydoc ::boost::intrusive::bstree::erase(const_iterator) + iterator erase(const_iterator i); + + //! @copydoc ::boost::intrusive::bstree::erase(const_iterator,const_iterator) + iterator erase(const_iterator b, const_iterator e); + + //! @copydoc ::boost::intrusive::bstree::erase(const_reference) + size_type erase(const_reference value); + + //! @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) + template + iterator erase_and_dispose(const_iterator i, Disposer disposer); + + //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_iterator,const_iterator,Disposer) + template + iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer); + + //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_reference, Disposer) + template + size_type erase_and_dispose(const_reference value, Disposer disposer); + + //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const KeyType&,KeyValueCompare,Disposer) + template + size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer); + + //! @copydoc ::boost::intrusive::bstree::clear + void clear(); + + //! @copydoc ::boost::intrusive::bstree::clear_and_dispose + template + void clear_and_dispose(Disposer disposer); + + //! @copydoc ::boost::intrusive::bstree::count(const_reference)const + size_type count(const_reference value) const; + + //! @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); + + //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare) + template + iterator lower_bound(const KeyType& key, KeyValueCompare comp); + + //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference)const + const_iterator lower_bound(const_reference value) const; + + //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare)const + template + const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const; + + //! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference) + iterator upper_bound(const_reference value); + + //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare) + template + iterator upper_bound(const KeyType& key, KeyValueCompare comp); + + //! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference)const + const_iterator upper_bound(const_reference value) const; + + //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare)const + template + const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const; + + //! @copydoc ::boost::intrusive::bstree::find(const_reference) + iterator find(const_reference value); + + //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare) + template + iterator find(const KeyType& key, KeyValueCompare comp); + + //! @copydoc ::boost::intrusive::bstree::find(const_reference)const + const_iterator find(const_reference value) const; + + //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare)const + 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); + + //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare) + template + std::pair equal_range(const KeyType& key, KeyValueCompare comp); + + //! @copydoc ::boost::intrusive::bstree::equal_range(const_reference)const + std::pair + equal_range(const_reference value) const; + + //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare)const + template + std::pair + equal_range(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); + + //! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool) + template + std::pair bounded_range + (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed); + + //! @copydoc ::boost::intrusive::bstree::bounded_range(const_reference,const_reference,bool,bool)const + std::pair + bounded_range(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 + template + 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::s_iterator_to(reference) + static iterator s_iterator_to(reference value); + + //! @copydoc ::boost::intrusive::bstree::s_iterator_to(const_reference) + static const_iterator s_iterator_to(const_reference value); + + //! @copydoc ::boost::intrusive::bstree::iterator_to(reference) + iterator iterator_to(reference value); + + //! @copydoc ::boost::intrusive::bstree::iterator_to(const_reference)const + const_iterator iterator_to(const_reference value) const; + + //! @copydoc ::boost::intrusive::bstree::init_node(reference) + static void init_node(reference value); + + //! @copydoc ::boost::intrusive::bstree::unlink_leftmost_without_rebalance + pointer unlink_leftmost_without_rebalance(); + + //! @copydoc ::boost::intrusive::bstree::replace_node + void replace_node(iterator replace_this, reference with_this); + + //! @copydoc ::boost::intrusive::bstree::remove_node + void remove_node(reference value); + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +}; + +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + +template +bool operator!= (const bs_multiset_impl &x, const bs_multiset_impl &y); + +template +bool operator>(const bs_multiset_impl &x, const bs_multiset_impl &y); + +template +bool operator<=(const bs_multiset_impl &x, const bs_multiset_impl &y); + +template +bool operator>=(const bs_multiset_impl &x, const bs_multiset_impl &y); + +template +void swap(bs_multiset_impl &x, bs_multiset_impl &y); + +#endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + +//! Helper metafunction to define a \c bs_multiset that yields to the same type when the +//! same options (either explicitly or implicitly) are used. +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +template +#else +template +#endif +struct make_bs_multiset +{ + /// @cond + typedef typename pack_options + < bstree_defaults, + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3, O4 + #else + Options... + #endif + >::type packed_options; + + typedef typename detail::get_value_traits + ::type value_traits; + + typedef bs_multiset_impl + < value_traits + , typename packed_options::compare + , typename packed_options::size_type + , packed_options::constant_time_size + > implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + +#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +template +#else +template +#endif +class bs_multiset + : public make_bs_multiset::type +{ + typedef typename make_bs_multiset::type Base; + + BOOST_MOVABLE_BUT_NOT_COPYABLE(bs_multiset) + + public: + typedef typename Base::value_compare value_compare; + typedef typename Base::value_traits value_traits; + typedef typename Base::iterator iterator; + typedef typename Base::const_iterator const_iterator; + + //Assert if passed value traits are compatible with the type + BOOST_STATIC_ASSERT((detail::is_same::value)); + + bs_multiset( const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : Base(cmp, v_traits) + {} + + template + bs_multiset( Iterator b, Iterator e + , const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : Base(b, e, cmp, v_traits) + {} + + bs_multiset(BOOST_RV_REF(bs_multiset) x) + : Base(::boost::move(static_cast(x))) + {} + + bs_multiset& operator=(BOOST_RV_REF(bs_multiset) x) + { return static_cast(this->Base::operator=(::boost::move(static_cast(x)))); } + + static bs_multiset &container_from_end_iterator(iterator end_iterator) + { return static_cast(Base::container_from_end_iterator(end_iterator)); } + + static const bs_multiset &container_from_end_iterator(const_iterator end_iterator) + { return static_cast(Base::container_from_end_iterator(end_iterator)); } + + static bs_multiset &container_from_iterator(iterator it) + { return static_cast(Base::container_from_iterator(it)); } + + static const bs_multiset &container_from_iterator(const_iterator it) + { return static_cast(Base::container_from_iterator(it)); } +}; + +#endif + +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_BS_SET_HPP diff --git a/include/boost/intrusive/bs_set_hook.hpp b/include/boost/intrusive/bs_set_hook.hpp index 682426a..1f16971 100644 --- a/include/boost/intrusive/bs_set_hook.hpp +++ b/include/boost/intrusive/bs_set_hook.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include @@ -28,7 +28,7 @@ namespace intrusive { template struct get_bs_set_node_algo { - typedef detail::tree_algorithms > type; + typedef bstree_algorithms > type; }; /// @endcond @@ -37,7 +37,7 @@ struct get_bs_set_node_algo #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else -template +template #endif struct make_bs_set_base_hook { @@ -50,14 +50,11 @@ struct make_bs_set_base_hook #endif ::type packed_options; - //Scapegoat trees can't be auto unlink trees - BOOST_STATIC_ASSERT(((int)packed_options::link_mode != (int)auto_unlink)); - - typedef detail::generic_hook + typedef generic_hook < get_bs_set_node_algo , typename packed_options::tag , packed_options::link_mode - , detail::BsSetBaseHook + , BsTreeBaseHookId > implementation_defined; /// @endcond typedef implementation_defined type; @@ -168,7 +165,7 @@ class bs_set_base_hook #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else -template +template #endif struct make_bs_set_member_hook { @@ -182,14 +179,11 @@ struct make_bs_set_member_hook ::type packed_options; - //Scapegoat trees can't be auto unlink trees - BOOST_STATIC_ASSERT(((int)packed_options::link_mode != (int)auto_unlink)); - - typedef detail::generic_hook + typedef generic_hook < get_bs_set_node_algo , member_tag , packed_options::link_mode - , detail::NoBaseHook + , NoBaseHookId > implementation_defined; /// @endcond typedef implementation_defined type; diff --git a/include/boost/intrusive/bstree.hpp b/include/boost/intrusive/bstree.hpp new file mode 100644 index 0000000..43c4a84 --- /dev/null +++ b/include/boost/intrusive/bstree.hpp @@ -0,0 +1,2012 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2013-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_BSTREE_HPP +#define BOOST_INTRUSIVE_BSTREE_HPP + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace intrusive { + +/// @cond + +struct bstree_defaults +{ + typedef detail::default_bstree_hook proto_value_traits; + static const bool constant_time_size = true; + typedef std::size_t size_type; + typedef void compare; + static const bool floating_point = true; //For sgtree + typedef void priority; //For treap +}; + +template +struct bstbase3 + : public detail::get_real_value_traits::type::node_traits::node + , public ValueTraits +{ + typedef ValueTraits value_traits; + typedef typename detail::get_real_value_traits::type real_value_traits; + typedef typename real_value_traits::node_traits node_traits; + typedef typename node_traits::node node_type; + typedef typename get_algo::type node_algorithms; + typedef typename node_traits::node_ptr node_ptr; + typedef typename node_traits::const_node_ptr const_node_ptr; + + bstbase3(const ValueTraits &val_traits) + : ValueTraits(val_traits) + {} + + static const bool external_value_traits = + detail::external_value_traits_bool_is_true::value; + + node_ptr header_ptr() + { return pointer_traits::pointer_to(static_cast(*this)); } + + const_node_ptr header_ptr() const + { return pointer_traits::pointer_to(static_cast(*this)); } + + const value_traits &val_traits() const + { return *this; } + + value_traits &val_traits() + { return *this; } + + const real_value_traits &get_real_value_traits(detail::bool_) const + { return *this; } + + const real_value_traits &get_real_value_traits(detail::bool_) const + { return this->val_traits().get_value_traits(*this); } + + real_value_traits &get_real_value_traits(detail::bool_) + { return *this; } + + real_value_traits &get_real_value_traits(detail::bool_) + { return this->val_traits().get_value_traits(*this); } + + const real_value_traits &get_real_value_traits() const + { return this->get_real_value_traits(detail::bool_()); } + + real_value_traits &get_real_value_traits() + { return this->get_real_value_traits(detail::bool_()); } + + typedef typename pointer_traits::template rebind_pointer::type const_real_value_traits_ptr; + + const_real_value_traits_ptr real_value_traits_ptr() const + { return pointer_traits::pointer_to(this->get_real_value_traits()); } + + + typedef tree_iterator iterator; + typedef tree_iterator const_iterator; + typedef boost::intrusive::detail::reverse_iterator reverse_iterator; + typedef boost::intrusive::detail::reverse_iterator const_reverse_iterator; + typedef BOOST_INTRUSIVE_IMPDEF(typename real_value_traits::pointer) pointer; + typedef BOOST_INTRUSIVE_IMPDEF(typename real_value_traits::const_pointer) const_pointer; + typedef BOOST_INTRUSIVE_IMPDEF(typename pointer_traits::element_type) value_type; + typedef BOOST_INTRUSIVE_IMPDEF(value_type) key_type; + typedef BOOST_INTRUSIVE_IMPDEF(typename pointer_traits::reference) reference; + typedef BOOST_INTRUSIVE_IMPDEF(typename pointer_traits::reference) const_reference; + typedef BOOST_INTRUSIVE_IMPDEF(typename pointer_traits::difference_type) difference_type; + static const bool safemode_or_autounlink = is_safe_autounlink::value; + static const bool stateful_value_traits = detail::is_stateful_value_traits::value; + + iterator begin() + { return iterator (node_traits::get_left(this->header_ptr()), this->real_value_traits_ptr()); } + + const_iterator begin() const + { return cbegin(); } + + const_iterator cbegin() const + { return const_iterator (node_traits::get_left(this->header_ptr()), this->real_value_traits_ptr()); } + + iterator end() + { return iterator (this->header_ptr(), this->real_value_traits_ptr()); } + + const_iterator end() const + { return cend(); } + + const_iterator cend() const + { return const_iterator (detail::uncast(this->header_ptr()), this->real_value_traits_ptr()); } + + reverse_iterator rbegin() + { return reverse_iterator(end()); } + + const_reverse_iterator rbegin() const + { return const_reverse_iterator(end()); } + + const_reverse_iterator crbegin() const + { return const_reverse_iterator(end()); } + + reverse_iterator rend() + { return reverse_iterator(begin()); } + + const_reverse_iterator rend() const + { return const_reverse_iterator(begin()); } + + const_reverse_iterator crend() const + { return const_reverse_iterator(begin()); } + + void replace_node(iterator replace_this, reference with_this) + { + node_algorithms::replace_node( get_real_value_traits().to_node_ptr(*replace_this) + , this->header_ptr() + , get_real_value_traits().to_node_ptr(with_this)); + if(safemode_or_autounlink) + node_algorithms::init(replace_this.pointed_node()); + } + + void rebalance() + { node_algorithms::rebalance(this->header_ptr()); } + + iterator rebalance_subtree(iterator root) + { return iterator(node_algorithms::rebalance_subtree(root.pointed_node()), this->real_value_traits_ptr()); } + + static iterator s_iterator_to(reference value) + { + BOOST_STATIC_ASSERT((!stateful_value_traits)); + return iterator (value_traits::to_node_ptr(value), const_real_value_traits_ptr()); + } + + static const_iterator s_iterator_to(const_reference value) + { + BOOST_STATIC_ASSERT((!stateful_value_traits)); + return const_iterator (value_traits::to_node_ptr(const_cast (value)), const_real_value_traits_ptr()); + } + + iterator iterator_to(reference value) + { return iterator (value_traits::to_node_ptr(value), this->real_value_traits_ptr()); } + + const_iterator iterator_to(const_reference value) const + { return const_iterator (value_traits::to_node_ptr(const_cast (value)), this->real_value_traits_ptr()); } + + static void init_node(reference value) + { node_algorithms::init(value_traits::to_node_ptr(value)); } + +}; + +template +struct bstbase2 + : public bstbase3 + , public detail::ebo_functor_holder::type::value_type + >::type> +{ + typedef bstbase3 treeheader_t; + typedef typename treeheader_t::real_value_traits real_value_traits; + typedef typename treeheader_t::node_algorithms node_algorithms; + typedef typename get_less + < VoidOrKeyComp, typename real_value_traits::value_type>::type value_compare; + typedef BOOST_INTRUSIVE_IMPDEF(value_compare) key_compare; + typedef typename treeheader_t::iterator iterator; + typedef typename treeheader_t::const_iterator const_iterator; + typedef typename treeheader_t::node_ptr node_ptr; + typedef typename treeheader_t::const_node_ptr const_node_ptr; + + bstbase2(const value_compare &comp, const ValueTraits &val_traits) + : treeheader_t(val_traits), detail::ebo_functor_holder(comp) + {} + + const value_compare &comp() const + { return this->get(); } + + value_compare &comp() + { return this->get(); } + + typedef BOOST_INTRUSIVE_IMPDEF(typename real_value_traits::pointer) pointer; + typedef BOOST_INTRUSIVE_IMPDEF(typename real_value_traits::const_pointer) const_pointer; + typedef BOOST_INTRUSIVE_IMPDEF(typename pointer_traits::element_type) value_type; + typedef BOOST_INTRUSIVE_IMPDEF(value_type) key_type; + typedef BOOST_INTRUSIVE_IMPDEF(typename pointer_traits::reference) reference; + typedef BOOST_INTRUSIVE_IMPDEF(typename pointer_traits::reference) const_reference; + typedef BOOST_INTRUSIVE_IMPDEF(typename pointer_traits::difference_type) difference_type; + typedef typename node_algorithms::insert_commit_data insert_commit_data; + + value_compare value_comp() const + { return this->comp(); } + + key_compare key_comp() const + { return this->comp(); } + + iterator lower_bound(const_reference value) + { return this->lower_bound(value, this->comp()); } + + const_iterator lower_bound(const_reference value) const + { return this->lower_bound(value, this->comp()); } + + template + iterator lower_bound(const KeyType &key, KeyValueCompare comp) + { + detail::key_nodeptr_comp + key_node_comp(comp, &this->get_real_value_traits()); + return iterator(node_algorithms::lower_bound + (this->header_ptr(), key, key_node_comp), this->real_value_traits_ptr()); + } + + template + const_iterator lower_bound(const KeyType &key, KeyValueCompare comp) const + { + detail::key_nodeptr_comp + key_node_comp(comp, &this->get_real_value_traits()); + return const_iterator(node_algorithms::lower_bound + (this->header_ptr(), key, key_node_comp), this->real_value_traits_ptr()); + } + + iterator upper_bound(const_reference value) + { return this->upper_bound(value, this->comp()); } + + template + iterator upper_bound(const KeyType &key, KeyValueCompare comp) + { + detail::key_nodeptr_comp + key_node_comp(comp, &this->get_real_value_traits()); + return iterator(node_algorithms::upper_bound + (this->header_ptr(), key, key_node_comp), this->real_value_traits_ptr()); + } + + const_iterator upper_bound(const_reference value) const + { return this->upper_bound(value, this->comp()); } + + template + const_iterator upper_bound(const KeyType &key, KeyValueCompare comp) const + { + detail::key_nodeptr_comp + key_node_comp(comp, &this->get_real_value_traits()); + return const_iterator(node_algorithms::upper_bound + (this->header_ptr(), key, key_node_comp), this->real_value_traits_ptr()); + } + + iterator find(const_reference value) + { return this->find(value, this->comp()); } + + template + iterator find(const KeyType &key, KeyValueCompare comp) + { + detail::key_nodeptr_comp + key_node_comp(comp, &this->get_real_value_traits()); + return iterator + (node_algorithms::find(this->header_ptr(), key, key_node_comp), this->real_value_traits_ptr()); + } + + const_iterator find(const_reference value) const + { return this->find(value, this->comp()); } + + template + const_iterator find(const KeyType &key, KeyValueCompare comp) const + { + detail::key_nodeptr_comp + key_node_comp(comp, &this->get_real_value_traits()); + return const_iterator + (node_algorithms::find(this->header_ptr(), key, key_node_comp), this->real_value_traits_ptr()); + } + + std::pair equal_range(const_reference value) + { return this->equal_range(value, this->comp()); } + + template + std::pair equal_range(const KeyType &key, KeyValueCompare comp) + { + detail::key_nodeptr_comp + key_node_comp(comp, &this->get_real_value_traits()); + std::pair ret + (node_algorithms::equal_range(this->header_ptr(), key, key_node_comp)); + return std::pair( iterator(ret.first, this->real_value_traits_ptr()) + , iterator(ret.second, this->real_value_traits_ptr())); + } + + std::pair + equal_range(const_reference value) const + { return this->equal_range(value, this->comp()); } + + template + std::pair + equal_range(const KeyType &key, KeyValueCompare comp) const + { + detail::key_nodeptr_comp + key_node_comp(comp, &this->get_real_value_traits()); + std::pair ret + (node_algorithms::equal_range(this->header_ptr(), key, key_node_comp)); + return std::pair( const_iterator(ret.first, this->real_value_traits_ptr()) + , const_iterator(ret.second, this->real_value_traits_ptr())); + } + + std::pair bounded_range + (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) + { return this->bounded_range(lower_value, upper_value, this->comp(), left_closed, right_closed); } + + template + std::pair bounded_range + (const KeyType &lower_key, const KeyType &upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) + { + detail::key_nodeptr_comp + key_node_comp(comp, &this->get_real_value_traits()); + std::pair ret + (node_algorithms::bounded_range + (this->header_ptr(), lower_key, upper_key, key_node_comp, left_closed, right_closed)); + return std::pair( iterator(ret.first, this->real_value_traits_ptr()) + , iterator(ret.second, this->real_value_traits_ptr())); + } + + std::pair bounded_range + (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const + { return this->bounded_range(lower_value, upper_value, this->comp(), left_closed, right_closed); } + + template + std::pair bounded_range + (const KeyType &lower_key, const KeyType &upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const + { + detail::key_nodeptr_comp + key_node_comp(comp, &this->get_real_value_traits()); + std::pair ret + (node_algorithms::bounded_range + (this->header_ptr(), lower_key, upper_key, key_node_comp, left_closed, right_closed)); + return std::pair( const_iterator(ret.first, this->real_value_traits_ptr()) + , const_iterator(ret.second, this->real_value_traits_ptr())); + } + + template + 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()); + std::pair ret = + (node_algorithms::insert_unique_check + (this->header_ptr(), key, comp, commit_data)); + return std::pair(iterator(ret.first, this->real_value_traits_ptr()), ret.second); + } + + template + std::pair insert_unique_check + (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()); + std::pair ret = + (node_algorithms::insert_unique_check + (this->header_ptr(), hint.pointed_node(), key, comp, commit_data)); + return std::pair(iterator(ret.first, this->real_value_traits_ptr()), ret.second); + } +}; + +template +struct bstbase + : public detail::size_holder + , public bstbase2 < ValueTraits, VoidOrKeyComp, AlgoType> +{ + typedef typename detail::get_real_value_traits::type real_value_traits; + typedef bstbase2< ValueTraits, VoidOrKeyComp, AlgoType> base_type; + typedef typename base_type::value_compare value_compare; + typedef BOOST_INTRUSIVE_IMPDEF(value_compare) key_compare; + typedef typename base_type::const_reference const_reference; + typedef typename base_type::reference reference; + typedef typename base_type::iterator iterator; + typedef typename base_type::const_iterator const_iterator; + typedef typename base_type::node_traits node_traits; + typedef typename get_algo + ::type algo_type; + typedef SizeType size_type; + + bstbase(const value_compare & comp, const ValueTraits &val_traits) + : base_type(comp, val_traits) + {} + + public: + typedef detail::size_holder size_traits; + + size_traits &sz_traits() + { return *this; } + + const size_traits &sz_traits() const + { return *this; } + + size_type count(const_reference value) const + { return size_type(this->count(value, this->comp())); } + + template + size_type count(const KeyType &key, KeyValueCompare comp) const + { + std::pair ret = this->equal_range(key, comp); + return size_type(std::distance(ret.first, ret.second)); + } + + bool empty() const + { + if(ConstantTimeSize){ + return !this->sz_traits().get_size(); + } + else{ + return algo_type::unique(this->header_ptr()); + } + } +}; + + +/// @endcond + +//! The class template bstree is an unbalanced intrusive binary search tree +//! container. The no-throw guarantee holds only, if the value_compare object +//! doesn't throw. +//! +//! The complexity guarantees only hold if the tree is balanced, logarithmic +//! complexity would increase to linear if the tree is totally unbalanced. +//! +//! The template parameter \c T is the type to be managed by the container. +//! The user can specify additional options and if no options are provided +//! default options are used. +//! +//! The container supports the following options: +//! \c base_hook<>/member_hook<>/value_traits<>, +//! \c constant_time_size<>, \c size_type<> and +//! \c compare<>. +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) +template +#else +template +#endif +class bstree_impl + : public bstbase + , private detail::clear_on_destructor_base > +{ + template friend class detail::clear_on_destructor_base; + public: + typedef ValueTraits value_traits; + /// @cond + static const bool external_value_traits = + detail::external_value_traits_bool_is_true::value; + typedef typename detail::get_real_value_traits::type real_value_traits; + typedef bstbase data_type; + typedef tree_iterator iterator_type; + typedef tree_iterator const_iterator_type; + /// @endcond + + typedef BOOST_INTRUSIVE_IMPDEF(typename real_value_traits::pointer) pointer; + typedef BOOST_INTRUSIVE_IMPDEF(typename real_value_traits::const_pointer) const_pointer; + typedef BOOST_INTRUSIVE_IMPDEF(typename pointer_traits::element_type) value_type; + typedef BOOST_INTRUSIVE_IMPDEF(value_type) key_type; + typedef BOOST_INTRUSIVE_IMPDEF(typename pointer_traits::reference) reference; + typedef BOOST_INTRUSIVE_IMPDEF(typename pointer_traits::reference) const_reference; + typedef BOOST_INTRUSIVE_IMPDEF(typename pointer_traits::difference_type) difference_type; + typedef BOOST_INTRUSIVE_IMPDEF(SizeType) size_type; + typedef BOOST_INTRUSIVE_IMPDEF(typename data_type::value_compare) value_compare; + typedef BOOST_INTRUSIVE_IMPDEF(value_compare) key_compare; + typedef BOOST_INTRUSIVE_IMPDEF(iterator_type) iterator; + typedef BOOST_INTRUSIVE_IMPDEF(const_iterator_type) const_iterator; + typedef BOOST_INTRUSIVE_IMPDEF(boost::intrusive::detail::reverse_iterator) reverse_iterator; + typedef BOOST_INTRUSIVE_IMPDEF(boost::intrusive::detail::reverse_iterator) const_reverse_iterator; + typedef BOOST_INTRUSIVE_IMPDEF(typename real_value_traits::node_traits) node_traits; + typedef BOOST_INTRUSIVE_IMPDEF(typename node_traits::node) node; + typedef BOOST_INTRUSIVE_IMPDEF(typename node_traits::node_ptr) node_ptr; + typedef BOOST_INTRUSIVE_IMPDEF(typename node_traits::const_node_ptr) const_node_ptr; + /// @cond + typedef typename get_algo::type algo_type; + /// @endcond + typedef BOOST_INTRUSIVE_IMPDEF(algo_type) node_algorithms; + + static const bool constant_time_size = ConstantTimeSize; + static const bool stateful_value_traits = detail::is_stateful_value_traits::value; + /// @cond + private: + + //noncopyable + BOOST_MOVABLE_BUT_NOT_COPYABLE(bstree_impl) + + 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))); + + + protected: + + + /// @endcond + + public: + + typedef typename node_algorithms::insert_commit_data insert_commit_data; + + //! Effects: Constructs an empty container. + //! + //! Complexity: Constant. + //! + //! Throws: If value_traits::node_traits::node + //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) + //! or the copy constructorof the value_compare object throws. Basic guarantee. + explicit bstree_impl( const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : data_type(cmp, v_traits) + { + node_algorithms::init_header(this->header_ptr()); + this->sz_traits().set_size(size_type(0)); + } + + //! Requires: Dereferencing iterator must yield an lvalue of type value_type. + //! cmp must be a comparison function that induces a strict weak ordering. + //! + //! Effects: Constructs an empty container and inserts elements from + //! [b, e). + //! + //! Complexity: Linear in N if [b, e) is already sorted using + //! comp and otherwise N * log N, where N is the distance between first and last. + //! + //! Throws: If value_traits::node_traits::node + //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) + //! or the copy constructor/operator() of the value_compare object throws. Basic guarantee. + template + bstree_impl( bool unique, Iterator b, Iterator e + , const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : data_type(cmp, v_traits) + { + node_algorithms::init_header(this->header_ptr()); + this->sz_traits().set_size(size_type(0)); + if(unique) + this->insert_unique(b, e); + else + this->insert_equal(b, e); + } + + //! Effects: to-do + //! + bstree_impl(BOOST_RV_REF(bstree_impl) x) + : data_type(::boost::move(x.comp()), ::boost::move(x.val_traits())) + { + node_algorithms::init_header(this->header_ptr()); + this->sz_traits().set_size(size_type(0)); + this->swap(x); + } + + //! Effects: to-do + //! + bstree_impl& operator=(BOOST_RV_REF(bstree_impl) x) + { this->swap(x); return *this; } + + //! Effects: Detaches all elements from this. The objects in the set + //! are not deleted (i.e. no destructors are called), but the nodes according to + //! the value_traits template parameter are reinitialized and thus can be reused. + //! + //! Complexity: Linear to elements contained in *this. + //! + //! Throws: Nothing. + ~bstree_impl() + {} + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + + //! Effects: Returns an iterator pointing to the beginning of the container. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator begin(); + + //! Effects: Returns a const_iterator pointing to the beginning of the container. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator begin() const; + + //! Effects: Returns a const_iterator pointing to the beginning of the container. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator cbegin() const; + + //! Effects: Returns an iterator pointing to the end of the container. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator end(); + + //! Effects: Returns a const_iterator pointing to the end of the container. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator end() const; + + //! Effects: Returns a const_iterator pointing to the end of the container. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator cend() const; + + //! Effects: Returns a reverse_iterator pointing to the beginning of the + //! reversed container. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + reverse_iterator rbegin(); + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed container. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator rbegin() const; + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed container. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator crbegin() const; + + //! Effects: Returns a reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + reverse_iterator rend(); + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator rend() const; + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator crend() const; + + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + + //! Precondition: end_iterator must be a valid end iterator + //! of the container. + //! + //! Effects: Returns a const reference to the container associated to the end iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + static bstree_impl &container_from_end_iterator(iterator end_iterator) + { + return *static_cast + (boost::intrusive::detail::to_raw_pointer(end_iterator.pointed_node())); + } + + //! Precondition: end_iterator must be a valid end const_iterator + //! of the container. + //! + //! Effects: Returns a const reference to the container associated to the iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + static const bstree_impl &container_from_end_iterator(const_iterator end_iterator) + { + return *static_cast + (boost::intrusive::detail::to_raw_pointer(end_iterator.pointed_node())); + } + + //! Precondition: it must be a valid iterator + //! of the container. + //! + //! Effects: Returns a const reference to the container associated to the iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Logarithmic. + static bstree_impl &container_from_iterator(iterator it) + { return container_from_end_iterator(it.end_iterator_from_it()); } + + //! Precondition: it must be a valid end const_iterator + //! of container. + //! + //! Effects: Returns a const reference to the container associated to the end iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Logarithmic. + static const bstree_impl &container_from_iterator(const_iterator it) + { return container_from_end_iterator(it.end_iterator_from_it()); } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + + //! Effects: Returns the key_compare object used by the container. + //! + //! Complexity: Constant. + //! + //! Throws: If value_compare copy-constructor throws. + key_compare key_comp() const; + + //! Effects: Returns the value_compare object used by the container. + //! + //! Complexity: Constant. + //! + //! Throws: If value_compare copy-constructor throws. + value_compare value_comp() const; + + //! Effects: Returns true if the container is empty. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + bool empty() const; + + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + + //! Effects: Returns the number of elements stored in the container. + //! + //! Complexity: Linear to elements contained in *this + //! if constant-time size option is disabled. Constant time otherwise. + //! + //! Throws: Nothing. + size_type size() const + { + if(constant_time_size) + return this->sz_traits().get_size(); + else{ + return (size_type)node_algorithms::size(this->header_ptr()); + } + } + + //! Effects: Swaps the contents of two containers. + //! + //! Complexity: Constant. + //! + //! Throws: If the comparison functor's swap call throws. + void swap(bstree_impl& other) + { + //This can throw + using std::swap; + swap(this->comp(), this->comp()); + //These can't throw + node_algorithms::swap_tree(this->header_ptr(), node_ptr(other.header_ptr())); + if(constant_time_size){ + size_type backup = this->sz_traits().get_size(); + this->sz_traits().set_size(other.sz_traits().get_size()); + other.sz_traits().set_size(backup); + } + } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! Cloner should yield to nodes equivalent to the original nodes. + //! + //! Effects: Erases all the elements from *this + //! calling Disposer::operator()(pointer), clones all the + //! elements from src calling Cloner::operator()(const_reference ) + //! and inserts them on *this. Copies the predicate from the source container. + //! + //! If cloner throws, all cloned elements are unlinked and disposed + //! calling Disposer::operator()(pointer). + //! + //! Complexity: Linear to erased plus inserted elements. + //! + //! Throws: If cloner throws or predicate copy assignment throws. Basic guarantee. + template + void clone_from(const bstree_impl &src, Cloner cloner, Disposer disposer) + { + this->clear_and_dispose(disposer); + if(!src.empty()){ + detail::exception_disposer + rollback(*this, disposer); + node_algorithms::clone + (const_node_ptr(src.header_ptr()) + ,node_ptr(this->header_ptr()) + ,detail::node_cloner (cloner, &this->get_real_value_traits()) + ,detail::node_disposer(disposer, &this->get_real_value_traits())); + this->sz_traits().set_size(src.sz_traits().get_size()); + this->comp() = src.comp(); + rollback.release(); + } + } + + //! Requires: value must be an lvalue + //! + //! Effects: Inserts value into the container before the upper bound. + //! + //! Complexity: Average complexity for insert element is at + //! most logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. Strong guarantee. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + iterator insert_equal(reference value) + { + detail::key_nodeptr_comp + key_node_comp(this->comp(), &this->get_real_value_traits()); + node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + iterator ret(node_algorithms::insert_equal_upper_bound + (this->header_ptr(), to_insert, key_node_comp), this->real_value_traits_ptr()); + this->sz_traits().increment(); + return ret; + } + + //! Requires: value must be an lvalue, and "hint" must be + //! a valid iterator. + //! + //! Effects: Inserts x into the container, using "hint" as a hint to + //! where it will be inserted. If "hint" is the upper_bound + //! the insertion takes constant time (two comparisons in the worst case) + //! + //! Complexity: Logarithmic in general, but it is amortized + //! constant time if t is inserted immediately before hint. + //! + //! Throws: If the internal value_compare ordering function throws. Strong guarantee. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + iterator insert_equal(const_iterator hint, reference value) + { + detail::key_nodeptr_comp + key_node_comp(this->comp(), &this->get_real_value_traits()); + node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + iterator ret(node_algorithms::insert_equal + (this->header_ptr(), hint.pointed_node(), to_insert, key_node_comp), this->real_value_traits_ptr()); + this->sz_traits().increment(); + return ret; + } + + //! Requires: Dereferencing iterator must yield an lvalue + //! of type value_type. + //! + //! Effects: Inserts a each element of a range into the container + //! before the upper bound of the key of each element. + //! + //! Complexity: Insert range is in general O(N * log(N)), where N is the + //! size of the range. However, it is linear in N if the range is already sorted + //! by value_comp(). + //! + //! Throws: Nothing. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + template + void insert_equal(Iterator b, Iterator e) + { + iterator iend(this->end()); + for (; b != e; ++b) + this->insert_equal(iend, *b); + } + + //! Requires: value must be an lvalue + //! + //! Effects: Inserts value into the container if the value + //! is not already present. + //! + //! Complexity: Average complexity for insert element is at + //! most logarithmic. + //! + //! Throws: Nothing. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + std::pair insert_unique(reference value) + { + insert_commit_data commit_data; + std::pair ret = this->insert_unique_check(value, this->comp(), commit_data); + if(!ret.second) + return ret; + return std::pair (this->insert_unique_commit(value, commit_data), true); + } + + //! Requires: value must be an lvalue, and "hint" must be + //! a valid iterator + //! + //! Effects: Tries to insert x into the container, using "hint" as a hint + //! to where it will be inserted. + //! + //! Complexity: Logarithmic in general, but it is amortized + //! constant time (two comparisons in the worst case) + //! if t is inserted immediately before hint. + //! + //! Throws: Nothing. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + iterator insert_unique(const_iterator hint, reference value) + { + insert_commit_data commit_data; + std::pair ret = this->insert_unique_check(hint, value, this->comp(), commit_data); + if(!ret.second) + return ret.first; + return this->insert_unique_commit(value, commit_data); + } + + //! Requires: Dereferencing iterator must yield an lvalue + //! of type value_type. + //! + //! Effects: Tries to insert each element of a range into the container. + //! + //! Complexity: Insert range is in general O(N * log(N)), where N is the + //! size of the range. However, it is linear in N if the range is already sorted + //! by value_comp(). + //! + //! Throws: Nothing. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + template + void insert_unique(Iterator b, Iterator e) + { + if(this->empty()){ + iterator iend(this->end()); + for (; b != e; ++b) + this->insert_unique(iend, *b); + } + else{ + for (; b != e; ++b) + this->insert_unique(*b); + } + } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + + //! Requires: key_value_comp must be a comparison function that induces + //! the same strict weak ordering as value_compare. The difference is that + //! key_value_comp compares an arbitrary key with the contained values. + //! + //! Effects: Checks if a value can be inserted in the container, using + //! a user provided key instead of the value itself. + //! + //! Returns: If there is an equivalent value + //! returns a pair containing an iterator to the already present value + //! and false. If the value can be inserted returns true in the returned + //! pair boolean and fills "commit_data" that is meant to be used with + //! the "insert_commit" function. + //! + //! Complexity: Average complexity is at most logarithmic. + //! + //! Throws: If the key_value_comp ordering function throws. Strong guarantee. + //! + //! Notes: This function is used to improve performance when constructing + //! a value_type is expensive: if there is an equivalent value + //! the constructed object must be discarded. Many times, the part of the + //! node that is used to impose the order is much cheaper to construct + //! than the value_type and this function offers the possibility to use that + //! part to check if the insertion will be successful. + //! + //! If the check is successful, the user can construct the value_type and use + //! "insert_commit" to insert the object in constant-time. This gives a total + //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)). + //! + //! "commit_data" remains valid for a subsequent "insert_commit" only if no more + //! objects are inserted or erased from the container. + template + std::pair insert_unique_check + (const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data); + + //! Requires: key_value_comp must be a comparison function that induces + //! the same strict weak ordering as value_compare. The difference is that + //! key_value_comp compares an arbitrary key with the contained values. + //! + //! Effects: Checks if a value can be inserted in the container, using + //! a user provided key instead of the value itself, using "hint" + //! as a hint to where it will be inserted. + //! + //! Returns: If there is an equivalent value + //! returns a pair containing an iterator to the already present value + //! and false. If the value can be inserted returns true in the returned + //! pair boolean and fills "commit_data" that is meant to be used with + //! the "insert_commit" function. + //! + //! Complexity: Logarithmic in general, but it's amortized + //! constant time if t is inserted immediately before hint. + //! + //! Throws: If the key_value_comp ordering function throws. Strong guarantee. + //! + //! Notes: This function is used to improve performance when constructing + //! a value_type is expensive: if there is an equivalent value + //! the constructed object must be discarded. Many times, the part of the + //! constructing that is used to impose the order is much cheaper to construct + //! than the value_type and this function offers the possibility to use that key + //! to check if the insertion will be successful. + //! + //! If the check is successful, the user can construct the value_type and use + //! "insert_commit" to insert the object in constant-time. This can give a total + //! constant-time complexity to the insertion: check(O(1)) + commit(O(1)). + //! + //! "commit_data" remains valid for a subsequent "insert_commit" only if no more + //! objects are inserted or erased from the container. + template + std::pair insert_unique_check + (const_iterator hint, const KeyType &key + ,KeyValueCompare key_value_comp, insert_commit_data &commit_data); + + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + + //! Requires: value must be an lvalue of type value_type. commit_data + //! must have been obtained from a previous call to "insert_check". + //! No objects should have been inserted or erased from the container between + //! the "insert_check" that filled "commit_data" and the call to "insert_commit". + //! + //! Effects: Inserts the value in the container using the information obtained + //! from the "commit_data" that a previous "insert_check" filled. + //! + //! Returns: An iterator to the newly inserted object. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Notes: This function has only sense if a "insert_check" has been + //! previously executed to fill "commit_data". No value should be inserted or + //! 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)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + node_algorithms::insert_unique_commit + (this->header_ptr(), to_insert, commit_data); + this->sz_traits().increment(); + return iterator(to_insert, this->real_value_traits_ptr()); + } + + //! Requires: value must be an lvalue, "pos" must be + //! a valid iterator (or end) and must be the succesor of value + //! once inserted according to the predicate + //! + //! Effects: Inserts x into the container before "pos". + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if "pos" is not + //! the successor of "value" container ordering invariant will be broken. + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + iterator insert_before(const_iterator pos, reference value) + { + node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + this->sz_traits().increment(); + return iterator(node_algorithms::insert_before + (this->header_ptr(), pos.pointed_node(), to_insert), this->real_value_traits_ptr()); + } + + //! Requires: value must be an lvalue, and it must be no less + //! than the greatest inserted key + //! + //! Effects: Inserts x into the container in the last position. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if value is + //! less than the greatest inserted key container ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_back(reference value) + { + node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + this->sz_traits().increment(); + node_algorithms::push_back(this->header_ptr(), to_insert); + } + + //! Requires: value must be an lvalue, and it must be no greater + //! than the minimum inserted key + //! + //! Effects: Inserts x into the container in the first position. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if value is + //! greater than the minimum inserted key container ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_front(reference value) + { + node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + this->sz_traits().increment(); + node_algorithms::push_front(this->header_ptr(), to_insert); + } + + //! Effects: Erases the element pointed to by pos. + //! + //! Complexity: Average complexity for erase element is constant time. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + iterator erase(const_iterator i) + { + const_iterator ret(i); + ++ret; + node_ptr to_erase(i.pointed_node()); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!node_algorithms::unique(to_erase)); + node_algorithms::erase(this->header_ptr(), to_erase); + this->sz_traits().decrement(); + if(safemode_or_autounlink) + node_algorithms::init(to_erase); + return ret.unconst(); + } + + //! Effects: Erases the range pointed to by b end e. + //! + //! Complexity: Average complexity for erase range is at most + //! O(log(size() + N)), where N is the number of elements in the range. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + iterator erase(const_iterator b, const_iterator e) + { size_type n; return this->private_erase(b, e, n); } + + //! Effects: Erases all the elements with the given value. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: O(log(size() + N). + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + size_type erase(const_reference value) + { return this->erase(value, this->comp()); } + + //! Effects: Erases all the elements with the given key. + //! according to the comparison functor "comp". + //! + //! Returns: The number of erased elements. + //! + //! Complexity: O(log(size() + N). + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + size_type erase(const KeyType& key, KeyValueCompare comp + /// @cond + , typename detail::enable_if_c::value >::type * = 0 + /// @endcond + ) + { + std::pair p = this->equal_range(key, comp); + size_type n; + this->private_erase(p.first, p.second, n); + return n; + } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases the element pointed to by pos. + //! Disposer::operator()(pointer) is called for the removed element. + //! + //! Complexity: Average complexity for erase element is constant time. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + iterator erase_and_dispose(const_iterator i, Disposer disposer) + { + node_ptr to_erase(i.pointed_node()); + iterator ret(this->erase(i)); + disposer(this->get_real_value_traits().to_value_ptr(to_erase)); + return ret; + } + + #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + template + iterator erase_and_dispose(iterator i, Disposer disposer) + { return this->erase_and_dispose(const_iterator(i), disposer); } + #endif + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements with the given value. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: O(log(size() + N). + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + size_type erase_and_dispose(const_reference value, Disposer disposer) + { + std::pair p = this->equal_range(value); + size_type n; + this->private_erase(p.first, p.second, n, disposer); + return n; + } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases the range pointed to by b end e. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Complexity: Average complexity for erase range is at most + //! O(log(size() + N)), where N is the number of elements in the range. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer) + { size_type n; return this->private_erase(b, e, n, disposer); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements with the given key. + //! according to the comparison functor "comp". + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: O(log(size() + N). + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer + /// @cond + , typename detail::enable_if_c::value >::type * = 0 + /// @endcond + ) + { + std::pair p = this->equal_range(key, comp); + size_type n; + this->private_erase(p.first, p.second, n, disposer); + return n; + } + + //! Effects: Erases all of the elements. + //! + //! Complexity: Linear to the number of elements on the container. + //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + void clear() + { + if(safemode_or_autounlink){ + this->clear_and_dispose(detail::null_disposer()); + } + else{ + node_algorithms::init_header(this->header_ptr()); + this->sz_traits().set_size(0); + } + } + + //! Effects: Erases all of the elements calling disposer(p) for + //! each node to be erased. + //! Complexity: Average complexity for is at most O(log(size() + N)), + //! where N is the number of elements in the container. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. Calls N times to disposer functor. + template + void clear_and_dispose(Disposer disposer) + { + node_algorithms::clear_and_dispose(this->header_ptr() + , detail::node_disposer(disposer, &this->get_real_value_traits())); + node_algorithms::init_header(this->header_ptr()); + this->sz_traits().set_size(0); + } + + #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + + //! Effects: Returns the number of contained elements with the given value + //! + //! Complexity: Logarithmic to the number of elements contained plus lineal + //! to number of objects with the given value. + //! + //! Throws: Nothing. + size_type count(const_reference value) const; + + //! Effects: Returns the number of contained elements with the given key + //! + //! Complexity: Logarithmic to the number of elements contained plus lineal + //! to number of objects with the given key. + //! + //! Throws: Nothing. + template + size_type count(const KeyType &key, KeyValueCompare comp) const; + + //! Effects: Returns an iterator to the first element whose + //! key is not less than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + iterator lower_bound(const_reference value); + + //! Effects: Returns an iterator to the first element whose + //! key is not less than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + const_iterator lower_bound(const_reference value) const; + + //! Effects: Returns an iterator to the first element whose + //! key is not less than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + template + iterator lower_bound(const KeyType &key, KeyValueCompare comp); + + //! Effects: Returns a const iterator to the first element whose + //! key is not less than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + template + const_iterator lower_bound(const KeyType &key, KeyValueCompare comp) const; + + //! Effects: Returns an iterator to the first element whose + //! key is greater than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + iterator upper_bound(const_reference value); + + //! Effects: Returns an iterator to the first element whose + //! key is greater than k according to comp or end() if that element + //! does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + template + iterator upper_bound(const KeyType &key, KeyValueCompare comp); + + //! Effects: Returns an iterator to the first element whose + //! key is greater than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + const_iterator upper_bound(const_reference value) const; + + //! Effects: Returns an iterator to the first element whose + //! key is greater than k according to comp or end() if that element + //! does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + template + const_iterator upper_bound(const KeyType &key, KeyValueCompare comp) const; + + //! Effects: Finds an iterator to the first element whose key is + //! k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + iterator find(const_reference value); + + //! Effects: Finds an iterator to the first element whose key is + //! k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + template + iterator find(const KeyType &key, KeyValueCompare comp); + + //! Effects: Finds a const_iterator to the first element whose key is + //! k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + const_iterator find(const_reference value) const; + + //! Effects: Finds a const_iterator to the first element whose key is + //! k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + template + const_iterator find(const KeyType &key, KeyValueCompare comp) const; + + //! Effects: Finds a range containing all elements whose key is k or + //! an empty range that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + std::pair equal_range(const_reference value); + + //! Effects: Finds a range containing all elements whose key is k or + //! an empty range that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + template + std::pair equal_range(const KeyType &key, KeyValueCompare comp); + + //! Effects: Finds a range containing all elements whose key is k or + //! an empty range that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + std::pair + equal_range(const_reference value) const; + + //! Effects: Finds a range containing all elements whose key is k or + //! an empty range that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + template + std::pair + equal_range(const KeyType &key, KeyValueCompare comp) const; + + //! Requires: 'lower_value' must not be greater than 'upper_value'. If + //! 'lower_value' == 'upper_value', ('left_closed' || 'right_closed') must be false. + //! + //! Effects: Returns an a pair with the following criteria: + //! + //! first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise + //! + //! second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the predicate throws. + //! + //! Note: This function can be more efficient than calling upper_bound + //! and lower_bound for lower_value and upper_value. + //! + //! Note: Experimental function, the interface might change in future releases. + std::pair bounded_range + (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); + + //! Requires: KeyValueCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the container. + //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If + //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. + //! + //! Effects: Returns an a pair with the following criteria: + //! + //! first = lower_bound(lower_key, comp) if left_closed, upper_bound(lower_key, comp) otherwise + //! + //! second = upper_bound(upper_key, comp) if right_closed, lower_bound(upper_key, comp) otherwise + //! + //! Complexity: Logarithmic. + //! + //! Throws: If "comp" throws. + //! + //! Note: This function can be more efficient than calling upper_bound + //! and lower_bound for lower_key and upper_key. + //! + //! Note: Experimental function, the interface might change in future releases. + template + std::pair bounded_range + (const KeyType &lower_key, const KeyType &upper_key, KeyValueCompare comp, bool left_closed, bool right_closed); + + //! Requires: 'lower_value' must not be greater than 'upper_value'. If + //! 'lower_value' == 'upper_value', ('left_closed' || 'right_closed') must be false. + //! + //! Effects: Returns an a pair with the following criteria: + //! + //! first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise + //! + //! second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the predicate throws. + //! + //! Note: This function can be more efficient than calling upper_bound + //! and lower_bound for lower_value and upper_value. + //! + //! Note: Experimental function, the interface might change in future releases. + std::pair bounded_range + (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; + + //! Requires: KeyValueCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the container. + //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If + //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. + //! + //! Effects: Returns an a pair with the following criteria: + //! + //! first = lower_bound(lower_key, comp) if left_closed, upper_bound(lower_key, comp) otherwise + //! + //! second = upper_bound(upper_key, comp) if right_closed, lower_bound(upper_key, comp) otherwise + //! + //! Complexity: Logarithmic. + //! + //! Throws: If "comp" throws. + //! + //! Note: This function can be more efficient than calling upper_bound + //! and lower_bound for lower_key and upper_key. + //! + //! Note: Experimental function, the interface might change in future releases. + template + std::pair bounded_range + (const KeyType &lower_key, const KeyType &upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; + + //! Requires: value must be an lvalue and shall be in a set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid iterator i belonging to the set + //! that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This static function is available only if the value traits + //! is stateless. + static iterator s_iterator_to(reference value); + + //! Requires: value must be an lvalue and shall be in a set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid const_iterator i belonging to the + //! set that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This static function is available only if the value traits + //! is stateless. + static const_iterator s_iterator_to(const_reference value); + + //! Requires: value must be an lvalue and shall be in a set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid iterator i belonging to the set + //! that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator iterator_to(reference value); + + //! Requires: value must be an lvalue and shall be in a set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid const_iterator i belonging to the + //! set that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator iterator_to(const_reference value) const; + + //! Requires: value shall not be in a container. + //! + //! Effects: init_node puts the hook of a value in a well-known default + //! state. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant time. + //! + //! Note: This function puts the hook in the well-known default state + //! used by auto_unlink and safe hooks. + static void init_node(reference value); + + #endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + + //! Effects: Unlinks the leftmost node from the container. + //! + //! Complexity: Average complexity is constant time. + //! + //! Throws: Nothing. + //! + //! Notes: This function breaks the container and the container can + //! only be used for more unlink_leftmost_without_rebalance calls. + //! This function is normally used to achieve a step by step + //! controlled destruction of the container. + pointer unlink_leftmost_without_rebalance() + { + node_ptr to_be_disposed(node_algorithms::unlink_leftmost_without_rebalance + (this->header_ptr())); + if(!to_be_disposed) + return 0; + this->sz_traits().decrement(); + if(safemode_or_autounlink)//If this is commented does not work with normal_link + node_algorithms::init(to_be_disposed); + return this->get_real_value_traits().to_value_ptr(to_be_disposed); + } + + #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + + //! Requires: replace_this must be a valid iterator of *this + //! and with_this must not be inserted in any container. + //! + //! Effects: Replaces replace_this in its position in the + //! container with with_this. The container does not need to be rebalanced. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This function will break container ordering invariants if + //! with_this is not equivalent to *replace_this according to the + //! ordering rules. This function is faster than erasing and inserting + //! the node, since no rebalancing or comparison is needed. + void replace_node(iterator replace_this, reference with_this); + + //! Effects: Rebalances the tree. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear. + void rebalance(); + + //! Requires: old_root is a node of a tree. + //! + //! Effects: Rebalances the subtree rooted at old_root. + //! + //! Returns: The new root of the subtree. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the elements in the subtree. + iterator rebalance_subtree(iterator root); + + #endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + + //! Effects: removes "value" from the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Logarithmic time. + //! + //! Note: This static function is only usable with non-constant + //! time size containers that have stateless comparison functors. + //! + //! If the user calls + //! this function with a constant time size container or stateful comparison + //! functor a compilation error will be issued. + static void remove_node(reference value) + { + BOOST_STATIC_ASSERT((!constant_time_size)); + node_ptr to_remove(value_traits::to_node_ptr(value)); + node_algorithms::unlink(to_remove); + if(safemode_or_autounlink) + node_algorithms::init(to_remove); + } + + /// @cond + private: + template + iterator private_erase(const_iterator b, const_iterator e, size_type &n, Disposer disposer) + { + for(n = 0; b != e; ++n) + this->erase_and_dispose(b++, disposer); + return b.unconst(); + } + + iterator private_erase(const_iterator b, const_iterator e, size_type &n) + { + for(n = 0; b != e; ++n) + this->erase(b++); + return b.unconst(); + } + /// @endcond + + private: + static bstree_impl &priv_container_from_end_iterator(const const_iterator &end_iterator) + { + return *static_cast + (boost::intrusive::detail::to_raw_pointer(end_iterator.pointed_node())); + } +}; + +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) +template +#else +template +#endif +inline bool operator< +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) +(const bstree_impl &x, const bstree_impl &y) +#else +( const bstree_impl &x +, const bstree_impl &y) +#endif +{ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } + +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) +template +#else +template +#endif +bool operator== +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) +(const bstree_impl &x, const bstree_impl &y) +#else +( const bstree_impl &x +, const bstree_impl &y) +#endif +{ + typedef bstree_impl tree_type; + typedef typename tree_type::const_iterator const_iterator; + + if(tree_type::constant_time_size && x.size() != y.size()){ + return false; + } + const_iterator end1 = x.end(); + const_iterator i1 = x.begin(); + const_iterator i2 = y.begin(); + if(tree_type::constant_time_size){ + while (i1 != end1 && *i1 == *i2) { + ++i1; + ++i2; + } + return i1 == end1; + } + else{ + const_iterator end2 = y.end(); + while (i1 != end1 && i2 != end2 && *i1 == *i2) { + ++i1; + ++i2; + } + return i1 == end1 && i2 == end2; + } +} + +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) +template +#else +template +#endif +inline bool operator!= +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) +(const bstree_impl &x, const bstree_impl &y) +#else +( const bstree_impl &x +, const bstree_impl &y) +#endif +{ return !(x == y); } + +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) +template +#else +template +#endif +inline bool operator> +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) +(const bstree_impl &x, const bstree_impl &y) +#else +( const bstree_impl &x +, const bstree_impl &y) +#endif +{ return y < x; } + +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) +template +#else +template +#endif +inline bool operator<= +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) +(const bstree_impl &x, const bstree_impl &y) +#else +( const bstree_impl &x +, const bstree_impl &y) +#endif +{ return !(y < x); } + +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) +template +#else +template +#endif +inline bool operator>= +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) +(const bstree_impl &x, const bstree_impl &y) +#else +( const bstree_impl &x +, const bstree_impl &y) +#endif +{ return !(x < y); } + +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) +template +#else +template +#endif +inline void swap +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) +(bstree_impl &x, bstree_impl &y) +#else +( bstree_impl &x +, bstree_impl &y) +#endif +{ x.swap(y); } + +//! Helper metafunction to define a \c bstree that yields to the same type when the +//! same options (either explicitly or implicitly) are used. +#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +template +#else +template +#endif +struct make_bstree +{ + /// @cond + typedef typename pack_options + < bstree_defaults, + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3, O4 + #else + Options... + #endif + >::type packed_options; + + typedef typename detail::get_value_traits + ::type value_traits; + + typedef bstree_impl + < value_traits + , typename packed_options::compare + , typename packed_options::size_type + , packed_options::constant_time_size + , BsTreeAlgorithms + > implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + + +#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +template +#else +template +#endif +class bstree + : public make_bstree::type +{ + typedef typename make_bstree + ::type Base; + BOOST_MOVABLE_BUT_NOT_COPYABLE(bstree) + + public: + typedef typename Base::value_compare value_compare; + typedef typename Base::value_traits value_traits; + typedef typename Base::real_value_traits real_value_traits; + typedef typename Base::iterator iterator; + typedef typename Base::const_iterator const_iterator; + + //Assert if passed value traits are compatible with the type + BOOST_STATIC_ASSERT((detail::is_same::value)); + + bstree( const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : Base(cmp, v_traits) + {} + + template + bstree( bool unique, Iterator b, Iterator e + , const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : Base(unique, b, e, cmp, v_traits) + {} + + bstree(BOOST_RV_REF(bstree) x) + : Base(::boost::move(static_cast(x))) + {} + + bstree& operator=(BOOST_RV_REF(bstree) x) + { return static_cast(this->Base::operator=(::boost::move(static_cast(x)))); } + + static bstree &container_from_end_iterator(iterator end_iterator) + { return static_cast(Base::container_from_end_iterator(end_iterator)); } + + static const bstree &container_from_end_iterator(const_iterator end_iterator) + { return static_cast(Base::container_from_end_iterator(end_iterator)); } + + static bstree &container_from_iterator(iterator it) + { return static_cast(Base::container_from_iterator(it)); } + + static const bstree &container_from_iterator(const_iterator it) + { return static_cast(Base::container_from_iterator(it)); } +}; + +#endif +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_BSTREE_HPP diff --git a/include/boost/intrusive/detail/tree_algorithms.hpp b/include/boost/intrusive/bstree_algorithms.hpp similarity index 76% rename from include/boost/intrusive/detail/tree_algorithms.hpp rename to include/boost/intrusive/bstree_algorithms.hpp index 27c8667..6297329 100644 --- a/include/boost/intrusive/detail/tree_algorithms.hpp +++ b/include/boost/intrusive/bstree_algorithms.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 @@ -10,8 +10,8 @@ // ///////////////////////////////////////////////////////////////////////////// -#ifndef BOOST_INTRUSIVE_TREE_ALGORITHMS_HPP -#define BOOST_INTRUSIVE_TREE_ALGORITHMS_HPP +#ifndef BOOST_INTRUSIVE_BSTREE_ALGORITHMS_HPP +#define BOOST_INTRUSIVE_BSTREE_ALGORITHMS_HPP #include #include @@ -22,7 +22,32 @@ namespace boost { namespace intrusive { -namespace detail { + +/// @cond + +//! This type is the information that will be filled by insert_unique_check +template +struct insert_commit_data_t +{ + insert_commit_data_t() + : link_left(false) + , node() + {} + bool link_left; + NodePtr node; +}; + +template +struct data_for_rebalance_t +{ + NodePtr x; + NodePtr x_parent; + NodePtr y; +}; + +/// @endcond + + //! This is an implementation of a binary search tree. //! A node in the search tree has references to its children and its parent. This @@ -66,14 +91,13 @@ namespace detail { //! | | | | | | | | //! +---------+ +---------+ +---------+ +---------+ //! - -//! tree_algorithms is configured with a NodeTraits class, which encapsulates the +//! bstree_algorithms is configured with a NodeTraits class, which encapsulates the //! information about the node to be manipulated. NodeTraits must support the //! following interface: //! //! Typedefs: //! -//! node: The type of the node that forms the circular list +//! node: The type of the node that forms the binary search tree //! //! node_ptr: A pointer to a node //! @@ -93,31 +117,18 @@ namespace detail { //! //! static void set_right(node_ptr n, node_ptr right); template -class tree_algorithms +class bstree_algorithms { public: typedef typename NodeTraits::node node; typedef NodeTraits node_traits; typedef typename NodeTraits::node_ptr node_ptr; typedef typename NodeTraits::const_node_ptr const_node_ptr; - - //! This type is the information that will be filled by insert_unique_check - struct insert_commit_data - { - insert_commit_data() - : link_left(false) - , node() - {} - bool link_left; - node_ptr node; - }; - - struct nop_erase_fixup - { - void operator()(const node_ptr&, const node_ptr&){} - }; + typedef insert_commit_data_t insert_commit_data; + typedef data_for_rebalance_t data_for_rebalance; /// @cond + private: template struct dispose_subtree_disposer @@ -136,20 +147,31 @@ class tree_algorithms } } Disposer *disposer_; - node_ptr subtree_; + const node_ptr subtree_; }; - static node_ptr uncast(const const_node_ptr & ptr) - { return pointer_traits::const_cast_from(ptr); } - /// @endcond public: + //! Requires: 'header' is the header node of a tree. + //! + //! Effects: Returns the first node of the tree, the header if the tree is empty. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. static node_ptr begin_node(const const_node_ptr & header) { return node_traits::get_left(header); } + //! Requires: 'header' is the header node of a tree. + //! + //! Effects: Returns the header of the tree. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. static node_ptr end_node(const const_node_ptr & header) - { return uncast(header); } + { return detail::uncast(header); } //! Requires: 'node' is a node of the tree or an node initialized //! by init(...) or init_node. @@ -162,15 +184,48 @@ class tree_algorithms static bool unique(const const_node_ptr & node) { return !NodeTraits::get_parent(node); } + //! Requires: 'node' is a node of the tree or a header node. + //! + //! Effects: Returns the header of the tree. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. static node_ptr get_header(const const_node_ptr & node) { - node_ptr h = uncast(node); - if(NodeTraits::get_parent(node)){ - h = NodeTraits::get_parent(node); - while(!is_header(h)) - h = NodeTraits::get_parent(h); + node_ptr n(detail::uncast(node)); + node_ptr p(NodeTraits::get_parent(node)); + //If p is null, then n is the header of an empty tree + if(p){ + //Non-empty tree, check if n is neither root nor header + node_ptr pp(NodeTraits::get_parent(p)); + //If granparent is not equal to n, then n is neither root nor header, + //the try the fast path + if(n != pp){ + do{ + n = p; + p = pp; + pp = NodeTraits::get_parent(pp); + }while(n != pp); + n = p; + } + //Check if n is root or header when size() > 0 + else if(!is_header(n)){ + n = p; + } } - return h; + return n; + /* + node_ptr h = detail::uncast(node); + node_ptr p = NodeTraits::get_parent(node); + if(p){ + while(!is_header(p)) + p = NodeTraits::get_parent(p); + return p; + } + else{ + return h; + }*/ } //! Requires: node1 and node2 can't be header nodes @@ -358,9 +413,7 @@ class tree_algorithms //! Note: This function will break container ordering invariants if //! new_node is not equivalent to node_to_be_replaced according to the //! ordering rules. This function is faster than erasing and inserting - //! the node, since no rebalancing and comparison is needed. - //! - //!Experimental function + //! the node, since no rebalancing and comparison is needed. Experimental function static void replace_node(const node_ptr & node_to_be_replaced, const node_ptr & new_node) { if(node_to_be_replaced == new_node) @@ -381,9 +434,7 @@ class tree_algorithms //! Note: This function will break container ordering invariants if //! new_node is not equivalent to node_to_be_replaced according to the //! ordering rules. This function is faster than erasing and inserting - //! the node, since no rebalancing or comparison is needed. - //! - //!Experimental function + //! the node, since no rebalancing or comparison is needed. Experimental function static void replace_node(const node_ptr & node_to_be_replaced, const node_ptr & header, const node_ptr & new_node) { if(node_to_be_replaced == new_node) @@ -447,7 +498,7 @@ class tree_algorithms p = x; x = NodeTraits::get_parent(x); } - return NodeTraits::get_right(p) != x ? x : uncast(p); + return NodeTraits::get_right(p) != x ? x : detail::uncast(p); } } @@ -602,7 +653,7 @@ class tree_algorithms if (leftmost_right){ NodeTraits::set_parent(leftmost_right, leftmost_parent); - NodeTraits::set_left(header, tree_algorithms::minimum(leftmost_right)); + NodeTraits::set_left(header, bstree_algorithms::minimum(leftmost_right)); if (is_root) NodeTraits::set_parent(header, leftmost_right); @@ -621,42 +672,6 @@ class tree_algorithms return leftmost; } - //! Requires: node is a node of the tree but it's not the header. - //! - //! Effects: Returns the number of nodes of the subtree. - //! - //! Complexity: Linear time. - //! - //! Throws: Nothing. - static std::size_t count(const const_node_ptr & subtree) - { - if(!subtree) return 0; - std::size_t count = 0; - node_ptr p = minimum(uncast(subtree)); - bool continue_looping = true; - while(continue_looping){ - ++count; - node_ptr p_right(NodeTraits::get_right(p)); - if(p_right){ - p = minimum(p_right); - } - else { - for(;;){ - node_ptr q; - if (p == subtree){ - continue_looping = false; - break; - } - q = p; - p = NodeTraits::get_parent(p); - if (NodeTraits::get_left(p) == q) - break; - } - } - } - return count; - } - //! Requires: node is a node of the tree but it's not the header. //! //! Effects: Returns the number of nodes of the subtree. @@ -722,6 +737,13 @@ class tree_algorithms } } + //! Requires: p is a node of a tree. + //! + //! Effects: Returns true if p is the header of the tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. static bool is_header(const const_node_ptr & p) { node_ptr p_left (NodeTraits::get_left(p)); @@ -754,7 +776,7 @@ class tree_algorithms static node_ptr find (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) { - node_ptr end = uncast(header); + node_ptr end = detail::uncast(header); node_ptr y = lower_bound(header, key, comp); return (y == end || comp(key, y)) ? end : y; } @@ -778,6 +800,8 @@ class tree_algorithms //! //! Note: This function can be more efficient than calling upper_bound //! and lower_bound for lower_key and upper_key. + //! + //! Note: Experimental function, the interface might change. template< class KeyType, class KeyNodePtrCompare> static std::pair bounded_range ( const const_node_ptr & header @@ -787,7 +811,7 @@ class tree_algorithms , bool left_closed , bool right_closed) { - node_ptr y = uncast(header); + node_ptr y = detail::uncast(header); node_ptr x = NodeTraits::get_parent(header); while(x){ @@ -835,6 +859,30 @@ class tree_algorithms return std::pair (y, y); } + //! 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 the number of elements with a key equivalent to "key"pair of node_ptr delimiting a range containing + //! according to "comp". + //! + //! Complexity: Logarithmic. + //! + //! Throws: If "comp" throws. + template + static std::size_t count + (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) + { + std::pair ret = equal_range(header, key, comp); + std::size_t n = 0; + while(ret.first != ret.second){ + ++n; + ret.first = next_node(ret.first); + } + return n; + } + //! 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 @@ -871,7 +919,7 @@ class tree_algorithms static node_ptr lower_bound (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) { - return lower_bound_loop(NodeTraits::get_parent(header), uncast(header), key, comp); + return lower_bound_loop(NodeTraits::get_parent(header), detail::uncast(header), key, comp); } //! Requires: "header" must be the header node of a tree. @@ -889,7 +937,7 @@ class tree_algorithms static node_ptr upper_bound (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) { - return upper_bound_loop(NodeTraits::get_parent(header), uncast(header), key, comp); + return upper_bound_loop(NodeTraits::get_parent(header), detail::uncast(header), key, comp); } //! Requires: "header" must be the header node of a tree. @@ -913,32 +961,6 @@ class tree_algorithms (const node_ptr & header, const node_ptr & new_value, const insert_commit_data &commit_data) { return insert_commit(header, new_value, commit_data); } - static void insert_commit - (const node_ptr & header, const node_ptr & new_node, const insert_commit_data &commit_data) - { - //Check if commit_data has not been initialized by a insert_unique_check call. - BOOST_INTRUSIVE_INVARIANT_ASSERT(commit_data.node != node_ptr()); - node_ptr parent_node(commit_data.node); - if(parent_node == header){ - NodeTraits::set_parent(header, new_node); - NodeTraits::set_right(header, new_node); - NodeTraits::set_left(header, new_node); - } - else if(commit_data.link_left){ - NodeTraits::set_left(parent_node, new_node); - if(parent_node == NodeTraits::get_left(header)) - NodeTraits::set_left(header, new_node); - } - else{ - NodeTraits::set_right(parent_node, new_node); - if(parent_node == NodeTraits::get_right(header)) - NodeTraits::set_right(header, new_node); - } - NodeTraits::set_parent(new_node, parent_node); - NodeTraits::set_right(new_node, node_ptr()); - NodeTraits::set_left(new_node, node_ptr()); - } - //! 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 @@ -975,11 +997,15 @@ class tree_algorithms //! if no more objects are inserted or erased from the set. template static std::pair insert_unique_check - (const const_node_ptr & header, const KeyType &key - ,KeyNodePtrCompare comp, insert_commit_data &commit_data, std::size_t *pdepth = 0) + (const const_node_ptr & header, const KeyType &key + ,KeyNodePtrCompare comp, insert_commit_data &commit_data + #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + , std::size_t *pdepth = 0 + #endif + ) { std::size_t depth = 0; - node_ptr h(uncast(header)); + node_ptr h(detail::uncast(header)); node_ptr y(h); node_ptr x(NodeTraits::get_parent(y)); node_ptr prev = node_ptr(); @@ -1011,10 +1037,53 @@ class tree_algorithms } } + //! 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. NodePtrCompare compares KeyType with a node_ptr. + //! "hint" is node from the "header"'s tree. + //! + //! Effects: Checks if there is an equivalent node to "key" in the + //! tree according to "comp" using "hint" as a hint to where it should be + //! inserted and obtains the needed information to realize + //! a constant-time node insertion if there is no equivalent node. + //! If "hint" is the upper_bound the function has constant time + //! complexity (two comparisons in the worst case). + //! + //! Returns: If there is an equivalent value + //! returns a pair containing a node_ptr to the already present node + //! and false. If there is not equivalent key can be inserted returns true + //! in the returned pair's boolean and fills "commit_data" that is meant to + //! be used with the "insert_commit" function to achieve a constant-time + //! insertion function. + //! + //! Complexity: Average complexity is at most logarithmic, but it is + //! amortized constant time if new_node should be inserted immediately before "hint". + //! + //! Throws: If "comp" throws. + //! + //! Notes: This function is used to improve performance when constructing + //! a node is expensive and the user does not want to have two equivalent nodes + //! in the tree: if there is an equivalent value + //! the constructed object must be discarded. Many times, the part of the + //! node that is used to impose the order is much cheaper to construct + //! than the node and this function offers the possibility to use that part + //! to check if the insertion will be successful. + //! + //! If the check is successful, the user can construct the node and use + //! "insert_commit" to insert the node in constant-time. This gives a total + //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)). + //! + //! "commit_data" remains valid for a subsequent "insert_unique_commit" only + //! if no more objects are inserted or erased from the set. template static std::pair insert_unique_check (const const_node_ptr & header, const node_ptr &hint, const KeyType &key - ,KeyNodePtrCompare comp, insert_commit_data &commit_data, std::size_t *pdepth = 0) + ,KeyNodePtrCompare comp, insert_commit_data &commit_data + #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + , std::size_t *pdepth = 0 + #endif + ) { //hint must be bigger than the key if(hint == header || comp(key, hint)){ @@ -1033,44 +1102,27 @@ class tree_algorithms return insert_unique_check(header, key, comp, commit_data, pdepth); } - template - static void insert_equal_check - (const node_ptr &header, const node_ptr & hint, const node_ptr & new_node, NodePtrCompare comp - , insert_commit_data &commit_data, std::size_t *pdepth = 0) - { - if(hint == header || !comp(hint, new_node)){ - node_ptr prev(hint); - if(hint == NodeTraits::get_left(header) || - !comp(new_node, (prev = prev_node(hint)))){ - bool link_left = unique(header) || !NodeTraits::get_left(hint); - commit_data.link_left = link_left; - commit_data.node = link_left ? hint : prev; - if(pdepth){ - *pdepth = commit_data.node == header ? 0 : depth(commit_data.node) + 1; - } - } - else{ - insert_equal_upper_bound_check(header, new_node, comp, commit_data, pdepth); - } - } - else{ - insert_equal_lower_bound_check(header, new_node, comp, commit_data, pdepth); - } - } - - 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); } - - 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); } - + //! Requires: "header" must be the header node of a tree. + //! NodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. NodePtrCompare compares two node_ptrs. "hint" is node from + //! the "header"'s tree. + //! + //! Effects: Inserts new_node into the tree, using "hint" as a hint to + //! where it will be inserted. If "hint" is the upper_bound + //! the insertion takes constant time (two comparisons in the worst case). + //! + //! Complexity: Logarithmic in general, but it is amortized + //! constant time if new_node is inserted immediately before "hint". + //! + //! Throws: If "comp" throws. template static node_ptr insert_equal - (const node_ptr & h, const node_ptr & hint, const node_ptr & new_node, NodePtrCompare comp, std::size_t *pdepth = 0) + (const node_ptr & h, const node_ptr & hint, const node_ptr & new_node, NodePtrCompare comp + #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + , std::size_t *pdepth = 0 + #endif + ) { insert_commit_data commit_data; insert_equal_check(h, hint, new_node, comp, commit_data, pdepth); @@ -1078,9 +1130,25 @@ class tree_algorithms return new_node; } + //! Requires: "h" must be the header node of a tree. + //! NodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. NodePtrCompare compares two node_ptrs. + //! + //! Effects: Inserts new_node into the tree before the upper bound + //! according to "comp". + //! + //! Complexity: Average complexity for insert element is at + //! most logarithmic. + //! + //! Throws: If "comp" throws. template static node_ptr insert_equal_upper_bound - (const node_ptr & h, const node_ptr & new_node, NodePtrCompare comp, std::size_t *pdepth = 0) + (const node_ptr & h, const node_ptr & new_node, NodePtrCompare comp + #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + , std::size_t *pdepth = 0 + #endif + ) { insert_commit_data commit_data; insert_equal_upper_bound_check(h, new_node, comp, commit_data, pdepth); @@ -1088,9 +1156,25 @@ class tree_algorithms return new_node; } + //! Requires: "h" must be the header node of a tree. + //! NodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. NodePtrCompare compares two node_ptrs. + //! + //! Effects: Inserts new_node into the tree before the lower bound + //! according to "comp". + //! + //! Complexity: Average complexity for insert element is at + //! most logarithmic. + //! + //! Throws: If "comp" throws. template static node_ptr insert_equal_lower_bound - (const node_ptr & h, const node_ptr & new_node, NodePtrCompare comp, std::size_t *pdepth = 0) + (const node_ptr & h, const node_ptr & new_node, NodePtrCompare comp + #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + , std::size_t *pdepth = 0 + #endif + ) { insert_commit_data commit_data; insert_equal_lower_bound_check(h, new_node, comp, commit_data, pdepth); @@ -1098,8 +1182,26 @@ class tree_algorithms return new_node; } + //! Requires: "header" must be the header node of a tree. + //! "pos" must be a valid iterator or header (end) node. + //! "pos" must be an iterator pointing to the successor to "new_node" + //! once inserted according to the order of already inserted nodes. This function does not + //! check "pos" and this precondition must be guaranteed by the caller. + //! + //! Effects: Inserts new_node into the tree before "pos". + //! + //! Complexity: Constant-time. + //! + //! Throws: Nothing. + //! + //! Note: If "pos" is not the successor of the newly inserted "new_node" + //! tree invariants might be broken. static node_ptr insert_before - (const node_ptr & header, const node_ptr & pos, const node_ptr & new_node, std::size_t *pdepth = 0) + (const node_ptr & header, const node_ptr & pos, const node_ptr & new_node + #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + , std::size_t *pdepth = 0 + #endif + ) { insert_commit_data commit_data; insert_before_check(header, pos, commit_data, pdepth); @@ -1107,59 +1209,56 @@ class tree_algorithms return new_node; } - static void insert_before_check - (const node_ptr &header, const node_ptr & pos - , insert_commit_data &commit_data, std::size_t *pdepth = 0) - { - node_ptr prev(pos); - if(pos != NodeTraits::get_left(header)) - prev = prev_node(pos); - bool link_left = unique(header) || !NodeTraits::get_left(pos); - commit_data.link_left = link_left; - commit_data.node = link_left ? pos : prev; - if(pdepth){ - *pdepth = commit_data.node == header ? 0 : depth(commit_data.node) + 1; - } - } - + //! Requires: "header" must be the header node of a tree. + //! "new_node" must be, according to the used ordering no less than the + //! greatest inserted key. + //! + //! Effects: Inserts new_node into the tree before "pos". + //! + //! Complexity: Constant-time. + //! + //! Throws: Nothing. + //! + //! Note: If "new_node" is less than the greatest inserted key + //! tree invariants are broken. This function is slightly faster than + //! using "insert_before". static void push_back - (const node_ptr & header, const node_ptr & new_node, std::size_t *pdepth = 0) + (const node_ptr & header, const node_ptr & new_node + #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + , std::size_t *pdepth = 0 + #endif + ) { insert_commit_data commit_data; push_back_check(header, commit_data, pdepth); insert_commit(header, new_node, commit_data); } - static void push_back_check - (const node_ptr & header, insert_commit_data &commit_data, std::size_t *pdepth = 0) - { - node_ptr prev(NodeTraits::get_right(header)); - if(pdepth){ - *pdepth = prev == header ? 0 : depth(prev) + 1; - } - commit_data.link_left = false; - commit_data.node = prev; - } - + //! Requires: "header" must be the header node of a tree. + //! "new_node" must be, according to the used ordering, no greater than the + //! lowest inserted key. + //! + //! Effects: Inserts new_node into the tree before "pos". + //! + //! Complexity: Constant-time. + //! + //! Throws: Nothing. + //! + //! Note: If "new_node" is greater than the lowest inserted key + //! tree invariants are broken. This function is slightly faster than + //! using "insert_before". static void push_front - (const node_ptr & header, const node_ptr & new_node, std::size_t *pdepth = 0) + (const node_ptr & header, const node_ptr & new_node + #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + , std::size_t *pdepth = 0 + #endif + ) { insert_commit_data commit_data; push_front_check(header, commit_data, pdepth); insert_commit(header, new_node, commit_data); } - static void push_front_check - (const node_ptr & header, insert_commit_data &commit_data, std::size_t *pdepth = 0) - { - node_ptr pos(NodeTraits::get_left(header)); - if(pdepth){ - *pdepth = pos == header ? 0 : depth(pos) + 1; - } - commit_data.link_left = true; - commit_data.node = pos; - } - //! Requires: 'node' can't be a header node. //! //! Effects: Calculates the depth of a node: the depth of a @@ -1215,6 +1314,442 @@ class tree_algorithms NodeTraits::set_right (target_header, rightmost); } + //! Requires: header must be the header of a tree, z a node + //! of that tree and z != header. + //! + //! Effects: Erases node "z" from the tree with header "header". + //! + //! Complexity: Amortized constant time. + //! + //! Throws: Nothing. + static void erase(const node_ptr & header, const node_ptr & z) + { + data_for_rebalance ignored; + erase_impl(header, z, ignored); + } + + //! Requires: node is a tree node but not the header. + //! + //! Effects: Unlinks the node and rebalances the tree. + //! + //! Complexity: Average complexity is constant time. + //! + //! Throws: Nothing. + static void unlink(const node_ptr & node) + { + node_ptr x = NodeTraits::get_parent(node); + if(x){ + while(!is_header(x)) + x = NodeTraits::get_parent(x); + erase(x, node); + } + } + + //! Requires: header must be the header of a tree. + //! + //! Effects: Rebalances the tree. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear. + static void rebalance(const node_ptr & header) + { + node_ptr root = NodeTraits::get_parent(header); + if(root){ + rebalance_subtree(root); + } + } + + //! Requires: old_root is a node of a tree. It shall not be null. + //! + //! Effects: Rebalances the subtree rooted at old_root. + //! + //! Returns: The new root of the subtree. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear. + static node_ptr rebalance_subtree(const node_ptr & old_root) + { + //Taken from: + //"Tree rebalancing in optimal time and space" + //Quentin F. Stout and Bette L. Warren + + //To avoid irregularities in the algorithm (old_root can be a + //left or right child or even the root of the tree) just put the + //root as the right child of its parent. Before doing this backup + //information to restore the original relationship after + //the algorithm is applied. + node_ptr super_root = NodeTraits::get_parent(old_root); + BOOST_INTRUSIVE_INVARIANT_ASSERT(super_root); + + //Get root info + node_ptr super_root_right_backup = NodeTraits::get_right(super_root); + bool super_root_is_header = NodeTraits::get_parent(super_root) == old_root; + bool old_root_is_right = is_right_child(old_root); + NodeTraits::set_right(super_root, old_root); + + std::size_t size; + subtree_to_vine(super_root, size); + vine_to_subtree(super_root, size); + node_ptr new_root = NodeTraits::get_right(super_root); + + //Recover root + if(super_root_is_header){ + NodeTraits::set_right(super_root, super_root_right_backup); + NodeTraits::set_parent(super_root, new_root); + } + else if(old_root_is_right){ + NodeTraits::set_right(super_root, new_root); + } + else{ + NodeTraits::set_right(super_root, super_root_right_backup); + NodeTraits::set_left(super_root, new_root); + } + return new_root; + } + + protected: + //! Requires: node is a node of the tree but it's not the header. + //! + //! Effects: Returns the number of nodes of the subtree. + //! + //! Complexity: Linear time. + //! + //! Throws: Nothing. + static std::size_t subtree_size(const const_node_ptr & subtree) + { + std::size_t count = 0; + if (subtree){ + node_ptr n = detail::uncast(subtree); + node_ptr m = NodeTraits::get_left(n); + while(m){ + n = m; + m = NodeTraits::get_left(n); + } + + while(1){ + ++count; + node_ptr n_right(NodeTraits::get_right(n)); + if(n_right){ + n = n_right; + m = NodeTraits::get_left(n); + while(m){ + n = m; + m = NodeTraits::get_left(n); + } + } + else { + do{ + if (n == subtree){ + return count; + } + m = n; + n = NodeTraits::get_parent(n); + }while(NodeTraits::get_left(n) != m); + } + } + } + return count; + } + + //! Requires: p is a node of a tree. + //! + //! Effects: Returns true if p is a left child. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + static bool is_left_child(const node_ptr & p) + { return NodeTraits::get_left(NodeTraits::get_parent(p)) == p; } + + //! Requires: p is a node of a tree. + //! + //! Effects: Returns true if p is a right child. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + 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 + #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + , std::size_t *pdepth = 0 + #endif + ) + { + node_ptr prev(pos); + if(pos != NodeTraits::get_left(header)) + prev = prev_node(pos); + bool link_left = unique(header) || !NodeTraits::get_left(pos); + commit_data.link_left = link_left; + commit_data.node = link_left ? pos : prev; + if(pdepth){ + *pdepth = commit_data.node == header ? 0 : depth(commit_data.node) + 1; + } + } + + static void push_back_check + (const node_ptr & header, insert_commit_data &commit_data + #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + , std::size_t *pdepth = 0 + #endif + ) + { + node_ptr prev(NodeTraits::get_right(header)); + if(pdepth){ + *pdepth = prev == header ? 0 : depth(prev) + 1; + } + commit_data.link_left = false; + commit_data.node = prev; + } + + static void push_front_check + (const node_ptr & header, insert_commit_data &commit_data + #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + , std::size_t *pdepth = 0 + #endif + ) + { + node_ptr pos(NodeTraits::get_left(header)); + if(pdepth){ + *pdepth = pos == header ? 0 : depth(pos) + 1; + } + commit_data.link_left = true; + commit_data.node = pos; + } + + template + static void insert_equal_check + (const node_ptr &header, const node_ptr & hint, const node_ptr & new_node, NodePtrCompare comp + , insert_commit_data &commit_data + /// @cond + , std::size_t *pdepth = 0 + /// @endcond + ) + { + if(hint == header || !comp(hint, new_node)){ + node_ptr prev(hint); + if(hint == NodeTraits::get_left(header) || + !comp(new_node, (prev = prev_node(hint)))){ + bool link_left = unique(header) || !NodeTraits::get_left(hint); + commit_data.link_left = link_left; + commit_data.node = link_left ? hint : prev; + if(pdepth){ + *pdepth = commit_data.node == header ? 0 : depth(commit_data.node) + 1; + } + } + else{ + insert_equal_upper_bound_check(header, new_node, comp, commit_data, pdepth); + } + } + else{ + insert_equal_lower_bound_check(header, new_node, comp, commit_data, pdepth); + } + } + + 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); } + + 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); } + + static void insert_commit + (const node_ptr & header, const node_ptr & new_node, const insert_commit_data &commit_data) + { + //Check if commit_data has not been initialized by a insert_unique_check call. + BOOST_INTRUSIVE_INVARIANT_ASSERT(commit_data.node != node_ptr()); + node_ptr parent_node(commit_data.node); + if(parent_node == header){ + NodeTraits::set_parent(header, new_node); + NodeTraits::set_right(header, new_node); + NodeTraits::set_left(header, new_node); + } + else if(commit_data.link_left){ + NodeTraits::set_left(parent_node, new_node); + if(parent_node == NodeTraits::get_left(header)) + NodeTraits::set_left(header, new_node); + } + else{ + NodeTraits::set_right(parent_node, new_node); + if(parent_node == NodeTraits::get_right(header)) + NodeTraits::set_right(header, new_node); + } + NodeTraits::set_parent(new_node, parent_node); + NodeTraits::set_right(new_node, node_ptr()); + NodeTraits::set_left(new_node, node_ptr()); + } + + private: + static void subtree_to_vine(node_ptr vine_tail, std::size_t &size) + { + //Inspired by LibAVL: + //It uses a clever optimization for trees with parent pointers. + //No parent pointer is updated when transforming a tree to a vine as + //most of them will be overriten during compression rotations. + //A final pass must be made after the rebalancing to updated those + //pointers not updated by tree_to_vine + compression calls + std::size_t len = 0; + node_ptr remainder = NodeTraits::get_right(vine_tail); + while(remainder){ + node_ptr tempptr = NodeTraits::get_left(remainder); + if(!tempptr){ //move vine-tail down one + vine_tail = remainder; + remainder = NodeTraits::get_right(remainder); + ++len; + } + else{ //rotate + NodeTraits::set_left(remainder, NodeTraits::get_right(tempptr)); + NodeTraits::set_right(tempptr, remainder); + remainder = tempptr; + NodeTraits::set_right(vine_tail, tempptr); + } + } + size = len; + } + + static void compress_subtree(node_ptr scanner, std::size_t count) + { + while(count--){ //compress "count" spine nodes in the tree with pseudo-root scanner + node_ptr child = NodeTraits::get_right(scanner); + node_ptr child_right = NodeTraits::get_right(child); + NodeTraits::set_right(scanner, child_right); + //Avoid setting the parent of child_right + scanner = child_right; + node_ptr scanner_left = NodeTraits::get_left(scanner); + NodeTraits::set_right(child, scanner_left); + if(scanner_left) + NodeTraits::set_parent(scanner_left, child); + NodeTraits::set_left(scanner, child); + NodeTraits::set_parent(child, scanner); + } + } + + static void vine_to_subtree(const node_ptr & super_root, std::size_t count) + { + std::size_t leaf_nodes = count + 1 - ((std::size_t) 1 << detail::floor_log2(count + 1)); + compress_subtree(super_root, leaf_nodes); //create deepest leaves + std::size_t vine_nodes = count - leaf_nodes; + while(vine_nodes > 1){ + vine_nodes /= 2; + compress_subtree(super_root, vine_nodes); + } + + //Update parents of nodes still in the in the original vine line + //as those have not been updated by subtree_to_vine or compress_subtree + for ( node_ptr q = super_root, p = NodeTraits::get_right(super_root) + ; p + ; q = p, p = NodeTraits::get_right(p)){ + NodeTraits::set_parent(p, q); + } + } + + //! Requires: "n" must be a node inserted in a tree. + //! + //! Effects: Returns a pointer to the header node of the tree. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + static node_ptr get_root(const node_ptr & node) + { + BOOST_INTRUSIVE_INVARIANT_ASSERT((!inited(node))); + node_ptr x = NodeTraits::get_parent(node); + if(x){ + while(!is_header(x)){ + x = NodeTraits::get_parent(x); + } + return x; + } + else{ + return node; + } + } + template static node_ptr clone_subtree (const const_node_ptr &source_parent, const node_ptr &target_parent @@ -1310,304 +1845,6 @@ class tree_algorithms } } - //! Requires: p is a node of a tree. - //! - //! Effects: Returns true if p is a left child. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - static bool is_left_child(const node_ptr & p) - { return NodeTraits::get_left(NodeTraits::get_parent(p)) == p; } - - //! Requires: p is a node of a tree. - //! - //! Effects: Returns true if p is a right child. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - static bool is_right_child(const node_ptr & p) - { return NodeTraits::get_right(NodeTraits::get_parent(p)) == p; } - - //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 erase(const node_ptr & header, const node_ptr & z) - { - data_for_rebalance ignored; - erase_impl(header, z, ignored); - } - - struct data_for_rebalance - { - node_ptr x; - node_ptr x_parent; - node_ptr y; - }; - - 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); - } - } - - static void unlink(const node_ptr & node) - { - node_ptr x = NodeTraits::get_parent(node); - if(x){ - while(!is_header(x)) - x = NodeTraits::get_parent(x); - erase(x, node); - } - } - - static void tree_to_vine(const node_ptr & header) - { subtree_to_vine(NodeTraits::get_parent(header)); } - - static void vine_to_tree(const node_ptr & header, std::size_t count) - { vine_to_subtree(NodeTraits::get_parent(header), count); } - - static void rebalance(const node_ptr & header) - { - //Taken from: - //"Tree rebalancing in optimal time and space" - //Quentin F. Stout and Bette L. Warren - std::size_t len = 0; - subtree_to_vine(NodeTraits::get_parent(header), &len); - vine_to_subtree(NodeTraits::get_parent(header), len); - } - - static node_ptr rebalance_subtree(const node_ptr & old_root) - { - std::size_t len = 0; - node_ptr new_root = subtree_to_vine(old_root, &len); - return vine_to_subtree(new_root, len); - } - - static node_ptr subtree_to_vine(const node_ptr & old_root, std::size_t *plen = 0) - { - std::size_t len; - len = 0; - if(!old_root) return node_ptr(); - - //To avoid irregularities in the algorithm (old_root can be a - //left or right child or even the root of the tree) just put the - //root as the right child of its parent. Before doing this backup - //information to restore the original relationship after - //the algorithm is applied. - node_ptr super_root = NodeTraits::get_parent(old_root); - BOOST_INTRUSIVE_INVARIANT_ASSERT(super_root); - - //Get info - node_ptr super_root_right_backup = NodeTraits::get_right(super_root); - bool super_root_is_header = is_header(super_root); - bool old_root_is_right = is_right_child(old_root); - - node_ptr x(old_root); - node_ptr new_root(x); - node_ptr save; - bool moved_to_right = false; - for( ; x; x = save){ - save = NodeTraits::get_left(x); - if(save){ - // Right rotation - node_ptr save_right = NodeTraits::get_right(save); - node_ptr x_parent = NodeTraits::get_parent(x); - NodeTraits::set_parent(save, x_parent); - NodeTraits::set_right (x_parent, save); - NodeTraits::set_parent(x, save); - NodeTraits::set_right (save, x); - NodeTraits::set_left(x, save_right); - if(save_right) - NodeTraits::set_parent(save_right, x); - if(!moved_to_right) - new_root = save; - } - else{ - moved_to_right = true; - save = NodeTraits::get_right(x); - ++len; - } - } - - if(super_root_is_header){ - NodeTraits::set_right(super_root, super_root_right_backup); - NodeTraits::set_parent(super_root, new_root); - } - else if(old_root_is_right){ - NodeTraits::set_right(super_root, new_root); - } - else{ - NodeTraits::set_right(super_root, super_root_right_backup); - NodeTraits::set_left(super_root, new_root); - } - if(plen) *plen = len; - return new_root; - } - - static node_ptr vine_to_subtree(const node_ptr & old_root, std::size_t count) - { - std::size_t leaf_nodes = count + 1 - ((std::size_t) 1 << floor_log2 (count + 1)); - std::size_t vine_nodes = count - leaf_nodes; - - node_ptr new_root = compress_subtree(old_root, leaf_nodes); - while(vine_nodes > 1){ - vine_nodes /= 2; - new_root = compress_subtree(new_root, vine_nodes); - } - return new_root; - } - - static node_ptr compress_subtree(const node_ptr & old_root, std::size_t count) - { - if(!old_root) return old_root; - - //To avoid irregularities in the algorithm (old_root can be - //left or right child or even the root of the tree) just put the - //root as the right child of its parent. First obtain - //information to restore the original relationship after - //the algorithm is applied. - node_ptr super_root = NodeTraits::get_parent(old_root); - BOOST_INTRUSIVE_INVARIANT_ASSERT(super_root); - - //Get info - node_ptr super_root_right_backup = NodeTraits::get_right(super_root); - bool super_root_is_header = is_header(super_root); - bool old_root_is_right = is_right_child(old_root); - - //Put old_root as right child - NodeTraits::set_right(super_root, old_root); - - //Start the compression algorithm - node_ptr even_parent = super_root; - node_ptr new_root = old_root; - - while(count--){ - node_ptr even = NodeTraits::get_right(even_parent); - node_ptr odd = NodeTraits::get_right(even); - - if(new_root == old_root) - new_root = odd; - - node_ptr even_right = NodeTraits::get_left(odd); - NodeTraits::set_right(even, even_right); - if (even_right) - NodeTraits::set_parent(even_right, even); - - NodeTraits::set_right(even_parent, odd); - NodeTraits::set_parent(odd, even_parent); - NodeTraits::set_left(odd, even); - NodeTraits::set_parent(even, odd); - even_parent = odd; - } - - if(super_root_is_header){ - NodeTraits::set_parent(super_root, new_root); - NodeTraits::set_right(super_root, super_root_right_backup); - } - else if(old_root_is_right){ - NodeTraits::set_right(super_root, new_root); - } - else{ - NodeTraits::set_left(super_root, new_root); - NodeTraits::set_right(super_root, super_root_right_backup); - } - return new_root; - } - - //! Requires: "n" must be a node inserted in a tree. - //! - //! Effects: Returns a pointer to the header node of the tree. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - static node_ptr get_root(const node_ptr & node) - { - BOOST_INTRUSIVE_INVARIANT_ASSERT((!inited(node))); - node_ptr x = NodeTraits::get_parent(node); - if(x){ - while(!is_header(x)){ - x = NodeTraits::get_parent(x); - } - return x; - } - else{ - return node; - } - } - - private: - template static node_ptr lower_bound_loop (node_ptr x, node_ptr y, const KeyType &key, KeyNodePtrCompare comp) @@ -1689,7 +1926,7 @@ class tree_algorithms } else{ // find z's successor - y = tree_algorithms::minimum (z_right); + y = bstree_algorithms::minimum (z_right); x = NodeTraits::get_right(y); // x might be null. } @@ -1707,23 +1944,23 @@ class tree_algorithms } else x_parent = y; - tree_algorithms::replace_own (z, y, header); + bstree_algorithms::replace_own (z, y, header); NodeTraits::set_parent(y, NodeTraits::get_parent(z)); } - else { // y == z --> z has only one child, or none + else { // y == z --> z has only one child, or void x_parent = NodeTraits::get_parent(z); if(x) NodeTraits::set_parent(x, x_parent); - tree_algorithms::replace_own (z, x, header); + 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 - tree_algorithms::minimum (x)); + 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 - tree_algorithms::maximum(x)); + bstree_algorithms::maximum(x)); } } @@ -1733,10 +1970,19 @@ class tree_algorithms } }; -} //namespace detail { +/// @cond + +template +struct get_algo +{ + typedef bstree_algorithms type; +}; + +/// @endcond + } //namespace intrusive } //namespace boost #include -#endif //BOOST_INTRUSIVE_TREE_ALGORITHMS_HPP +#endif //BOOST_INTRUSIVE_BSTREE_ALGORITHMS_HPP diff --git a/include/boost/intrusive/circular_list_algorithms.hpp b/include/boost/intrusive/circular_list_algorithms.hpp index 5add320..9d6213a 100644 --- a/include/boost/intrusive/circular_list_algorithms.hpp +++ b/include/boost/intrusive/circular_list_algorithms.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 @@ -16,6 +16,7 @@ #include #include +#include #include namespace boost { @@ -405,6 +406,16 @@ class circular_list_algorithms } }; +/// @cond + +template +struct get_algo +{ + typedef circular_list_algorithms type; +}; + +/// @endcond + } //namespace intrusive } //namespace boost diff --git a/include/boost/intrusive/circular_slist_algorithms.hpp b/include/boost/intrusive/circular_slist_algorithms.hpp index fc3848e..fb5f75a 100644 --- a/include/boost/intrusive/circular_slist_algorithms.hpp +++ b/include/boost/intrusive/circular_slist_algorithms.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 @@ -18,6 +18,7 @@ #include #include #include +#include #include namespace boost { @@ -396,6 +397,16 @@ class circular_slist_algorithms } }; +/// @cond + +template +struct get_algo +{ + typedef circular_slist_algorithms type; +}; + +/// @endcond + } //namespace intrusive } //namespace boost diff --git a/include/boost/intrusive/derivation_value_traits.hpp b/include/boost/intrusive/derivation_value_traits.hpp index 0aae01b..0b3c936 100644 --- a/include/boost/intrusive/derivation_value_traits.hpp +++ b/include/boost/intrusive/derivation_value_traits.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 diff --git a/include/boost/intrusive/detail/any_node_and_algorithms.hpp b/include/boost/intrusive/detail/any_node_and_algorithms.hpp index b274135..899023d 100644 --- a/include/boost/intrusive/detail/any_node_and_algorithms.hpp +++ b/include/boost/intrusive/detail/any_node_and_algorithms.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 diff --git a/include/boost/intrusive/detail/assert.hpp b/include/boost/intrusive/detail/assert.hpp index 33de97f..3dacbcc 100644 --- a/include/boost/intrusive/detail/assert.hpp +++ b/include/boost/intrusive/detail/assert.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 diff --git a/include/boost/intrusive/detail/avltree_node.hpp b/include/boost/intrusive/detail/avltree_node.hpp index f6aefcb..8031c7d 100644 --- a/include/boost/intrusive/detail/avltree_node.hpp +++ b/include/boost/intrusive/detail/avltree_node.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 diff --git a/include/boost/intrusive/detail/clear_on_destructor_base.hpp b/include/boost/intrusive/detail/clear_on_destructor_base.hpp index 1b5c27f..c81015d 100644 --- a/include/boost/intrusive/detail/clear_on_destructor_base.hpp +++ b/include/boost/intrusive/detail/clear_on_destructor_base.hpp @@ -1,6 +1,6 @@ //////} // /////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-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) // diff --git a/include/boost/intrusive/detail/common_slist_algorithms.hpp b/include/boost/intrusive/detail/common_slist_algorithms.hpp index 166f78d..a5433bb 100644 --- a/include/boost/intrusive/detail/common_slist_algorithms.hpp +++ b/include/boost/intrusive/detail/common_slist_algorithms.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 diff --git a/include/boost/intrusive/detail/config_begin.hpp b/include/boost/intrusive/detail/config_begin.hpp index 7d15336..109a590 100644 --- a/include/boost/intrusive/detail/config_begin.hpp +++ b/include/boost/intrusive/detail/config_begin.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 diff --git a/include/boost/intrusive/detail/config_end.hpp b/include/boost/intrusive/detail/config_end.hpp index d653030..a081443 100644 --- a/include/boost/intrusive/detail/config_end.hpp +++ b/include/boost/intrusive/detail/config_end.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 diff --git a/include/boost/intrusive/detail/ebo_functor_holder.hpp b/include/boost/intrusive/detail/ebo_functor_holder.hpp index 850d074..3c2959b 100644 --- a/include/boost/intrusive/detail/ebo_functor_holder.hpp +++ b/include/boost/intrusive/detail/ebo_functor_holder.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Joaquin M Lopez Munoz 2006-2012 +// (C) Copyright Joaquin M Lopez Munoz 2006-2013 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/intrusive/detail/function_detector.hpp b/include/boost/intrusive/detail/function_detector.hpp index 08cee2d..f8eccf9 100644 --- a/include/boost/intrusive/detail/function_detector.hpp +++ b/include/boost/intrusive/detail/function_detector.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2009-2012. +// (C) Copyright Ion Gaztanaga 2009-2013. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/intrusive/detail/generic_hook.hpp b/include/boost/intrusive/detail/generic_hook.hpp index 5ddd520..e85f2b5 100644 --- a/include/boost/intrusive/detail/generic_hook.hpp +++ b/include/boost/intrusive/detail/generic_hook.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 @@ -24,85 +24,71 @@ namespace boost { namespace intrusive { -namespace detail { /// @cond -enum -{ NoBaseHook -, ListBaseHook -, SlistBaseHook -, SetBaseHook -, UsetBaseHook -, SplaySetBaseHook -, AvlSetBaseHook -, BsSetBaseHook -, AnyBaseHook +enum base_hook_type +{ NoBaseHookId +, ListBaseHookId +, SlistBaseHookId +, RbTreeBaseHookId +, HashBaseHookId +, SplayTreeBaseHookId +, AvlTreeBaseHookId +, BsTreeBaseHookId +, AnyBaseHookId }; -struct no_default_definer{}; -template -struct default_definer; +template +struct hook_tags_definer{}; -template -struct default_definer -{ typedef Hook default_list_hook; }; +template +struct hook_tags_definer +{ typedef HookTags default_list_hook; }; -template -struct default_definer -{ typedef Hook default_slist_hook; }; +template +struct hook_tags_definer +{ typedef HookTags default_slist_hook; }; -template -struct default_definer -{ typedef Hook default_set_hook; }; +template +struct hook_tags_definer +{ typedef HookTags default_rbtree_hook; }; -template -struct default_definer -{ typedef Hook default_uset_hook; }; +template +struct hook_tags_definer +{ typedef HookTags default_hashtable_hook; }; -template -struct default_definer -{ typedef Hook default_splay_set_hook; }; +template +struct hook_tags_definer +{ typedef HookTags default_splaytree_hook; }; -template -struct default_definer -{ typedef Hook default_avl_set_hook; }; +template +struct hook_tags_definer +{ typedef HookTags default_avltree_hook; }; -template -struct default_definer -{ typedef Hook default_bs_set_hook; }; +template +struct hook_tags_definer +{ typedef HookTags default_bstree_hook; }; -template -struct default_definer -{ typedef Hook default_any_hook; }; - -template -struct make_default_definer -{ - typedef typename detail::if_c - < BaseHookType != 0 - , default_definer - , no_default_definer>::type type; -}; +template +struct hook_tags_definer +{ typedef HookTags default_any_hook; }; template - < class GetNodeAlgorithms + < class NodeTraits , class Tag , link_mode_type LinkMode - , int HookType + , base_hook_type BaseHookType > -struct make_node_holder +struct hooktags { - typedef typename detail::if_c - ::value - , detail::node_holder - < typename GetNodeAlgorithms::type::node - , Tag - , LinkMode - , HookType> - , typename GetNodeAlgorithms::type::node - >::type type; + static const link_mode_type link_mode = LinkMode; + typedef Tag tag; + typedef NodeTraits node_traits; + static const bool is_base_hook = !detail::is_same::value; + static const bool safemode_or_autounlink = is_safe_autounlink::value; + static const unsigned int type = BaseHookType; }; /// @endcond @@ -111,22 +97,28 @@ template < class GetNodeAlgorithms , class Tag , link_mode_type LinkMode - , int HookType + , base_hook_type BaseHookType > class generic_hook /// @cond - - //If the hook is a base hook, derive generic hook from detail::node_holder + //If the hook is a base hook, derive generic hook from node_holder //so that a unique base class is created to convert from the node - //to the type. This mechanism will be used by base_hook_traits. + //to the type. This mechanism will be used by bhtraits. // //If the hook is a member hook, generic hook will directly derive //from the hook. - : public make_default_definer - < generic_hook - , detail::is_same::value*HookType + : public detail::if_c + < detail::is_same::value + , typename GetNodeAlgorithms::type::node + , node_holder >::type - , public make_node_holder::type + //If this is the a default-tagged base hook derive from a class that + //will define an special internal typedef. Containers will be able to detect this + //special typedef and obtain generic_hook's internal types in order to deduce + //value_traits for this hook. + , public hook_tags_definer + < generic_hook + , detail::is_same::value*BaseHookType> /// @endcond { /// @cond @@ -136,16 +128,10 @@ class generic_hook typedef typename node_algorithms::const_node_ptr const_node_ptr; public: - struct boost_intrusive_tags - { - static const int hook_type = HookType; - static const link_mode_type link_mode = LinkMode; - typedef Tag tag; - typedef typename GetNodeAlgorithms::type::node_traits node_traits; - static const bool is_base_hook = !detail::is_same::value; - static const bool safemode_or_autounlink = - (int)link_mode == (int)auto_unlink || (int)link_mode == (int)safe_link; - }; + + typedef hooktags + < typename GetNodeAlgorithms::type::node_traits + , Tag, LinkMode, BaseHookType> hooktags; node_ptr this_ptr() { return pointer_traits::pointer_to(static_cast(*this)); } @@ -158,14 +144,14 @@ class generic_hook generic_hook() { - if(boost_intrusive_tags::safemode_or_autounlink){ + if(hooktags::safemode_or_autounlink){ node_algorithms::init(this->this_ptr()); } } generic_hook(const generic_hook& ) { - if(boost_intrusive_tags::safemode_or_autounlink){ + if(hooktags::safemode_or_autounlink){ node_algorithms::init(this->this_ptr()); } } @@ -176,7 +162,7 @@ class generic_hook ~generic_hook() { destructor_impl - (*this, detail::link_dispatch()); + (*this, detail::link_dispatch()); } void swap_nodes(generic_hook &other) @@ -188,19 +174,18 @@ class generic_hook bool is_linked() const { //is_linked() can be only used in safe-mode or auto-unlink - BOOST_STATIC_ASSERT(( boost_intrusive_tags::safemode_or_autounlink )); + BOOST_STATIC_ASSERT(( hooktags::safemode_or_autounlink )); return !node_algorithms::unique(this->this_ptr()); } void unlink() { - BOOST_STATIC_ASSERT(( (int)boost_intrusive_tags::link_mode == (int)auto_unlink )); + BOOST_STATIC_ASSERT(( (int)hooktags::link_mode == (int)auto_unlink )); node_algorithms::unlink(this->this_ptr()); node_algorithms::init(this->this_ptr()); } }; -} //namespace detail } //namespace intrusive } //namespace boost 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 5651b4c..be4a015 100644 --- a/include/boost/intrusive/detail/has_member_function_callable_with.hpp +++ b/include/boost/intrusive/detail/has_member_function_callable_with.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2011-2012. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2011-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) // diff --git a/include/boost/intrusive/detail/hashtable_node.hpp b/include/boost/intrusive/detail/hashtable_node.hpp index 86e6074..d9a3c41 100644 --- a/include/boost/intrusive/detail/hashtable_node.hpp +++ b/include/boost/intrusive/detail/hashtable_node.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 @@ -20,11 +20,13 @@ #include #include #include -//#include //remove-me +#include //remove-me #include +#include #include +#include #include -#include +#include namespace boost { @@ -89,6 +91,7 @@ struct bucket_traits_impl typedef typename pointer_traits ::template rebind_pointer < bucket_impl >::type bucket_ptr; + typedef Slist slist; typedef typename Slist::size_type size_type; /// @endcond @@ -100,7 +103,6 @@ struct bucket_traits_impl : buckets_(x.buckets_), buckets_len_(x.buckets_len_) {} - bucket_traits_impl(BOOST_RV_REF(bucket_traits_impl) x) : buckets_(x.buckets_), buckets_len_(x.buckets_len_) { x.buckets_ = bucket_ptr(); x.buckets_len_ = 0; } @@ -127,57 +129,104 @@ struct bucket_traits_impl size_type buckets_len_; }; -template +template +struct hash_reduced_slist_node_traits +{ + template static detail::one test(...); + template static detail::two test(typename U::reduced_slist_node_traits* = 0); + static const bool value = sizeof(test(0)) == sizeof(detail::two); +}; + +template +struct apply_reduced_slist_node_traits +{ + typedef typename NodeTraits::reduced_slist_node_traits type; +}; + +template +struct reduced_slist_node_traits +{ + typedef typename detail::eval_if_c + < hash_reduced_slist_node_traits::value + , apply_reduced_slist_node_traits + , detail::identity + >::type type; +}; + +template +struct get_slist_impl +{ + typedef trivial_value_traits trivial_traits; + + //Reducing symbol length + struct type : make_slist + < typename NodeTraits::node + , boost::intrusive::value_traits + , boost::intrusive::constant_time_size + , boost::intrusive::size_type::difference_type>::type > + >::type + {}; +}; + +} //namespace detail { + +template class hashtable_iterator : public std::iterator < std::forward_iterator_tag - , typename Container::value_type - , typename pointer_traits::difference_type + , typename BucketValueTraits::real_value_traits::value_type + , typename pointer_traits::difference_type , typename detail::add_const_if_c - ::type * + ::type * , typename detail::add_const_if_c - ::type & + ::type & > { - typedef typename Container::real_value_traits real_value_traits; - typedef typename Container::siterator siterator; - typedef typename Container::const_siterator const_siterator; - typedef typename Container::bucket_type bucket_type; + typedef typename BucketValueTraits::real_value_traits real_value_traits; + typedef typename BucketValueTraits::real_bucket_traits real_bucket_traits; + typedef typename real_value_traits::node_traits node_traits; + typedef typename detail::get_slist_impl + ::type + >::type slist_impl; + typedef typename slist_impl::iterator siterator; + typedef typename slist_impl::const_iterator const_siterator; + typedef detail::bucket_impl bucket_type; typedef typename pointer_traits - ::template rebind_pointer - < const Container >::type const_cont_ptr; - typedef typename Container::size_type size_type; + ::template rebind_pointer + < const BucketValueTraits >::type const_bucketvaltraits_ptr; + typedef typename slist_impl::size_type size_type; - static typename Container::node_ptr downcast_bucket(typename bucket_type::node_ptr p) + + static typename node_traits::node_ptr downcast_bucket(typename bucket_type::node_ptr p) { - return pointer_traits:: - pointer_to(static_cast(*p)); + return pointer_traits:: + pointer_to(static_cast(*p)); } public: - typedef typename Container::value_type value_type; - typedef typename detail::add_const_if_c - ::type *pointer; - typedef typename detail::add_const_if_c - ::type &reference; + typedef typename real_value_traits::value_type value_type; + typedef typename detail::add_const_if_c::type *pointer; + typedef typename detail::add_const_if_c::type &reference; hashtable_iterator () {} - explicit hashtable_iterator(siterator ptr, const Container *cont) - : slist_it_ (ptr), cont_ (cont ? pointer_traits::pointer_to(*cont) : const_cont_ptr() ) + explicit hashtable_iterator(siterator ptr, const BucketValueTraits *cont) + : slist_it_ (ptr), traitsptr_ (cont ? pointer_traits::pointer_to(*cont) : const_bucketvaltraits_ptr() ) {} - hashtable_iterator(const hashtable_iterator &other) - : slist_it_(other.slist_it()), cont_(other.get_container()) + hashtable_iterator(const hashtable_iterator &other) + : slist_it_(other.slist_it()), traitsptr_(other.get_bucket_value_traits()) {} const siterator &slist_it() const { return slist_it_; } - hashtable_iterator unconst() const - { return hashtable_iterator(this->slist_it(), this->get_container()); } + hashtable_iterator unconst() const + { return hashtable_iterator(this->slist_it(), this->get_bucket_value_traits()); } public: hashtable_iterator& operator++() @@ -201,48 +250,57 @@ class hashtable_iterator pointer operator->() const { - return boost::intrusive::detail::to_raw_pointer(this->get_real_value_traits()->to_value_ptr + return boost::intrusive::detail::to_raw_pointer(this->priv_real_value_traits().to_value_ptr (downcast_bucket(slist_it_.pointed_node()))); } - const const_cont_ptr &get_container() const - { return cont_; } + const const_bucketvaltraits_ptr &get_bucket_value_traits() const + { return traitsptr_; } - const real_value_traits *get_real_value_traits() const - { return &this->get_container()->get_real_value_traits(); } + const real_value_traits &priv_real_value_traits() const + { return traitsptr_->priv_real_value_traits(); } + + const real_bucket_traits &priv_real_bucket_traits() const + { return traitsptr_->priv_real_bucket_traits(); } private: void increment() { - const Container *cont = boost::intrusive::detail::to_raw_pointer(cont_); - bucket_type* buckets = boost::intrusive::detail::to_raw_pointer(cont->bucket_pointer()); - size_type buckets_len = cont->bucket_count(); + const real_bucket_traits &rbuck_traits = this->priv_real_bucket_traits(); + bucket_type* const buckets = boost::intrusive::detail::to_raw_pointer(rbuck_traits.bucket_begin()); + const size_type buckets_len = rbuck_traits.bucket_count(); ++slist_it_; - if(buckets[0].cend().pointed_node() <= slist_it_.pointed_node() && - slist_it_.pointed_node()<= buckets[buckets_len].cend().pointed_node() ){ - //Now get the bucket_impl from the iterator + const typename slist_impl::node_ptr n = slist_it_.pointed_node(); + const siterator first_bucket_bbegin = buckets->end(); + if(first_bucket_bbegin.pointed_node() <= n && n <= buckets[buckets_len-1].cend().pointed_node()){ + //If one-past the node is inside the bucket then look for the next non-empty bucket + //1. get the bucket_impl from the iterator const bucket_type &b = static_cast (bucket_type::slist_type::container_from_end_iterator(slist_it_)); - //Now just calculate the index b has in the bucket array - size_type n_bucket = static_cast(&b - &buckets[0]); + //2. Now just calculate the index b has in the bucket array + size_type n_bucket = static_cast(&b - buckets); + + //3. Iterate until a non-empty bucket is found do{ - if (++n_bucket == buckets_len){ - slist_it_ = (&buckets[0] + buckets_len)->end(); - break; + if (++n_bucket >= buckets_len){ //bucket overflow, return end() iterator + slist_it_ = buckets->before_begin(); + return; } - slist_it_ = buckets[n_bucket].begin(); } - while (slist_it_ == buckets[n_bucket].end()); + while (buckets[n_bucket].empty()); + slist_it_ = buckets[n_bucket].begin(); + } + else{ + //++slist_it_ yield to a valid object } } - siterator slist_it_; - const_cont_ptr cont_; + siterator slist_it_; + const_bucketvaltraits_ptr traitsptr_; }; -} //namespace detail { } //namespace intrusive { } //namespace boost { diff --git a/include/boost/intrusive/detail/is_stateful_value_traits.hpp b/include/boost/intrusive/detail/is_stateful_value_traits.hpp index 8677c66..c98f6c6 100644 --- a/include/boost/intrusive/detail/is_stateful_value_traits.hpp +++ b/include/boost/intrusive/detail/is_stateful_value_traits.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2009-2012. +// (C) Copyright Ion Gaztanaga 2009-2013. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/intrusive/detail/list_node.hpp b/include/boost/intrusive/detail/list_node.hpp index 32274e6..6f1bdbe 100644 --- a/include/boost/intrusive/detail/list_node.hpp +++ b/include/boost/intrusive/detail/list_node.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 @@ -65,41 +65,41 @@ struct list_node_traits // list_iterator provides some basic functions for a // node oriented bidirectional iterator: -template +template class list_iterator - : public std::iterator - < std::bidirectional_iterator_tag - , typename Container::value_type - , typename Container::difference_type - , typename detail::if_c::type - , typename detail::if_c::type - > + : public iiterator::iterator_base { protected: - typedef typename Container::real_value_traits real_value_traits; - typedef typename real_value_traits::node_traits node_traits; - typedef typename node_traits::node node; - typedef typename node_traits::node_ptr node_ptr; - typedef typename pointer_traits:: - template rebind_pointer::type void_pointer; - static const bool store_container_ptr = - detail::store_cont_ptr_on_it::value; + typedef iiterator + types_t; + + static const bool stateful_value_traits = types_t::stateful_value_traits; + + typedef RealValueTraits real_value_traits; + typedef typename types_t::node_traits node_traits; + + typedef typename types_t::node node; + typedef typename types_t::node_ptr node_ptr; + typedef typename types_t::void_pointer void_pointer; public: - typedef typename Container::value_type value_type; - typedef typename detail::if_c::type pointer; - typedef typename detail::if_c::type reference; + typedef typename types_t::value_type value_type; + typedef typename types_t::pointer pointer; + typedef typename types_t::reference reference; + + typedef typename pointer_traits + ::template rebind_pointer + ::type const_real_value_traits_ptr; list_iterator() - : members_ (node_ptr(), 0) {} - explicit list_iterator(const node_ptr & node, const Container *cont_ptr) - : members_ (node, cont_ptr) + explicit list_iterator(const node_ptr & nodeptr, const const_real_value_traits_ptr &traits_ptr) + : members_(nodeptr, traits_ptr) {} - list_iterator(list_iterator const& other) - : members_(other.pointed_node(), other.get_container()) + list_iterator(list_iterator const& other) + : members_(other.pointed_node(), other.get_real_value_traits()) {} const node_ptr &pointed_node() const @@ -108,12 +108,14 @@ class list_iterator list_iterator &operator=(const node_ptr &node) { members_.nodeptr_ = node; return static_cast(*this); } + const_real_value_traits_ptr get_real_value_traits() const + { return pointer_traits::static_cast_from(members_.get_ptr()); } + public: list_iterator& operator++() { node_ptr p = node_traits::get_next(members_.nodeptr_); members_.nodeptr_ = p; - //members_.nodeptr_ = node_traits::get_next(members_.nodeptr_); return static_cast (*this); } @@ -149,43 +151,11 @@ class list_iterator pointer operator->() const { return this->get_real_value_traits()->to_value_ptr(members_.nodeptr_); } - const Container *get_container() const - { - if(store_container_ptr){ - const Container* c = static_cast(members_.get_ptr()); - BOOST_INTRUSIVE_INVARIANT_ASSERT(c != 0); - return c; - } - else{ - return 0; - } - } - - const real_value_traits *get_real_value_traits() const - { - if(store_container_ptr) - return &this->get_container()->get_real_value_traits(); - else - return 0; - } - - list_iterator unconst() const - { return list_iterator(this->pointed_node(), this->get_container()); } + list_iterator unconst() const + { return list_iterator(this->pointed_node(), this->get_real_value_traits()); } private: - struct members - : public detail::select_constptr - ::type - { - typedef typename detail::select_constptr - ::type Base; - - members(const node_ptr &n_ptr, const void *cont) - : Base(cont), nodeptr_(n_ptr) - {} - - node_ptr nodeptr_; - } members_; + iiterator_members members_; }; } //namespace intrusive diff --git a/include/boost/intrusive/detail/memory_util.hpp b/include/boost/intrusive/detail/memory_util.hpp index 7f69f91..d2a5896 100644 --- a/include/boost/intrusive/detail/memory_util.hpp +++ b/include/boost/intrusive/detail/memory_util.hpp @@ -6,7 +6,7 @@ // ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2011-2012. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2011-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) // diff --git a/include/boost/intrusive/detail/mpl.hpp b/include/boost/intrusive/detail/mpl.hpp index a2d9973..a98435a 100644 --- a/include/boost/intrusive/detail/mpl.hpp +++ b/include/boost/intrusive/detail/mpl.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 diff --git a/include/boost/intrusive/detail/parent_from_member.hpp b/include/boost/intrusive/detail/parent_from_member.hpp index f86a0e7..cf9f379 100644 --- a/include/boost/intrusive/detail/parent_from_member.hpp +++ b/include/boost/intrusive/detail/parent_from_member.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 @@ -30,18 +30,38 @@ inline std::ptrdiff_t offset_from_pointer_to_member(const Member Parent::* ptr_t { //The implementation of a pointer to member is compiler dependent. #if defined(BOOST_INTRUSIVE_MSVC_ABI_PTR_TO_MEMBER) - //msvc compliant compilers use their the first 32 bits as offset (even in 64 bit mode) + + //MSVC compliant compilers use their the first 32 bits as offset (even in 64 bit mode) union caster_union { const Member Parent::* ptr_to_member; boost::int32_t offset; } caster; - caster.ptr_to_member = ptr_to_member; + //MSVC ABI can use up to 3 int32 to represent pointer to member data //with virtual base classes, in those cases there is no simple to - //obtain the address of parent. So static assert to avoid runtime errors + //obtain the address of the parent. So static assert to avoid runtime errors BOOST_STATIC_ASSERT( sizeof(caster) == sizeof(boost::int32_t) ); + + caster.ptr_to_member = ptr_to_member; return std::ptrdiff_t(caster.offset); + //Additional info on MSVC behaviour for the future. For 2/3 int ptr-to-member + //types dereference seems to be: + // + // vboffset = [compile_time_offset if 2-int ptr2memb] / + // [ptr2memb.i32[2] if 3-int ptr2memb]. + // vbtable = *(this + vboffset); + // adj = vbtable[ptr2memb.i32[1]]; + // var = adj + (this + vboffset) + ptr2memb.i32[0]; + // + //To reverse the operation we need to + // - obtain vboffset (in 2-int ptr2memb implementation only) + // - Go to Parent's vbtable and obtain adjustment at index ptr2memb.i32[1] + // - parent = member - adj - vboffset - ptr2memb.i32[0] + // + //Even accessing to RTTI we might not be able to obtain this information + //so anyone who thinks it's possible, please send a patch. + //This works with gcc, msvc, ac++, ibmcpp #elif defined(__GNUC__) || defined(__HP_aCC) || defined(BOOST_INTEL) || \ defined(__IBMCPP__) || defined(__DECCXX) diff --git a/include/boost/intrusive/detail/preprocessor.hpp b/include/boost/intrusive/detail/preprocessor.hpp index 348b104..b3ed6e6 100644 --- a/include/boost/intrusive/detail/preprocessor.hpp +++ b/include/boost/intrusive/detail/preprocessor.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-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) // diff --git a/include/boost/intrusive/detail/rbtree_node.hpp b/include/boost/intrusive/detail/rbtree_node.hpp index 92d9417..793d47f 100644 --- a/include/boost/intrusive/detail/rbtree_node.hpp +++ b/include/boost/intrusive/detail/rbtree_node.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2012. +// (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 @@ -20,6 +20,8 @@ #include #include #include +#include +#include namespace boost { namespace intrusive { diff --git a/include/boost/intrusive/detail/slist_node.hpp b/include/boost/intrusive/detail/slist_node.hpp index ee92919..af124af 100644 --- a/include/boost/intrusive/detail/slist_node.hpp +++ b/include/boost/intrusive/detail/slist_node.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 @@ -15,7 +15,7 @@ #define BOOST_INTRUSIVE_SLIST_NODE_HPP #include -#include +#include #include #include @@ -54,41 +54,41 @@ struct slist_node_traits // slist_iterator provides some basic functions for a // node oriented bidirectional iterator: -template +template class slist_iterator - : public std::iterator - < std::forward_iterator_tag - , typename Container::value_type - , typename Container::difference_type - , typename detail::if_c::type - , typename detail::if_c::type - > + : public iiterator::iterator_base { protected: - typedef typename Container::real_value_traits real_value_traits; - typedef typename real_value_traits::node_traits node_traits; - typedef typename node_traits::node node; - typedef typename node_traits::node_ptr node_ptr; - typedef typename pointer_traits - ::template rebind_pointer ::type void_pointer; - static const bool store_container_ptr = - detail::store_cont_ptr_on_it::value; + typedef iiterator + types_t; + + static const bool stateful_value_traits = types_t::stateful_value_traits; + + typedef RealValueTraits real_value_traits; + typedef typename types_t::node_traits node_traits; + + typedef typename types_t::node node; + typedef typename types_t::node_ptr node_ptr; + typedef typename types_t::void_pointer void_pointer; public: - typedef typename Container::value_type value_type; - typedef typename detail::if_c::type pointer; - typedef typename detail::if_c::type reference; + typedef typename types_t::value_type value_type; + typedef typename types_t::pointer pointer; + typedef typename types_t::reference reference; + + typedef typename pointer_traits + ::template rebind_pointer + ::type const_real_value_traits_ptr; slist_iterator() - : members_ (node_ptr(), 0) {} - explicit slist_iterator(const node_ptr & node, const Container *cont_ptr) - : members_ (node, cont_ptr) + explicit slist_iterator(const node_ptr & nodeptr, const const_real_value_traits_ptr &traits_ptr) + : members_(nodeptr, traits_ptr) {} - slist_iterator(slist_iterator const& other) - : members_(other.pointed_node(), other.get_container()) + slist_iterator(slist_iterator const& other) + : members_(other.pointed_node(), other.get_real_value_traits()) {} const node_ptr &pointed_node() const @@ -97,6 +97,9 @@ class slist_iterator slist_iterator &operator=(const node_ptr &node) { members_.nodeptr_ = node; return static_cast(*this); } + const_real_value_traits_ptr get_real_value_traits() const + { return pointer_traits::static_cast_from(members_.get_ptr()); } + public: slist_iterator& operator++() { @@ -123,39 +126,12 @@ class slist_iterator pointer operator->() const { return this->get_real_value_traits()->to_value_ptr(members_.nodeptr_); } - const Container *get_container() const - { - if(store_container_ptr) - return static_cast(members_.get_ptr()); - else - return 0; - } - - slist_iterator unconst() const - { return slist_iterator(this->pointed_node(), this->get_container()); } - - const real_value_traits *get_real_value_traits() const - { - if(store_container_ptr) - return &this->get_container()->get_real_value_traits(); - else - return 0; - } + slist_iterator unconst() const + { return slist_iterator(this->pointed_node(), this->get_real_value_traits()); } private: - struct members - : public detail::select_constptr - ::type - { - typedef typename detail::select_constptr - ::type Base; - members(const node_ptr &n_ptr, const void *cont) - : Base(cont), nodeptr_(n_ptr) - {} - - node_ptr nodeptr_; - } members_; + iiterator_members members_; }; } //namespace intrusive diff --git a/include/boost/intrusive/detail/transform_iterator.hpp b/include/boost/intrusive/detail/transform_iterator.hpp index 488db9a..808e81a 100644 --- a/include/boost/intrusive/detail/transform_iterator.hpp +++ b/include/boost/intrusive/detail/transform_iterator.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 diff --git a/include/boost/intrusive/detail/tree_node.hpp b/include/boost/intrusive/detail/tree_node.hpp index aa3374e..68891f1 100644 --- a/include/boost/intrusive/detail/tree_node.hpp +++ b/include/boost/intrusive/detail/tree_node.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 @@ -15,8 +15,11 @@ #include #include +#include +#include #include #include +#include namespace boost { namespace intrusive { @@ -77,43 +80,42 @@ struct tree_node_traits // tree_iterator provides some basic functions for a // node oriented bidirectional iterator: -template +template class tree_iterator - : public std::iterator - < std::bidirectional_iterator_tag - , typename Container::value_type - , typename Container::difference_type - , typename detail::if_c::type - , typename detail::if_c::type - > + : public iiterator::iterator_base { protected: - typedef typename Container::real_value_traits real_value_traits; - typedef typename Container::node_algorithms node_algorithms; - typedef typename real_value_traits::node_traits node_traits; - typedef typename node_traits::node node; - typedef typename node_traits::node_ptr node_ptr; - typedef typename pointer_traits::template - rebind_pointer::type void_pointer; - static const bool store_container_ptr = - detail::store_cont_ptr_on_it::value; + typedef iiterator< RealValueTraits, IsConst + , std::bidirectional_iterator_tag> types_t; + + typedef RealValueTraits real_value_traits; + typedef typename types_t::node_traits node_traits; + + typedef typename types_t::node node; + typedef typename types_t::node_ptr node_ptr; + typedef typename types_t::void_pointer void_pointer; + static const bool stateful_value_traits = types_t::stateful_value_traits; + + typedef typename pointer_traits + ::template rebind_pointer + ::type const_real_value_traits_ptr; public: - typedef typename Container::value_type value_type; - typedef typename detail::if_c::type pointer; - typedef typename detail::if_c::type reference; + typedef typename types_t::value_type value_type; + typedef typename types_t::pointer pointer; + typedef typename types_t::reference reference; + typedef bstree_algorithms node_algorithms; tree_iterator() - : members_ (node_ptr(), (const void *)0) {} - explicit tree_iterator(const node_ptr & nodeptr, const Container *cont_ptr) - : members_ (nodeptr, cont_ptr) + explicit tree_iterator(const node_ptr & nodeptr, const const_real_value_traits_ptr &traits_ptr) + : members_(nodeptr, traits_ptr) {} - tree_iterator(tree_iterator const& other) - : members_(other.pointed_node(), other.get_container()) + tree_iterator(tree_iterator const& other) + : members_(other.pointed_node(), other.get_real_value_traits()) {} const node_ptr &pointed_node() const @@ -161,34 +163,21 @@ class tree_iterator pointer operator->() const { return this->get_real_value_traits()->to_value_ptr(members_.nodeptr_); } - const Container *get_container() const - { return static_cast(members_.get_ptr()); } - - const real_value_traits *get_real_value_traits() const - { return &this->get_container()->get_real_value_traits(); } + const_real_value_traits_ptr get_real_value_traits() const + { + return pointer_traits::static_cast_from(members_.get_ptr()); + } tree_iterator end_iterator_from_it() const { - return tree_iterator(node_algorithms::get_header(this->pointed_node()), this->get_container()); + return tree_iterator(node_algorithms::get_header(this->pointed_node()), this->get_real_value_traits()); } - tree_iterator unconst() const - { return tree_iterator(this->pointed_node(), this->get_container()); } + tree_iterator unconst() const + { return tree_iterator(this->pointed_node(), this->get_real_value_traits()); } private: - struct members - : public detail::select_constptr - ::type - { - typedef typename detail::select_constptr - ::type Base; - - members(const node_ptr &n_ptr, const void *cont) - : Base(cont), nodeptr_(n_ptr) - {} - - node_ptr nodeptr_; - } members_; + iiterator_members members_; }; } //namespace intrusive diff --git a/include/boost/intrusive/detail/utilities.hpp b/include/boost/intrusive/detail/utilities.hpp index bb34220..5e6abdb 100644 --- a/include/boost/intrusive/detail/utilities.hpp +++ b/include/boost/intrusive/detail/utilities.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 @@ -29,9 +29,36 @@ #include #include #include +#include +#include namespace boost { namespace intrusive { + +enum algo_types +{ + CircularListAlgorithms, + CircularSListAlgorithms, + LinearSListAlgorithms, + BsTreeAlgorithms, + RbTreeAlgorithms, + AvlTreeAlgorithms, + SgTreeAlgorithms, + SplayTreeAlgorithms, + TreapAlgorithms +}; + +template +struct get_algo; + +template +struct is_safe_autounlink +{ + static const bool value = + (int)link_mode == (int)auto_unlink || + (int)link_mode == (int)safe_link; +}; + namespace detail { template @@ -60,17 +87,12 @@ struct TRAITS_PREFIX##_bool_is_true\ };\ // -BOOST_INTRUSIVE_INTERNAL_STATIC_BOOL_IS_TRUE(internal_base_hook, boost_intrusive_tags::is_base_hook) +BOOST_INTRUSIVE_INTERNAL_STATIC_BOOL_IS_TRUE(internal_base_hook, hooktags::is_base_hook) BOOST_INTRUSIVE_INTERNAL_STATIC_BOOL_IS_TRUE(internal_any_hook, is_any_hook) BOOST_INTRUSIVE_INTERNAL_STATIC_BOOL_IS_TRUE(external_value_traits, external_value_traits) BOOST_INTRUSIVE_INTERNAL_STATIC_BOOL_IS_TRUE(external_bucket_traits, external_bucket_traits) BOOST_INTRUSIVE_INTERNAL_STATIC_BOOL_IS_TRUE(resizable, resizable) -template -struct node_holder - : public Node -{}; - template inline T* to_raw_pointer(T* p) { return p; } @@ -114,7 +136,7 @@ class init_disposer { NodeAlgorithms::init(p); } }; -template +template struct size_holder { static const bool constant_time_size = ConstantSize; @@ -166,17 +188,17 @@ struct size_holder {} }; -template +template struct key_nodeptr_comp : private detail::ebo_functor_holder { - typedef typename Container::real_value_traits real_value_traits; - typedef typename Container::value_type value_type; + typedef RealValueTraits real_value_traits; + typedef typename real_value_traits::value_type value_type; typedef typename real_value_traits::node_ptr node_ptr; typedef typename real_value_traits::const_node_ptr const_node_ptr; typedef detail::ebo_functor_holder base_t; - key_nodeptr_comp(KeyValueCompare kcomp, const Container *cont) - : base_t(kcomp), cont_(cont) + key_nodeptr_comp(KeyValueCompare kcomp, const RealValueTraits *traits) + : base_t(kcomp), traits_(traits) {} template @@ -188,7 +210,7 @@ struct key_nodeptr_comp template const value_type & key_forward (const T &node, typename enable_if_c::value>::type * = 0) const - { return *cont_->get_real_value_traits().to_value_ptr(node); } + { return *traits_->to_value_ptr(node); } template const T & key_forward(const T &key, typename enable_if_c::value>::type* = 0) const @@ -199,27 +221,28 @@ struct key_nodeptr_comp bool operator()(const KeyType &key1, const KeyType2 &key2) const { return base_t::get()(this->key_forward(key1), this->key_forward(key2)); } - const Container *cont_; + const RealValueTraits *traits_; }; -template +template struct node_cloner : private detail::ebo_functor_holder { - typedef typename Container::real_value_traits real_value_traits; - typedef typename Container::node_algorithms node_algorithms; - typedef typename real_value_traits::value_type value_type; - typedef typename real_value_traits::pointer pointer; - typedef typename real_value_traits::node_traits::node node; - typedef typename real_value_traits::node_ptr node_ptr; + typedef RealValueTraits real_value_traits; + typedef typename real_value_traits::node_traits node_traits; + typedef typename node_traits::node_ptr node_ptr; + typedef detail::ebo_functor_holder base_t; + typedef typename get_algo< AlgoType + , node_traits>::type node_algorithms; + static const bool safemode_or_autounlink = + is_safe_autounlink::value; + typedef typename real_value_traits::value_type value_type; + typedef typename real_value_traits::pointer pointer; + typedef typename node_traits::node node; typedef typename real_value_traits::const_node_ptr const_node_ptr; - typedef detail::ebo_functor_holder base_t; - enum { safemode_or_autounlink = - (int)real_value_traits::link_mode == (int)auto_unlink || - (int)real_value_traits::link_mode == (int)safe_link }; - node_cloner(F f, const Container *cont) - : base_t(f), cont_(cont) + node_cloner(F f, const RealValueTraits *traits) + : base_t(f), traits_(traits) {} node_ptr operator()(const node_ptr & p) @@ -228,50 +251,58 @@ struct node_cloner node_ptr operator()(const node &to_clone) { const value_type &v = - *cont_->get_real_value_traits().to_value_ptr + *traits_->to_value_ptr (pointer_traits::pointer_to(to_clone)); - node_ptr n = cont_->get_real_value_traits().to_node_ptr(*base_t::get()(v)); + node_ptr n = traits_->to_node_ptr(*base_t::get()(v)); //Cloned node must be in default mode if the linking mode requires it if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(n)); return n; } - const Container *cont_; + const RealValueTraits *traits_; }; -template +template struct node_disposer : private detail::ebo_functor_holder { - typedef typename Container::real_value_traits real_value_traits; - typedef typename real_value_traits::node_ptr node_ptr; + typedef RealValueTraits real_value_traits; + typedef typename real_value_traits::node_traits node_traits; + typedef typename node_traits::node_ptr node_ptr; typedef detail::ebo_functor_holder base_t; - typedef typename Container::node_algorithms node_algorithms; - enum { safemode_or_autounlink = - (int)real_value_traits::link_mode == (int)auto_unlink || - (int)real_value_traits::link_mode == (int)safe_link }; + typedef typename get_algo< AlgoType + , node_traits>::type node_algorithms; + static const bool safemode_or_autounlink = + is_safe_autounlink::value; - node_disposer(F f, const Container *cont) - : base_t(f), cont_(cont) + node_disposer(F f, const RealValueTraits *cont) + : base_t(f), traits_(cont) {} void operator()(const node_ptr & p) { if(safemode_or_autounlink) node_algorithms::init(p); - base_t::get()(cont_->get_real_value_traits().to_value_ptr(p)); + base_t::get()(traits_->to_value_ptr(p)); } - const Container *cont_; + const RealValueTraits *traits_; }; +template struct dummy_constptr { - dummy_constptr(const void *) + typedef typename boost::intrusive::pointer_traits:: + template rebind_pointer::type ConstVoidPtr; + + explicit dummy_constptr(ConstVoidPtr) {} - const void *get_ptr() const - { return 0; } + dummy_constptr() + {} + + ConstVoidPtr get_ptr() const + { return ConstVoidPtr(); } }; template @@ -280,7 +311,10 @@ struct constptr typedef typename boost::intrusive::pointer_traits:: template rebind_pointer::type ConstVoidPtr; - constptr(const void *ptr) + constptr() + {} + + explicit constptr(const ConstVoidPtr &ptr) : const_void_ptr_(ptr) {} @@ -296,7 +330,7 @@ struct select_constptr typedef typename detail::if_c < store_ptr , constptr - , dummy_constptr + , dummy_constptr >::type type; }; @@ -330,148 +364,6 @@ template void destructor_impl(Hook &, detail::link_dispatch) {} -template -struct base_hook_traits -{ - public: - typedef detail::node_holder - node_holder; - typedef typename NodeTraits::node node; - typedef NodeTraits node_traits; - typedef T value_type; - typedef typename node_traits::node_ptr node_ptr; - typedef typename node_traits::const_node_ptr const_node_ptr; - typedef typename pointer_traits:: - template rebind_pointer::type pointer; - typedef typename pointer_traits:: - template rebind_pointer::type const_pointer; - //typedef typename pointer_traits::reference reference; - //typedef typename pointer_traits::reference const_reference; - typedef T & reference; - typedef const T & const_reference; - typedef node_holder & node_holder_reference; - typedef const node_holder & const_node_holder_reference; - typedef node& node_reference; - typedef const node & const_node_reference; - - static const link_mode_type link_mode = LinkMode; - - static pointer to_value_ptr(const node_ptr & n) - { - return pointer_traits::pointer_to - (static_cast(static_cast(*n))); - } - - static const_pointer to_value_ptr(const const_node_ptr & n) - { - return pointer_traits::pointer_to - (static_cast(static_cast(*n))); - } - - static node_ptr to_node_ptr(reference value) - { - return pointer_traits::pointer_to - (static_cast(static_cast(value))); - } - - static const_node_ptr to_node_ptr(const_reference value) - { - return pointer_traits::pointer_to - (static_cast(static_cast(value))); - } -}; - -template -struct member_hook_traits -{ - public: - typedef Hook hook_type; - typedef typename hook_type::boost_intrusive_tags::node_traits node_traits; - typedef typename node_traits::node node; - typedef T value_type; - typedef typename node_traits::node_ptr node_ptr; - typedef typename node_traits::const_node_ptr const_node_ptr; - typedef typename pointer_traits:: - template rebind_pointer::type pointer; - typedef typename pointer_traits:: - template rebind_pointer::type const_pointer; - typedef T & reference; - typedef const T & const_reference; - typedef node& node_reference; - typedef const node & const_node_reference; - typedef hook_type& hook_reference; - typedef const hook_type & const_hook_reference; - - static const link_mode_type link_mode = Hook::boost_intrusive_tags::link_mode; - - static node_ptr to_node_ptr(reference value) - { - return pointer_traits::pointer_to - (static_cast(static_cast(value.*P))); - } - - static const_node_ptr to_node_ptr(const_reference value) - { - return pointer_traits::pointer_to - (static_cast(static_cast(value.*P))); - } - - static pointer to_value_ptr(const node_ptr & n) - { - return pointer_traits::pointer_to - (*detail::parent_from_member - (static_cast(boost::intrusive::detail::to_raw_pointer(n)), P)); - } - - static const_pointer to_value_ptr(const const_node_ptr & n) - { - return pointer_traits::pointer_to - (*detail::parent_from_member - (static_cast(boost::intrusive::detail::to_raw_pointer(n)), P)); - } -}; - -template -struct function_hook_traits -{ - public: - typedef typename Functor::hook_type hook_type; - typedef typename Functor::hook_ptr hook_ptr; - typedef typename Functor::const_hook_ptr const_hook_ptr; - typedef typename hook_type::boost_intrusive_tags::node_traits node_traits; - typedef typename node_traits::node node; - typedef typename Functor::value_type value_type; - typedef typename node_traits::node_ptr node_ptr; - typedef typename node_traits::const_node_ptr const_node_ptr; - typedef typename pointer_traits:: - template rebind_pointer::type pointer; - typedef typename pointer_traits:: - template rebind_pointer::type const_pointer; - typedef value_type & reference; - typedef const value_type & const_reference; - static const link_mode_type link_mode = hook_type::boost_intrusive_tags::link_mode; - - static node_ptr to_node_ptr(reference value) - { return static_cast(boost::intrusive::detail::to_raw_pointer(Functor::to_hook_ptr(value))); } - - static const_node_ptr to_node_ptr(const_reference value) - { return static_cast(boost::intrusive::detail::to_raw_pointer(Functor::to_hook_ptr(value))); } - - static pointer to_value_ptr(const node_ptr & n) - { return Functor::to_value_ptr(to_hook_ptr(n)); } - - static const_pointer to_value_ptr(const const_node_ptr & n) - { return Functor::to_value_ptr(to_hook_ptr(n)); } - - private: - static hook_ptr to_hook_ptr(const node_ptr & n) - { return hook_ptr(&*static_cast(&*n)); } - - static const_hook_ptr to_hook_ptr(const const_node_ptr & n) - { return const_hook_ptr(&*static_cast(&*n)); } -}; - - //This function uses binary search to discover the //highest set bit of the integer inline std::size_t floor_log2 (std::size_t x) @@ -492,6 +384,8 @@ inline std::size_t floor_log2 (std::size_t x) return log2; } +//Thanks to Laurent de Soras in +//http://www.flipcode.com/archives/Fast_log_Function.shtml inline float fast_log2 (float val) { union caster_t @@ -502,13 +396,15 @@ inline float fast_log2 (float val) caster.val = val; boost::uint32_t x = caster.x; - const int log_2 = (int)(((x >> 23) & 255) - 128); - x &= ~(255 << 23); - x += 127 << 23; + const int log_2 = int((x >> 23) & 255) - 128; + x &= ~(boost::uint32_t(255u) << 23u); + x += boost::uint32_t(127) << 23u; caster.x = x; val = caster.val; + //1+log2(m), m ranging from 1 to 2 + //3rd degree polynomial keeping first derivate continuity. + //For less precision the line can be commented out val = ((-1.0f/3.f) * val + 2.f) * val - (2.0f/3.f); - return (val + log_2); } @@ -605,72 +501,47 @@ class exception_array_disposer } }; -template -struct store_cont_ptr_on_it_impl -{ - static const bool value = is_stateful_value_traits::value; -}; - -template -struct store_cont_ptr_on_it_impl -{ - static const bool value = true; -}; - -template -struct store_cont_ptr_on_it -{ - typedef typename Container::value_traits value_traits; - static const bool value = store_cont_ptr_on_it_impl - ::value>::value; -}; - -template +template struct node_to_value : public detail::select_constptr < typename pointer_traits - ::template rebind_pointer::type - , detail::store_cont_ptr_on_it::value + ::template rebind_pointer::type + , is_stateful_value_traits::value >::type { - static const bool store_container_ptr = - detail::store_cont_ptr_on_it::value; - - typedef typename Container::real_value_traits real_value_traits; - typedef typename real_value_traits::value_type value_type; + static const bool stateful_value_traits = is_stateful_value_traits::value; typedef typename detail::select_constptr < typename pointer_traits - ::template rebind_pointer::type - , store_container_ptr >::type Base; - typedef typename real_value_traits::node_traits::node node; - typedef typename detail::add_const_if_c - ::type vtype; - typedef typename detail::add_const_if_c - ::type ntype; - typedef typename pointer_traits - ::template rebind_pointer::type npointer; + :: + template rebind_pointer::type + , stateful_value_traits >::type Base; - node_to_value(const Container *cont) - : Base(cont) + typedef RealValueTraits real_value_traits; + typedef typename real_value_traits::value_type value_type; + typedef typename real_value_traits::node_traits::node node; + typedef typename detail::add_const_if_c + ::type vtype; + typedef typename detail::add_const_if_c + ::type ntype; + typedef typename pointer_traits + :: + template rebind_pointer::type npointer; + typedef typename pointer_traits:: + template rebind_pointer::type const_real_value_traits_ptr; + + node_to_value(const const_real_value_traits_ptr &ptr) + : Base(ptr) {} typedef vtype & result_type; typedef ntype & first_argument_type; - const Container *get_container() const + const_real_value_traits_ptr get_real_value_traits() const { - if(store_container_ptr) - return static_cast(Base::get_ptr()); + if(stateful_value_traits) + return pointer_traits::static_cast_from(Base::get_ptr()); else - return 0; - } - - const real_value_traits *get_real_value_traits() const - { - if(store_container_ptr) - return &this->get_container()->get_real_value_traits(); - else - return 0; + return const_real_value_traits_ptr(); } result_type operator()(first_argument_type arg) const @@ -849,7 +720,346 @@ class reverse_iterator It m_current; // the wrapped iterator }; +template +struct uncast_types +{ + typedef typename pointer_traits::element_type element_type; + typedef typename remove_const::type non_const_type; + typedef typename pointer_traits:: + template rebind_pointer::type non_const_pointer; + typedef pointer_traits non_const_traits; +}; + +template +static typename uncast_types::non_const_pointer + uncast(const ConstNodePtr & ptr) +{ + return uncast_types::non_const_traits::const_cast_from(ptr); +} + } //namespace detail + +template +struct node_holder + : public Node +{}; + +template +struct bhtraits_base +{ + public: + typedef NodePtr node_ptr; + typedef typename pointer_traits::element_type node; + typedef node_holder node_holder_type; + typedef T value_type; + typedef typename pointer_traits:: + template rebind_pointer::type const_node_ptr; + typedef typename pointer_traits:: + template rebind_pointer::type pointer; + typedef typename pointer_traits:: + template rebind_pointer::type const_pointer; + //typedef typename pointer_traits::reference reference; + //typedef typename pointer_traits::reference const_reference; + typedef T & reference; + typedef const T & const_reference; + typedef node_holder_type & node_holder_reference; + typedef const node_holder_type & const_node_holder_reference; + typedef node& node_reference; + typedef const node & const_node_reference; + + static pointer to_value_ptr(const node_ptr & n) + { + return pointer_traits::pointer_to + (static_cast(static_cast(*n))); + } + + static const_pointer to_value_ptr(const const_node_ptr & n) + { + return pointer_traits::pointer_to + (static_cast(static_cast(*n))); + } + + static node_ptr to_node_ptr(reference value) + { + return pointer_traits::pointer_to + (static_cast(static_cast(value))); + } + + static const_node_ptr to_node_ptr(const_reference value) + { + return pointer_traits::pointer_to + (static_cast(static_cast(value))); + } +}; + +template +struct bhtraits + : public bhtraits_base +{ + static const link_mode_type link_mode = LinkMode; + typedef NodeTraits node_traits; +}; + +/* +template::element_type T::* P> +struct mhtraits_base +{ + public: + typedef typename pointer_traits::element_type node; + typedef T value_type; + typedef NodePtr node_ptr; + typedef typename pointer_traits:: + template rebind_pointer::type const_node_ptr; + typedef typename pointer_traits:: + template rebind_pointer::type pointer; + typedef typename pointer_traits:: + template rebind_pointer::type const_pointer; + typedef T & reference; + typedef const T & const_reference; + typedef node& node_reference; + typedef const node & const_node_reference; + + static node_ptr to_node_ptr(reference value) + { + return pointer_traits::pointer_to + (static_cast(value.*P)); + } + + static const_node_ptr to_node_ptr(const_reference value) + { + return pointer_traits::pointer_to + (static_cast(value.*P)); + } + + static pointer to_value_ptr(const node_ptr & n) + { + return pointer_traits::pointer_to + (*detail::parent_from_member + (boost::intrusive::detail::to_raw_pointer(n), P)); + } + + static const_pointer to_value_ptr(const const_node_ptr & n) + { + return pointer_traits::pointer_to + (*detail::parent_from_member + (boost::intrusive::detail::to_raw_pointer(n), P)); + } +}; + + +template +struct mhtraits + : public mhtraits_base +{ + static const link_mode_type link_mode = LinkMode; + typedef NodeTraits node_traits; +}; +*/ + + +template +struct mhtraits +{ + public: + typedef Hook hook_type; + typedef typename hook_type::hooktags::node_traits node_traits; + typedef typename node_traits::node node; + typedef T value_type; + typedef typename node_traits::node_ptr node_ptr; + typedef typename node_traits::const_node_ptr const_node_ptr; + typedef typename pointer_traits:: + template rebind_pointer::type pointer; + typedef typename pointer_traits:: + template rebind_pointer::type const_pointer; + typedef T & reference; + typedef const T & const_reference; + typedef node& node_reference; + typedef const node & const_node_reference; + typedef hook_type& hook_reference; + typedef const hook_type & const_hook_reference; + + static const link_mode_type link_mode = Hook::hooktags::link_mode; + + static node_ptr to_node_ptr(reference value) + { + return pointer_traits::pointer_to + (static_cast(static_cast(value.*P))); + } + + static const_node_ptr to_node_ptr(const_reference value) + { + return pointer_traits::pointer_to + (static_cast(static_cast(value.*P))); + } + + static pointer to_value_ptr(const node_ptr & n) + { + return pointer_traits::pointer_to + (*detail::parent_from_member + (static_cast(boost::intrusive::detail::to_raw_pointer(n)), P)); + } + + static const_pointer to_value_ptr(const const_node_ptr & n) + { + return pointer_traits::pointer_to + (*detail::parent_from_member + (static_cast(boost::intrusive::detail::to_raw_pointer(n)), P)); + } +}; + + +template +struct fhtraits +{ + public: + typedef typename Functor::hook_type hook_type; + typedef typename Functor::hook_ptr hook_ptr; + typedef typename Functor::const_hook_ptr const_hook_ptr; + typedef typename hook_type::hooktags::node_traits node_traits; + typedef typename node_traits::node node; + typedef typename Functor::value_type value_type; + typedef typename node_traits::node_ptr node_ptr; + typedef typename node_traits::const_node_ptr const_node_ptr; + typedef typename pointer_traits:: + template rebind_pointer::type pointer; + typedef typename pointer_traits:: + template rebind_pointer::type const_pointer; + typedef value_type & reference; + typedef const value_type & const_reference; + static const link_mode_type link_mode = hook_type::hooktags::link_mode; + + static node_ptr to_node_ptr(reference value) + { return static_cast(boost::intrusive::detail::to_raw_pointer(Functor::to_hook_ptr(value))); } + + static const_node_ptr to_node_ptr(const_reference value) + { return static_cast(boost::intrusive::detail::to_raw_pointer(Functor::to_hook_ptr(value))); } + + static pointer to_value_ptr(const node_ptr & n) + { return Functor::to_value_ptr(to_hook_ptr(n)); } + + static const_pointer to_value_ptr(const const_node_ptr & n) + { return Functor::to_value_ptr(to_hook_ptr(n)); } + + private: + static hook_ptr to_hook_ptr(const node_ptr & n) + { return hook_ptr(&*static_cast(&*n)); } + + static const_hook_ptr to_hook_ptr(const const_node_ptr & n) + { return const_hook_ptr(&*static_cast(&*n)); } +}; + +template +struct iiterator +{ + typedef RealValueTraits real_value_traits; + typedef typename real_value_traits::node_traits node_traits; + typedef typename node_traits::node node; + typedef typename node_traits::node_ptr node_ptr; + typedef ::boost::intrusive::pointer_traits nodepointer_traits_t; + typedef typename nodepointer_traits_t::template + rebind_pointer::type void_pointer; + typedef typename RealValueTraits::value_type value_type; + typedef typename RealValueTraits::pointer nonconst_pointer; + typedef typename RealValueTraits::const_pointer yesconst_pointer; + typedef typename ::boost::intrusive::pointer_traits + ::reference nonconst_reference; + typedef typename ::boost::intrusive::pointer_traits + ::reference yesconst_reference; + typedef typename nodepointer_traits_t::difference_type difference_type; + typedef typename detail::if_c + ::type pointer; + typedef typename detail::if_c + ::type reference; + typedef std::iterator + < Category + , value_type + , difference_type + , pointer + , reference + > iterator_base; + static const bool stateful_value_traits = + detail::is_stateful_value_traits::value; +}; + +template +struct iiterator_members +{ + typedef ::boost::intrusive::pointer_traits pointer_traits_t; + typedef typename pointer_traits_t::template + rebind_pointer::type const_void_pointer; + + iiterator_members() + {} + + iiterator_members(const NodePtr &n_ptr, const const_void_pointer &data) + : nodeptr_(n_ptr), ptr_(data) + {} + + const_void_pointer get_ptr() const + { return ptr_; } + + NodePtr nodeptr_; + const_void_pointer ptr_; +}; + +template +struct iiterator_members +{ + typedef ::boost::intrusive::pointer_traits pointer_traits_t; + typedef typename pointer_traits_t::template + rebind_pointer::type const_void_pointer; + + iiterator_members() + {} + + iiterator_members(const NodePtr &n_ptr, const const_void_pointer &) + : nodeptr_(n_ptr) + {} + + const_void_pointer get_ptr() const + { return const_void_pointer(); } + + NodePtr nodeptr_; +}; + +template +struct get_less +{ + typedef Less type; +}; + +template +struct get_less +{ + typedef ::std::less type; +}; + +template +struct get_equal_to +{ + typedef EqualTo type; +}; + +template +struct get_equal_to +{ + typedef ::std::equal_to type; +}; + +template +struct get_hash +{ + typedef Hash type; +}; + +template +struct get_hash +{ + typedef ::boost::hash type; +}; + +struct empty{}; + } //namespace intrusive } //namespace boost diff --git a/include/boost/intrusive/detail/workaround.hpp b/include/boost/intrusive/detail/workaround.hpp index 123fb9f..71a50c8 100644 --- a/include/boost/intrusive/detail/workaround.hpp +++ b/include/boost/intrusive/detail/workaround.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-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) // @@ -17,6 +17,10 @@ #define BOOST_INTRUSIVE_PERFECT_FORWARDING #endif +//Macros for documentation purposes. For code, expands to the argument +#define BOOST_INTRUSIVE_IMPDEF(TYPE) TYPE +#define BOOST_INTRUSIVE_SEEDOC(TYPE) TYPE + #include #endif //#ifndef BOOST_INTRUSIVE_DETAIL_WRKRND_HPP diff --git a/include/boost/intrusive/hashtable.hpp b/include/boost/intrusive/hashtable.hpp index eaf834c..bf1f18f 100644 --- a/include/boost/intrusive/hashtable.hpp +++ b/include/boost/intrusive/hashtable.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 @@ -32,12 +32,10 @@ #include #include //Implementation utilities -#include #include #include #include #include -#include #include namespace boost { @@ -45,8 +43,6 @@ namespace intrusive { /// @cond -namespace detail { - struct hash_bool_flags { static const std::size_t unique_keys_pos = 1u; @@ -57,99 +53,13 @@ struct hash_bool_flags static const std::size_t incremental_pos = 32u; }; -template - < class ValueTraits - , class Hash - , class Equal - , class SizeType - , class BucketTraits - , std::size_t BoolFlags - > -struct usetopt -{ - typedef ValueTraits value_traits; - typedef Hash hash; - typedef Equal equal; - typedef SizeType size_type; - typedef BucketTraits bucket_traits; - static const std::size_t bool_flags = BoolFlags; -}; - -template - < class UsetOpt - , std::size_t BoolMask - > -struct usetopt_mask -{ - typedef usetopt - type; -}; - -template -struct hash_reduced_slist_node_traits -{ - template static detail::one test(...); - template static detail::two test(typename U::reduced_slist_node_traits* = 0); - static const bool value = sizeof(test(0)) == sizeof(detail::two); -}; - -template -struct apply_reduced_slist_node_traits -{ - typedef typename NodeTraits::reduced_slist_node_traits type; -}; - -template -struct reduced_slist_node_traits -{ - typedef typename detail::eval_if_c - < hash_reduced_slist_node_traits::value - , apply_reduced_slist_node_traits - , detail::identity - >::type type; -}; - -template -struct get_slist_impl -{ - typedef trivial_value_traits trivial_traits; - - //Reducing symbol length - struct type : make_slist - < typename NodeTraits::node - , boost::intrusive::value_traits - , boost::intrusive::constant_time_size - , boost::intrusive::size_type::difference_type>::type > - >::type - {}; -}; - -template -struct real_from_supposed_value_traits -{ - typedef typename detail::eval_if_c - < detail::external_value_traits_bool_is_true - ::value - , detail::eval_value_traits - - , detail::identity - - >::type type; -}; +namespace detail { template struct get_slist_impl_from_supposed_value_traits { - typedef typename - real_from_supposed_value_traits - < SupposedValueTraits>::type real_value_traits; + typedef typename detail::get_real_value_traits + ::type real_value_traits; typedef typename detail::get_node_traits ::type node_traits; typedef typename get_slist_impl @@ -214,135 +124,19 @@ struct optimize_multikey_is_true static const bool value = optimize_multikey_bool::value > sizeof(one)*2; }; -template -struct bucket_plus_size - : public detail::size_holder //size_traits - < 0 != (Config::bool_flags & hash_bool_flags::constant_time_size_pos) - , typename Config::size_type> -{ - typedef detail::size_holder - < 0 != (Config::bool_flags & hash_bool_flags::constant_time_size_pos) - , typename Config::size_type> size_traits; - typedef typename Config::bucket_traits bucket_traits; - - template - bucket_plus_size(BOOST_FWD_REF(BucketTraits) b_traits) - : bucket_traits_(::boost::forward(b_traits)) - {} - - bucket_plus_size & operator =(const bucket_plus_size &x) - { - this->size_traits::operator=(x); - bucket_traits_ = x.bucket_traits_; - return *this; - } - bucket_traits bucket_traits_; -}; - -template -struct bucket_hash_t - : public detail::ebo_functor_holder //hash -{ - typedef typename Config::hash hasher; - typedef detail::size_holder - < 0 != (Config::bool_flags & hash_bool_flags::constant_time_size_pos) - , typename Config::size_type> size_traits; - typedef typename Config::bucket_traits bucket_traits; - - template - bucket_hash_t(BOOST_FWD_REF(BucketTraits) b_traits, const hasher & h) - : detail::ebo_functor_holder(h), bucket_plus_size_(::boost::forward(b_traits)) - {} - - bucket_plus_size bucket_plus_size_; -}; - -template -struct bucket_hash_equal_t - : public detail::ebo_functor_holder -{ - typedef typename Config::equal equal; - typedef typename Config::hash hasher; - typedef typename Config::bucket_traits bucket_traits; - - template - bucket_hash_equal_t(BOOST_FWD_REF(BucketTraits) b_traits, const hasher & h, const equal &e) - : detail::ebo_functor_holder(e)//equal() - , bucket_hash(::boost::forward(b_traits), h) - {} - - template - void set_cache(T) - {} - - bucket_hash_t bucket_hash; -}; - -template //cache_begin == true version -struct bucket_hash_equal_t - : public detail::ebo_functor_holder -{ - typedef typename Config::equal equal; - typedef typename Config::hash hasher; - typedef typename Config::bucket_traits bucket_traits; - typedef typename unordered_bucket_ptr_impl - ::type bucket_ptr; - - template - bucket_hash_equal_t(BOOST_FWD_REF(BucketTraits) b_traits, const hasher & h, const equal &e) - : detail::ebo_functor_holder(e) //equal() - , bucket_hash(::boost::forward(b_traits), h) - {} - - void set_cache(const bucket_ptr & c) - { cached_begin_ = c; } - - bucket_hash_t bucket_hash; - bucket_ptr cached_begin_; -}; - -template -struct hashtable_data_t : public Config::value_traits -{ - static const std::size_t bool_flags = Config::bool_flags; - typedef typename Config::value_traits value_traits; - typedef typename Config::equal equal; - typedef typename Config::hash hasher; - typedef typename Config::bucket_traits bucket_traits; - - template - hashtable_data_t( BOOST_FWD_REF(BucketTraits) b_traits, const hasher & h - , const equal &e, const value_traits &val_traits) - : Config::value_traits(val_traits) //value_traits - , internal_(::boost::forward(b_traits), h, e) - {} - typedef typename detail::usetopt_mask - < Config - , detail::hash_bool_flags::constant_time_size_pos - | detail::hash_bool_flags::incremental_pos - >::type masked_config_t; - struct internal - : public detail::size_holder //split_traits - < 0 != (Config::bool_flags & hash_bool_flags::incremental_pos) - , typename Config::size_type> - { - template - internal(BOOST_FWD_REF(BucketTraits) b_traits, const hasher & h, const equal &e) - : bucket_hash_equal_(::boost::forward(b_traits), h, e) - {} - - bucket_hash_equal_t - < masked_config_t - , 0 != (bool_flags & hash_bool_flags::cache_begin_pos) - > bucket_hash_equal_; - } internal_; -}; - struct insert_commit_data_impl { std::size_t hash; }; +template +inline typename pointer_traits::template rebind_pointer::type + dcast_bucket_ptr(const SlistNodePtr &p) +{ + typedef typename pointer_traits::template rebind_pointer::type node_ptr; + return pointer_traits::pointer_to(static_cast(*p)); +} + template struct group_functions { @@ -356,9 +150,6 @@ struct group_functions typedef typename reduced_node_traits::node slist_node; typedef circular_slist_algorithms group_algorithms; - static node_ptr dcast_bucket_ptr(const slist_node_ptr &p) - { return pointer_traits::pointer_to(static_cast(*p)); } - static slist_node_ptr get_bucket_before_begin (const slist_node_ptr &bucket_beg, const slist_node_ptr &bucket_end, const node_ptr &p) { @@ -384,7 +175,7 @@ struct group_functions slist_node_ptr possible_end = node_traits::get_next(last_node_group); while(!(bucket_beg <= possible_end && possible_end <= bucket_end)){ - first_node_of_group = group_functions::dcast_bucket_ptr(possible_end); + first_node_of_group = detail::dcast_bucket_ptr(possible_end); last_node_group = group_traits::get_next(first_node_of_group); possible_end = node_traits::get_next(last_node_group); } @@ -395,7 +186,7 @@ struct group_functions { //Just iterate using group links and obtain the node //before "first_in_group)" - node_ptr prev_node = group_functions::dcast_bucket_ptr(bucket_node); + node_ptr prev_node = detail::dcast_bucket_ptr(bucket_node); node_ptr nxt(node_traits::get_next(prev_node)); while(nxt != first_in_group){ prev_node = group_traits::get_next(nxt); @@ -480,7 +271,7 @@ struct group_functions , const slist_node_ptr &first_end_ptr, const slist_node_ptr &last_end_ptr) { slist_node_ptr prev; - node_ptr elem(group_functions::dcast_bucket_ptr(i)); + node_ptr elem(detail::dcast_bucket_ptr(i)); //It's the last in group if the next_node is a bucket slist_node_ptr nxt(node_traits::get_next(elem)); @@ -575,6 +366,22 @@ struct node_functions {} }; +inline std::size_t hash_to_bucket(std::size_t hash_value, std::size_t bucket_cnt, detail::false_) +{ return hash_value % bucket_cnt; } + +inline std::size_t hash_to_bucket(std::size_t hash_value, std::size_t bucket_cnt, detail::true_) +{ return hash_value & (bucket_cnt - 1); } + +template +inline std::size_t hash_to_bucket_split(std::size_t hash_value, std::size_t bucket_cnt, std::size_t split) +{ + std::size_t bucket_number = detail::hash_to_bucket(hash_value, bucket_cnt, detail::bool_()); + if(Incremental) + if(bucket_number >= split) + bucket_number -= bucket_cnt/2; + return bucket_number; +} + } //namespace detail { //!This metafunction will obtain the type of a bucket @@ -584,7 +391,7 @@ template struct unordered_bucket : public detail::unordered_bucket_impl ::value_traits + template pack::proto_value_traits > {}; @@ -595,7 +402,7 @@ template struct unordered_bucket_ptr : public detail::unordered_bucket_ptr_impl ::value_traits + template pack::proto_value_traits > {}; @@ -607,7 +414,7 @@ template struct unordered_default_bucket_traits { typedef typename ValueTraitsOrHookOption:: - template pack::value_traits supposed_value_traits; + template pack::proto_value_traits supposed_value_traits; typedef typename detail:: get_slist_impl_from_supposed_value_traits ::type slist_impl; @@ -618,28 +425,630 @@ struct unordered_default_bucket_traits struct default_bucket_traits; -template -struct uset_defaults - : pack_options - < none - , base_hook - , constant_time_size - , size_type - , equal > - , hash > - , bucket_traits - , power_2_buckets - , cache_begin - , compare_hash - , incremental - >::type -{}; +struct hashtable_defaults +{ + typedef detail::default_hashtable_hook proto_value_traits; + typedef std::size_t size_type; + typedef void equal; + typedef void hash; + typedef default_bucket_traits bucket_traits; + static const bool constant_time_size = true; + static const bool power_2_buckets = false; + static const bool cache_begin = false; + static const bool compare_hash = false; + static const bool incremental = false; +}; + +template +struct downcast_node_to_value_t + : public detail::node_to_value +{ + typedef detail::node_to_value base_t; + typedef typename base_t::result_type result_type; + typedef RealValueTraits real_value_traits; + typedef typename detail::get_slist_impl + ::type + >::type slist_impl; + typedef typename detail::add_const_if_c + ::type & first_argument_type; + typedef typename detail::add_const_if_c + < typename RealValueTraits::node_traits::node + , IsConst>::type & intermediate_argument_type; + typedef typename pointer_traits + :: + template rebind_pointer + ::type const_real_value_traits_ptr; + + downcast_node_to_value_t(const const_real_value_traits_ptr &ptr) + : base_t(ptr) + {} + + result_type operator()(first_argument_type arg) const + { return this->base_t::operator()(static_cast(arg)); } +}; + +template +struct node_cast_adaptor + : private detail::ebo_functor_holder +{ + typedef detail::ebo_functor_holder base_t; + + typedef typename pointer_traits::element_type slist_node; + typedef typename pointer_traits::element_type node; + + template + node_cast_adaptor(const ConvertibleToF &c2f, const RealValuTraits *traits) + : base_t(base_t(c2f, traits)) + {} + + typename base_t::node_ptr operator()(const slist_node &to_clone) + { return base_t::operator()(static_cast(to_clone)); } + + void operator()(SlistNodePtr to_clone) + { + base_t::operator()(pointer_traits::pointer_to(static_cast(*to_clone))); + } +}; + +static const std::size_t hashtable_data_bool_flags_mask = + ( hash_bool_flags::cache_begin_pos + | hash_bool_flags::constant_time_size_pos + | hash_bool_flags::incremental_pos + ); + +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 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; + + template + bucket_plus_vtraits(const ValueTraits &val_traits, BOOST_FWD_REF(BucketTraitsType) b_traits) + : ValueTraits(val_traits), bucket_traits_(::boost::forward(b_traits)) + {} + + bucket_plus_vtraits & operator =(const bucket_plus_vtraits &x) + { + 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_()); } + + //bucket_value_traits + // + const bucket_plus_vtraits &get_bucket_value_traits() const + { return *this; } + + 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()); } + + //value traits + // + const value_traits &priv_value_traits() const + { return *this; } + + value_traits &priv_value_traits() + { return *this; } + + //bucket_traits + // + const bucket_traits &priv_bucket_traits() const + { return this->bucket_traits_; } + + bucket_traits &priv_bucket_traits() + { return this->bucket_traits_; } + + //operations + typedef typename detail::unordered_bucket_ptr_impl::type bucket_ptr; + + bucket_ptr priv_bucket_pointer() const + { return this->priv_real_bucket_traits().bucket_begin(); } + + typename slist_impl::size_type priv_bucket_count() const + { return this->priv_real_bucket_traits().bucket_count(); } + + bucket_ptr priv_invalid_bucket() const + { + const real_bucket_traits &rbt = this->priv_real_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(); + } + + /// + static siterator priv_get_last(bucket_type &b, detail::true_) //optimize multikey + { + //First find the last node of p's group. + //This requires checking the first node of the next group or + //the bucket node. + slist_node_ptr end_ptr(b.end().pointed_node()); + node_ptr possible_end(node_traits::get_next( detail::dcast_bucket_ptr(end_ptr))); + node_ptr last_node_group(possible_end); + + while(end_ptr != possible_end){ + last_node_group = group_traits::get_next(detail::dcast_bucket_ptr(possible_end)); + possible_end = node_traits::get_next(last_node_group); + } + return bucket_type::s_iterator_to(*last_node_group); + } + + static siterator priv_get_last(bucket_type &b, detail::false_) //NOT optimize multikey + { return b.previous(b.end()); } + + static siterator priv_get_previous(bucket_type &b, siterator i, detail::true_) //optimize multikey + { + node_ptr elem(detail::dcast_bucket_ptr(i.pointed_node())); + node_ptr prev_in_group(group_traits::get_next(elem)); + bool first_in_group = node_traits::get_next(prev_in_group) != elem; + typename bucket_type::node &n = first_in_group + ? *group_functions_t::get_prev_to_first_in_group(b.end().pointed_node(), elem) + : *group_traits::get_next(elem) + ; + return bucket_type::s_iterator_to(n); + } + + static siterator priv_get_previous(bucket_type &b, siterator i, detail::false_) //NOT optimize multikey + { return b.previous(i); } + + static void priv_clear_group_nodes(bucket_type &b, detail::true_) //optimize multikey + { + siterator it(b.begin()), itend(b.end()); + while(it != itend){ + node_ptr to_erase(detail::dcast_bucket_ptr(it.pointed_node())); + ++it; + group_algorithms::init(to_erase); + } + } + + static void priv_clear_group_nodes(bucket_type &, detail::false_) //NOT optimize multikey + {} + + std::size_t priv_get_bucket_num_no_hash_store(siterator it, detail::true_) //optimize multikey + { + const bucket_ptr f(this->priv_bucket_pointer()), l(f + this->priv_bucket_count() - 1); + slist_node_ptr bb = group_functions_t::get_bucket_before_begin + ( f->end().pointed_node() + , l->end().pointed_node() + , detail::dcast_bucket_ptr(it.pointed_node())); + //Now get the bucket_impl from the iterator + const bucket_type &b = static_cast + (bucket_type::slist_type::container_from_end_iterator(bucket_type::s_iterator_to(*bb))); + //Now just calculate the index b has in the bucket array + return static_cast(&b - &*f); + } + + std::size_t priv_get_bucket_num_no_hash_store(siterator it, detail::false_) //NO optimize multikey + { + bucket_ptr f(this->priv_bucket_pointer()), l(f + this->priv_bucket_count() - 1); + slist_node_ptr first_ptr(f->cend().pointed_node()) + , last_ptr(l->cend().pointed_node()); + + //The end node is embedded in the singly linked list: + //iterate until we reach it. + while(!(first_ptr <= it.pointed_node() && it.pointed_node() <= last_ptr)){ + ++it; + } + //Now get the bucket_impl from the iterator + const bucket_type &b = static_cast + (bucket_type::container_from_end_iterator(it)); + + //Now just calculate the index b has in the bucket array + return static_cast(&b - &*f); + } + + 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; + } + + node &priv_value_to_node(value_type &v) + { return *this->priv_real_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); } + + 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)); } + + 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)); } + + bucket_traits bucket_traits_; +}; + +template +struct bucket_hash_t + : public detail::ebo_functor_holder + ::real_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 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)) + {} + + const hasher &priv_hasher() const + { return this->detail::ebo_functor_holder::get(); } + + hasher &priv_hasher() + { 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)); } + + std::size_t priv_stored_or_compute_hash(const value_type &v, detail::false_) const //For store_hash == false + { return this->priv_hasher()(v); } +}; + +template +struct bucket_hash_equal_t + : public detail::ebo_functor_holder //equal + ::real_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 typename get_equal_to< VoidOrKeyEqual + , typename real_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; + + 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) + {} + + bucket_ptr priv_get_cache() + { return this->priv_bucket_pointer(); } + + void priv_set_cache(const bucket_ptr &) + {} + + size_type priv_get_cache_bucket_num() + { return 0u; } + + void priv_initialize_cache() + {} + + void priv_swap_cache(bucket_hash_equal_t &) + {} + + siterator priv_begin() const + { + size_type n = 0; + size_type bucket_cnt = this->priv_bucket_count(); + for (n = 0; n < bucket_cnt; ++n){ + bucket_type &b = this->priv_bucket_pointer()[n]; + if(!b.empty()){ + return b.begin(); + } + } + return this->priv_invalid_local_it(); + } + + void priv_insertion_update_cache(size_type) + {} + + void priv_erasure_update_cache_range(size_type, size_type) + {} + + void priv_erasure_update_cache() + {} + + const value_equal &priv_equal() const + { return this->detail::ebo_functor_holder::get(); } + + value_equal &priv_equal() + { return this->detail::ebo_functor_holder::get(); } +}; + +template //cache_begin == true version +struct bucket_hash_equal_t + : public detail::ebo_functor_holder //equal + ::real_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; + + 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) + {} + + typedef typename detail::unordered_bucket_ptr_impl + ::type bucket_ptr; + + bucket_ptr &priv_get_cache() + { return cached_begin_; } + + const bucket_ptr &priv_get_cache() const + { return cached_begin_; } + + void priv_set_cache(const bucket_ptr &p) + { cached_begin_ = p; } + + std::size_t priv_get_cache_bucket_num() + { return this->cached_begin_ - this->priv_bucket_pointer(); } + + void priv_initialize_cache() + { this->cached_begin_ = this->priv_invalid_bucket(); } + + void priv_swap_cache(bucket_hash_equal_t &other) + { + std::swap(this->cached_begin_, other.cached_begin_); + } + + siterator priv_begin() const + { + if(this->cached_begin_ == this->priv_invalid_bucket()){ + return this->priv_invalid_local_it(); + } + else{ + return this->cached_begin_->begin(); + } + } + + void priv_insertion_update_cache(size_type insertion_bucket) + { + bucket_ptr p = this->priv_bucket_pointer() + insertion_bucket; + if(p < this->cached_begin_){ + this->cached_begin_ = p; + } + } + + const value_equal &priv_equal() const + { return this->detail::ebo_functor_holder::get(); } + + value_equal &priv_equal() + { return this->detail::ebo_functor_holder::get(); } + + void priv_erasure_update_cache_range(size_type first_bucket_num, size_type last_bucket_num) + { + //If the last bucket is the end, the cache must be updated + //to the last position if all + if(this->priv_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->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() + ; current_n < num_buckets + ; ++current_n, ++this->priv_get_cache()){ + if(!this->priv_get_cache()->empty()){ + return; + } + } + this->priv_initialize_cache(); + } + } + + private: + bucket_ptr cached_begin_; +}; + +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 + , 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; + + 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) + {} + + 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; } +}; + +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> +{ + static const std::size_t bool_flags = BoolFlags; + typedef detail::size_holder + < 0 != (BoolFlags & hash_bool_flags::constant_time_size_pos) + , 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; + 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; } + + 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) + {} +}; /// @endcond //! The class template hashtable is an intrusive hash table container, that //! is used to construct intrusive unordered_set and unordered_multiset containers. The -//! no-throw guarantee holds only, if the Equal object and Hasher don't throw. +//! no-throw guarantee holds only, if the VoidOrKeyEqual object and Hasher don't throw. //! //! hashtable is a semi-intrusive container: each object to be stored in the //! container must contain a proper hook, but the container also needs @@ -676,35 +1085,41 @@ struct uset_defaults #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class hashtable_impl - : private detail::clear_on_destructor_base > + : public hashtable_data_t + < SizeType + , BoolFlags & hashtable_data_bool_flags_mask + , VoidOrKeyHash, VoidOrKeyEqual, ValueTraits, BucketTraits> + , private detail::clear_on_destructor_base > { template friend class detail::clear_on_destructor_base; public: - typedef typename Config::value_traits value_traits; + typedef ValueTraits value_traits; + + typedef hashtable_data_t + < SizeType + , BoolFlags & hashtable_data_bool_flags_mask + , VoidOrKeyHash, VoidOrKeyEqual, ValueTraits, BucketTraits> data_type; /// @cond - static const bool external_value_traits = - detail::external_value_traits_bool_is_true::value; - typedef typename detail::eval_if_c - < external_value_traits - , detail::eval_value_traits - , detail::identity - >::type real_value_traits; - typedef typename Config::bucket_traits bucket_traits; - static const bool external_bucket_traits = - detail::external_bucket_traits_bool_is_true::value; - typedef typename detail::eval_if_c - < external_bucket_traits - , detail::eval_bucket_traits - , detail::identity - >::type real_bucket_traits; + 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; + >::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; + + /// @endcond typedef typename real_value_traits::pointer pointer; @@ -713,18 +1128,18 @@ class hashtable_impl typedef typename pointer_traits::reference reference; typedef typename pointer_traits::reference const_reference; typedef typename pointer_traits::difference_type difference_type; - typedef typename Config::size_type size_type; + typedef SizeType size_type; typedef value_type key_type; - typedef typename Config::equal key_equal; - typedef typename Config::hash hasher; + typedef typename data_type::value_equal key_equal; + typedef typename data_type::hasher hasher; typedef detail::bucket_impl bucket_type; typedef typename pointer_traits ::template rebind_pointer < bucket_type >::type bucket_ptr; typedef typename slist_impl::iterator siterator; typedef typename slist_impl::const_iterator const_siterator; - typedef detail::hashtable_iterator iterator; - typedef detail::hashtable_iterator const_iterator; + typedef hashtable_iterator iterator; + typedef hashtable_iterator const_iterator; typedef typename real_value_traits::node_traits node_traits; typedef typename node_traits::node node; typedef typename pointer_traits @@ -738,12 +1153,12 @@ class hashtable_impl 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 != (Config::bool_flags & detail::hash_bool_flags::unique_keys_pos); - static const bool constant_time_size = 0 != (Config::bool_flags & detail::hash_bool_flags::constant_time_size_pos); - static const bool cache_begin = 0 != (Config::bool_flags & detail::hash_bool_flags::cache_begin_pos); - static const bool compare_hash = 0 != (Config::bool_flags & detail::hash_bool_flags::compare_hash_pos); - static const bool incremental = 0 != (Config::bool_flags & detail::hash_bool_flags::incremental_pos); - static const bool power_2_buckets = incremental || (0 != (Config::bool_flags & detail::hash_bool_flags::power_2_buckets_pos)); + static const bool unique_keys = 0 != (BoolFlags & hash_bool_flags::unique_keys_pos); + static const bool constant_time_size = 0 != (BoolFlags & hash_bool_flags::constant_time_size_pos); + static const bool cache_begin = 0 != (BoolFlags & hash_bool_flags::cache_begin_pos); + static const bool compare_hash = 0 != (BoolFlags & hash_bool_flags::compare_hash_pos); + static const bool incremental = 0 != (BoolFlags & hash_bool_flags::incremental_pos); + static const bool power_2_buckets = incremental || (0 != (BoolFlags & hash_bool_flags::power_2_buckets_pos)); static const bool optimize_multikey = detail::optimize_multikey_is_true::value && !unique_keys; @@ -768,65 +1183,15 @@ class hashtable_impl typedef detail::bool_ cache_begin_t; typedef detail::bool_ power_2_buckets_t; typedef detail::size_holder size_traits; - typedef detail::size_holder split_traits; + typedef detail::size_holder split_traits; typedef detail::group_functions group_functions_t; typedef detail::node_functions node_functions_t; - static const std::size_t hashtable_data_bool_flags_mask = - ( detail::hash_bool_flags::cache_begin_pos - | detail::hash_bool_flags::constant_time_size_pos - | detail::hash_bool_flags::incremental_pos - ); - typedef typename detail::usetopt_mask - ::type masked_config_t; - detail::hashtable_data_t data_; - - template - struct downcast_node_to_value - : public detail::node_to_value - { - typedef detail::node_to_value base_t; - typedef typename base_t::result_type result_type; - typedef typename detail::add_const_if_c - ::type &first_argument_type; - typedef typename detail::add_const_if_c - ::type &intermediate_argument_type; - - downcast_node_to_value(const hashtable_impl *cont) - : base_t(cont) - {} - - result_type operator()(first_argument_type arg) const - { return this->base_t::operator()(static_cast(arg)); } - }; - - template - struct node_cast_adaptor - : private detail::ebo_functor_holder - { - typedef detail::ebo_functor_holder base_t; - - template - node_cast_adaptor(const ConvertibleToF &c2f, const hashtable_impl *cont) - : base_t(base_t(c2f, cont)) - {} - - typename base_t::node_ptr operator()(const typename slist_impl::node &to_clone) - { return base_t::operator()(static_cast(to_clone)); } - - void operator()(typename slist_impl::node_ptr to_clone) - { - base_t::operator()(pointer_traits::pointer_to(static_cast(*to_clone))); - } - }; - private: //noncopyable, movable BOOST_MOVABLE_BUT_NOT_COPYABLE(hashtable_impl) - enum { safemode_or_autounlink = - (int)real_value_traits::link_mode == (int)auto_unlink || - (int)real_value_traits::link_mode == (int)safe_link }; + 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))); @@ -834,9 +1199,15 @@ class hashtable_impl BOOST_STATIC_ASSERT(!(cache_begin && ((int)real_value_traits::link_mode == (int)auto_unlink))); template - node_cast_adaptor > + node_cast_adaptor< detail::node_disposer + , slist_node_ptr, node_ptr > make_node_disposer(const Disposer &disposer) const - { return node_cast_adaptor >(disposer, this); } + { + return node_cast_adaptor + < detail::node_disposer + , slist_node_ptr, node_ptr > + (disposer, &this->priv_real_value_traits()); + } /// @endcond @@ -845,36 +1216,18 @@ class hashtable_impl typedef detail::transform_iterator < typename slist_impl::iterator - , downcast_node_to_value > local_iterator; + , downcast_node_to_value_t + < real_value_traits + , false> > local_iterator; typedef detail::transform_iterator < typename slist_impl::iterator - , downcast_node_to_value > const_local_iterator; - - /// @cond - - const real_value_traits &get_real_value_traits(detail::false_) const - { return this->data_; } - - const real_value_traits &get_real_value_traits(detail::true_) const - { return data_.get_value_traits(*this); } - - real_value_traits &get_real_value_traits(detail::false_) - { return this->data_; } - - real_value_traits &get_real_value_traits(detail::true_) - { return data_.get_value_traits(*this); } - - /// @endcond + , downcast_node_to_value_t + < real_value_traits + , true> > const_local_iterator; public: - const real_value_traits &get_real_value_traits() const - { return this->get_real_value_traits(detail::bool_()); } - - real_value_traits &get_real_value_traits() - { return this->get_real_value_traits(detail::bool_()); } - //! Requires: buckets must not be being used by any other resource. //! //! Effects: Constructs an empty unordered_set, storing a reference @@ -892,7 +1245,7 @@ class hashtable_impl , const hasher & hash_func = hasher() , const key_equal &equal_func = key_equal() , const value_traits &v_traits = value_traits()) - : data_(b_traits, hash_func, equal_func, v_traits) + : data_type(b_traits, hash_func, equal_func, v_traits) { this->priv_initialize_buckets(); this->priv_size_traits().set_size(size_type(0)); @@ -907,13 +1260,13 @@ class hashtable_impl //! Effects: to-do //! hashtable_impl(BOOST_RV_REF(hashtable_impl) x) - : data_( ::boost::move(x.priv_bucket_traits()) + : data_type( ::boost::move(x.priv_bucket_traits()) , ::boost::move(x.priv_hasher()) , ::boost::move(x.priv_equal()) , ::boost::move(x.priv_value_traits()) ) { - this->priv_swap_cache(cache_begin_t(), x); + this->priv_swap_cache(x); x.priv_initialize_cache(); if(constant_time_size){ this->priv_size_traits().set_size(size_type(0)); @@ -948,7 +1301,7 @@ class hashtable_impl //! //! Throws: Nothing. iterator begin() - { return iterator(this->priv_begin(), this); } + { return iterator(this->priv_begin(), &this->get_bucket_value_traits()); } //! Effects: Returns a const_iterator pointing to the beginning //! of the unordered_set. @@ -968,7 +1321,7 @@ class hashtable_impl //! //! Throws: Nothing. const_iterator cbegin() const - { return const_iterator(this->priv_begin(), this); } + { return const_iterator(this->priv_begin(), &this->get_bucket_value_traits()); } //! Effects: Returns an iterator pointing to the end of the unordered_set. //! @@ -1077,7 +1430,7 @@ class hashtable_impl //These can't throw swap(this->priv_bucket_traits(), other.priv_bucket_traits()); swap(this->priv_value_traits(), other.priv_value_traits()); - this->priv_swap_cache(cache_begin_t(), other); + this->priv_swap_cache(other); if(constant_time_size){ size_type backup = this->priv_size_traits().get_size(); this->priv_size_traits().set_size(other.priv_size_traits().get_size()); @@ -1128,9 +1481,12 @@ class hashtable_impl const bucket_ptr src_buckets = src.priv_bucket_pointer(); const bucket_ptr dst_buckets = this->priv_bucket_pointer(); size_type constructed; - typedef node_cast_adaptor > NodeDisposer; - typedef node_cast_adaptor > NodeCloner; - NodeDisposer node_disp(disposer, this); + + typedef node_cast_adaptor< detail::node_disposer + , slist_node_ptr, node_ptr > NodeDisposer; + typedef node_cast_adaptor< detail::node_cloner + , slist_node_ptr, node_ptr > NodeCloner; + NodeDisposer node_disp(disposer, &this->priv_real_value_traits()); detail::exception_array_disposer rollback(dst_buckets[0], node_disp, constructed); @@ -1139,7 +1495,7 @@ class hashtable_impl ; ++constructed){ dst_buckets[constructed].clone_from ( src_buckets[constructed] - , NodeCloner(cloner, this), node_disp); + , NodeCloner(cloner, &this->priv_real_value_traits()), node_disp); } if(src_bucket_count != dst_bucket_count){ //Now insert the remaining ones using the modulo trick @@ -1147,12 +1503,12 @@ class hashtable_impl ; constructed < src_bucket_count ; ++constructed){ bucket_type &dst_b = - dst_buckets[this->priv_hash_to_bucket(constructed, dst_bucket_count, dst_bucket_count)]; + dst_buckets[detail::hash_to_bucket_split(constructed, dst_bucket_count, dst_bucket_count)]; bucket_type &src_b = src_buckets[constructed]; for( siterator b(src_b.begin()), e(src_b.end()) ; b != e ; ++b){ - dst_b.push_front(*(NodeCloner(cloner, this)(*b.pointed_node()))); + dst_b.push_front(*(NodeCloner(cloner, &this->priv_real_value_traits())(*b.pointed_node()))); } } } @@ -1327,7 +1683,7 @@ class hashtable_impl if(success){ prev_pos = prev; } - return std::pair(iterator(prev_pos, this),success); + return std::pair(iterator(prev_pos, &this->get_bucket_value_traits()),success); } //! Requires: value must be an lvalue of type value_type. commit_data @@ -1360,7 +1716,7 @@ class hashtable_impl BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(n)); this->priv_insertion_update_cache(bucket_num); group_functions_t::insert_in_group(node_ptr(), n, optimize_multikey_t()); - return iterator(b.insert_after(b.before_begin(), *n), this); + return iterator(b.insert_after(b.before_begin(), *n), &this->get_bucket_value_traits()); } //! Effects: Erases the element pointed to by i. @@ -1485,7 +1841,7 @@ class hashtable_impl last_bucket_num = this->priv_get_bucket_num(last_local_it); } this->priv_erase_range(before_first_local_it, first_bucket_num, last_local_it, last_bucket_num, disposer); - this->priv_erasure_update_cache(first_bucket_num, last_bucket_num); + this->priv_erasure_update_cache_range(first_bucket_num, last_bucket_num); } } @@ -1530,8 +1886,7 @@ class hashtable_impl size_type bucket_num; std::size_t h; siterator prev; - siterator it = - this->priv_find(key, hash_func, equal_func, bucket_num, h, prev); + siterator it = this->priv_find(key, hash_func, equal_func, bucket_num, h, prev); bool success = it != this->priv_invalid_local_it(); size_type cnt(0); if(!success){ @@ -1540,7 +1895,7 @@ class hashtable_impl else if(optimize_multikey){ siterator last = bucket_type::s_iterator_to (*node_traits::get_next(group_functions_t::get_last_in_group - (hashtable_impl::dcast_bucket_ptr(it.pointed_node()), optimize_multikey_t()))); + (detail::dcast_bucket_ptr(it.pointed_node()), optimize_multikey_t()))); this->priv_erase_range_impl(bucket_num, prev, last, disposer, cnt); } else{ @@ -1670,7 +2025,7 @@ class hashtable_impl std::size_t hash; siterator prev; siterator local_it = this->priv_find(key, hash_func, equal_func, bucket_n, hash, prev); - return iterator(local_it, this); + return iterator(local_it, &this->get_bucket_value_traits()); } //! Effects: Finds a const_iterator to the first element whose key is @@ -1709,7 +2064,7 @@ class hashtable_impl std::size_t hash_value; siterator prev; siterator sit = this->priv_find(key, hash_func, equal_func, bucket_n, hash_value, prev); - return const_iterator(sit, this); + return const_iterator(sit, &this->get_bucket_value_traits()); } //! Effects: Returns a range containing all elements with values equivalent @@ -1750,7 +2105,7 @@ class hashtable_impl std::pair ret = this->priv_equal_range (key, hash_func, equal_func, bucket_n1, bucket_n2, cnt); return std::pair - (iterator(ret.first, this), iterator(ret.second, this)); + (iterator(ret.first, &this->get_bucket_value_traits()), iterator(ret.second, &this->get_bucket_value_traits())); } //! Effects: Returns a range containing all elements with values equivalent @@ -1792,7 +2147,7 @@ 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), const_iterator(ret.second, this)); + (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 @@ -1806,7 +2161,7 @@ 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); + 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 @@ -1821,7 +2176,7 @@ class hashtable_impl const_iterator iterator_to(const_reference value) const { siterator sit = bucket_type::s_iterator_to(const_cast(this->priv_value_to_node(value))); - return const_iterator(sit, this); + return const_iterator(sit, &this->get_bucket_value_traits()); } //! Requires: value must be an lvalue and shall be in a unordered_set of @@ -1840,7 +2195,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, (hashtable_impl*)0); + return local_iterator(sit, const_real_value_traits_ptr()); } //! Requires: value must be an lvalue and shall be in a unordered_set of @@ -1859,7 +2214,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, (hashtable_impl*)0); + return const_local_iterator(sit, const_real_value_traits_ptr()); } //! Requires: value must be an lvalue and shall be in a unordered_set of @@ -1874,7 +2229,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); + return local_iterator(sit, this->real_value_traits_ptr()); } //! Requires: value must be an lvalue and shall be in a unordered_set of @@ -1890,7 +2245,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); + return const_local_iterator(sit, this->real_value_traits_ptr()); } //! Effects: Returns the number of buckets passed in the constructor @@ -1960,7 +2315,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); } + { return local_iterator(this->priv_bucket_pointer()[n].begin(), this->real_value_traits_ptr()); } //! Requires: n is in the range [0, this->bucket_count()). //! @@ -1990,7 +2345,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); + return const_local_iterator(sit, this->real_value_traits_ptr()); } //! Requires: n is in the range [0, this->bucket_count()). @@ -2005,7 +2360,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); } + { return local_iterator(this->priv_bucket_pointer()[n].end(), this->real_value_traits_ptr()); } //! Requires: n is in the range [0, this->bucket_count()). //! @@ -2033,7 +2388,10 @@ class hashtable_impl //! Note: [this->begin(n), this->end(n)) is a valid range //! containing all of the elements in the nth bucket. const_local_iterator cend(size_type n) const - { return const_local_iterator(const_cast(this->priv_bucket_pointer()[n]).end(), this); } + { + return const_local_iterator ( const_cast(this->priv_bucket_pointer()[n]).end() + , this->real_value_traits_ptr()); + } //! Requires: new_bucket_traits can hold a pointer to a new bucket array //! or the same as the old bucket array with a different length. new_size is the length of the @@ -2107,12 +2465,12 @@ class hashtable_impl for(;i != end_sit; ++i){ const value_type &v = this->priv_value_from_slist_node(i.pointed_node()); const std::size_t hash_value = this->priv_stored_or_compute_hash(v, store_hash_t()); - const size_type new_n = this->priv_hash_to_bucket(hash_value, new_bucket_count, new_bucket_count); + const size_type new_n = detail::hash_to_bucket_split(hash_value, new_bucket_count, new_bucket_count); if(cache_begin && new_n < new_first_bucket_num) new_first_bucket_num = new_n; siterator last = bucket_type::s_iterator_to (*group_functions_t::get_last_in_group - (hashtable_impl::dcast_bucket_ptr(i.pointed_node()), optimize_multikey_t())); + (detail::dcast_bucket_ptr(i.pointed_node()), optimize_multikey_t())); if(same_buffer && new_n == n){ before_i = last; } @@ -2124,7 +2482,7 @@ class hashtable_impl } } else{ - const size_type new_n = this->priv_hash_to_bucket(n, new_bucket_count, new_bucket_count); + const size_type new_n = detail::hash_to_bucket_split(n, new_bucket_count, new_bucket_count); if(cache_begin && new_n < new_first_bucket_num) new_first_bucket_num = new_n; bucket_type &new_b = new_buckets[new_n]; @@ -2186,7 +2544,7 @@ class hashtable_impl const size_type new_n = this->priv_hash_to_bucket(hash_value); siterator last = bucket_type::s_iterator_to (*group_functions_t::get_last_in_group - (hashtable_impl::dcast_bucket_ptr(i.pointed_node()), optimize_multikey_t())); + (detail::dcast_bucket_ptr(i.pointed_node()), optimize_multikey_t())); if(new_n == bucket_to_rehash){ before_i = last; } @@ -2321,95 +2679,35 @@ class hashtable_impl /// @cond private: - std::size_t priv_hash_to_bucket(std::size_t hash_value) const - { return this->priv_hash_to_bucket(hash_value, this->priv_real_bucket_traits().bucket_count(), this->priv_split_traits().get_size()); } - - std::size_t priv_hash_to_bucket(std::size_t hash_value, std::size_t bucket_cnt, std::size_t split) const + void priv_clear_buckets(bucket_ptr buckets_ptr, size_type bucket_cnt) { - std::size_t bucket_number = hashtable_impl::priv_hash_to_bucket_impl(hash_value, bucket_cnt, power_2_buckets_t()); - if(incremental) - if(bucket_number >= split) - bucket_number -= bucket_cnt/2; - return bucket_number; + for(; bucket_cnt--; ++buckets_ptr){ + if(safemode_or_autounlink){ + bucket_plus_vtraits_t::priv_clear_group_nodes(*buckets_ptr, optimize_multikey_t()); + buckets_ptr->clear_and_dispose(detail::init_disposer()); + } + else{ + buckets_ptr->clear(); + } + } + this->priv_initialize_cache(); } - static std::size_t priv_hash_to_bucket_impl(std::size_t hash_value, std::size_t bucket_cnt, detail::false_) - { return hash_value % bucket_cnt; } + void priv_initialize_buckets() + { this->priv_clear_buckets(this->priv_bucket_pointer(), this->priv_bucket_count()); } - static std::size_t priv_hash_to_bucket_impl(std::size_t hash_value, std::size_t bucket_cnt, detail::true_) - { return hash_value & (bucket_cnt - 1); } + void priv_clear_buckets() + { + this->priv_clear_buckets + ( this->priv_get_cache() + , this->priv_bucket_count() - (this->priv_get_cache() - this->priv_bucket_pointer())); + } - const key_equal &priv_equal() const - { return static_cast(this->data_.internal_.bucket_hash_equal_.get()); } - - key_equal &priv_equal() - { return static_cast(this->data_.internal_.bucket_hash_equal_.get()); } - - const value_traits &priv_value_traits() const - { return data_; } - - value_traits &priv_value_traits() - { return data_; } - - value_type &priv_value_from_slist_node(slist_node_ptr n) - { return *this->get_real_value_traits().to_value_ptr(hashtable_impl::dcast_bucket_ptr(n)); } - - const value_type &priv_value_from_slist_node(slist_node_ptr n) const - { return *this->get_real_value_traits().to_value_ptr(hashtable_impl::dcast_bucket_ptr(n)); } - - const real_bucket_traits &priv_real_bucket_traits(detail::false_) const - { return this->data_.internal_.bucket_hash_equal_.bucket_hash.bucket_plus_size_.bucket_traits_; } - - const real_bucket_traits &priv_real_bucket_traits(detail::true_) const - { return this->data_.internal_.bucket_hash_equal_.bucket_hash.bucket_plus_size_.bucket_traits_.get_bucket_traits(*this); } - - real_bucket_traits &priv_real_bucket_traits(detail::false_) - { return this->data_.internal_.bucket_hash_equal_.bucket_hash.bucket_plus_size_.bucket_traits_; } - - real_bucket_traits &priv_real_bucket_traits(detail::true_) - { return this->data_.internal_.bucket_hash_equal_.bucket_hash.bucket_plus_size_.bucket_traits_.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 bucket_traits &priv_bucket_traits() const - { return this->data_.internal_.bucket_hash_equal_.bucket_hash.bucket_plus_size_.bucket_traits_; } - - bucket_traits &priv_bucket_traits() - { return this->data_.internal_.bucket_hash_equal_.bucket_hash.bucket_plus_size_.bucket_traits_; } - - const hasher &priv_hasher() const - { return static_cast(this->data_.internal_.bucket_hash_equal_.bucket_hash.get()); } - - hasher &priv_hasher() - { return static_cast(this->data_.internal_.bucket_hash_equal_.bucket_hash.get()); } - - bucket_ptr priv_bucket_pointer() const - { return this->priv_real_bucket_traits().bucket_begin(); } - - size_type priv_bucket_count() const - { return this->priv_real_bucket_traits().bucket_count(); } - - node &priv_value_to_node(value_type &v) - { return *this->get_real_value_traits().to_node_ptr(v); } - - const node &priv_value_to_node(const value_type &v) const - { return *this->get_real_value_traits().to_node_ptr(v); } - - size_traits &priv_size_traits() - { return this->data_.internal_.bucket_hash_equal_.bucket_hash.bucket_plus_size_; } - - const size_traits &priv_size_traits() const - { return this->data_.internal_.bucket_hash_equal_.bucket_hash.bucket_plus_size_; } - - split_traits &priv_split_traits() - { return this->data_.internal_; } - - const split_traits &priv_split_traits() const - { return this->data_.internal_; } + 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()); + } template void priv_erase_range_impl @@ -2427,7 +2725,7 @@ class hashtable_impl ++to_erase; slist_node_ptr end_ptr = end_sit.pointed_node(); while(to_erase != end_sit){ - group_functions_t::erase_from_group(end_ptr, hashtable_impl::dcast_bucket_ptr(to_erase.pointed_node()), optimize_multikey_t()); + group_functions_t::erase_from_group(end_ptr, detail::dcast_bucket_ptr(to_erase.pointed_node()), optimize_multikey_t()); to_erase = b.erase_after_and_dispose(before_first_it, make_node_disposer(disposer)); ++num_erased; } @@ -2449,7 +2747,7 @@ class hashtable_impl ++nxt; siterator end_sit(b.end()); while(nxt != end_sit){ - group_functions_t::init_group(hashtable_impl::dcast_bucket_ptr(nxt.pointed_node()), optimize_multikey_t()); + group_functions_t::init_group(detail::dcast_bucket_ptr(nxt.pointed_node()), optimize_multikey_t()); nxt = b.erase_after_and_dispose (b_begin, make_node_disposer(disposer)); this->priv_size_traits().decrement(); @@ -2476,125 +2774,23 @@ class hashtable_impl } } - static node_ptr dcast_bucket_ptr(typename slist_impl::node_ptr p) - { return pointer_traits::pointer_to(static_cast(*p)); } - - std::size_t priv_stored_or_compute_hash(const value_type &v, detail::true_) const - { return node_traits::get_hash(this->get_real_value_traits().to_node_ptr(v)); } - - std::size_t priv_stored_or_compute_hash(const value_type &v, detail::false_) const - { return this->priv_hasher()(v); } - - std::size_t priv_stored_hash(slist_node_ptr n, detail::true_) const - { return node_traits::get_hash(hashtable_impl::dcast_bucket_ptr(n)); } - - std::size_t priv_stored_hash(slist_node_ptr, detail::false_) const - { - //This code should never be reached! - BOOST_INTRUSIVE_INVARIANT_ASSERT(0); - return 0; - } - - static void priv_clear_group_nodes(bucket_type &b, detail::true_) - { - siterator it(b.begin()), itend(b.end()); - while(it != itend){ - node_ptr to_erase(hashtable_impl::dcast_bucket_ptr(it.pointed_node())); - ++it; - group_algorithms::init(to_erase); - } - } - - static void priv_clear_group_nodes(bucket_type &, detail::false_) - {} - std::size_t priv_get_bucket_num(siterator it) { return this->priv_get_bucket_num_hash_dispatch(it, store_hash_t()); } - std::size_t priv_get_bucket_num_hash_dispatch(siterator it, detail::true_) + std::size_t priv_get_bucket_num_hash_dispatch(siterator it, detail::true_) //store_hash { return this->priv_hash_to_bucket (this->priv_stored_hash(it.pointed_node(), store_hash_t())); } - std::size_t priv_get_bucket_num_hash_dispatch(siterator it, detail::false_) + 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()); } - std::size_t priv_get_bucket_num_no_hash_store(siterator it, detail::true_) - { - const bucket_ptr f(this->priv_bucket_pointer()), l(f + this->priv_bucket_count() - 1); - slist_node_ptr bb = group_functions_t::get_bucket_before_begin - ( f->end().pointed_node() - , l->end().pointed_node() - , hashtable_impl::dcast_bucket_ptr(it.pointed_node())); - //Now get the bucket_impl from the iterator - const bucket_type &b = static_cast - (bucket_type::slist_type::container_from_end_iterator(bucket_type::s_iterator_to(*bb))); - //Now just calculate the index b has in the bucket array - return static_cast(&b - &*f); - } - - std::size_t priv_get_bucket_num_no_hash_store(siterator it, detail::false_) - { - bucket_ptr f(this->priv_bucket_pointer()), l(f + this->priv_bucket_count() - 1); - slist_node_ptr first_ptr(f->cend().pointed_node()) - , last_ptr(l->cend().pointed_node()); - - //The end node is embedded in the singly linked list: - //iterate until we reach it. - while(!(first_ptr <= it.pointed_node() && it.pointed_node() <= last_ptr)){ - ++it; - } - //Now get the bucket_impl from the iterator - const bucket_type &b = static_cast - (bucket_type::container_from_end_iterator(it)); - - //Now just calculate the index b has in the bucket array - return static_cast(&b - &*f); - } - - siterator priv_get_previous - (bucket_type &b, siterator i) - { return this->priv_get_previous(b, i, optimize_multikey_t()); } - - siterator priv_get_previous - (bucket_type &b, siterator i, detail::true_) - { - node_ptr elem(hashtable_impl::dcast_bucket_ptr(i.pointed_node())); - node_ptr prev_in_group(group_traits::get_next(elem)); - bool first_in_group = node_traits::get_next(prev_in_group) != elem; - typename bucket_type::node &n = first_in_group - ? *group_functions_t::get_prev_to_first_in_group(b.end().pointed_node(), elem) - : *group_traits::get_next(elem) - ; - return bucket_type::s_iterator_to(n); - } - - siterator priv_get_previous - (bucket_type &b, siterator i, detail::false_) - { return b.previous(i); } + static siterator priv_get_previous(bucket_type &b, siterator i) + { return bucket_plus_vtraits_t::priv_get_previous(b, i, optimize_multikey_t()); } static siterator priv_get_last(bucket_type &b) - { return hashtable_impl::priv_get_last(b, optimize_multikey_t()); } - - static siterator priv_get_last(bucket_type &b, detail::true_) - { - //First find the last node of p's group. - //This requires checking the first node of the next group or - //the bucket node. - slist_node_ptr end_ptr(b.end().pointed_node()); - node_ptr possible_end(node_traits::get_next( hashtable_impl::dcast_bucket_ptr(end_ptr))); - node_ptr last_node_group(possible_end); - - while(end_ptr != possible_end){ - last_node_group = group_traits::get_next(hashtable_impl::dcast_bucket_ptr(possible_end)); - possible_end = node_traits::get_next(last_node_group); - } - return bucket_type::s_iterator_to(*last_node_group); - } - - static siterator priv_get_last(bucket_type &b, detail::false_) - { return b.previous(b.end()); } + { return bucket_plus_vtraits_t::priv_get_last(b, optimize_multikey_t()); } template void priv_erase(const_iterator i, Disposer disposer, detail::true_) @@ -2621,7 +2817,7 @@ class hashtable_impl if(nxt_in_group) group_algorithms::unlink_after(nxt_in_group); if(safemode_or_autounlink) - group_algorithms::init(hashtable_impl::dcast_bucket_ptr(elem)); + group_algorithms::init(detail::dcast_bucket_ptr(elem)); } template @@ -2633,159 +2829,6 @@ class hashtable_impl b.erase_after_and_dispose(prev, make_node_disposer(disposer)); } - bucket_ptr priv_invalid_bucket() const - { - const real_bucket_traits &rbt = this->priv_real_bucket_traits(); - return rbt.bucket_begin() + rbt.bucket_count(); - } - - siterator priv_invalid_local_it() const - { return this->priv_invalid_bucket()->end(); } - - siterator priv_begin() const - { return this->priv_begin(cache_begin_t()); } - - siterator priv_begin(detail::false_) const - { - size_type n = 0; - size_type bucket_cnt = this->priv_bucket_count(); - for (n = 0; n < bucket_cnt; ++n){ - bucket_type &b = this->priv_bucket_pointer()[n]; - if(!b.empty()){ - return b.begin(); - } - } - return this->priv_invalid_local_it(); - } - - siterator priv_begin(detail::true_) const - { - if(this->data_.internal_.bucket_hash_equal_.cached_begin_ == this->priv_invalid_bucket()){ - return this->priv_invalid_local_it(); - } - else{ - return this->data_.internal_.bucket_hash_equal_.cached_begin_->begin(); - } - } - - void priv_initialize_cache() - { this->priv_initialize_cache(cache_begin_t()); } - - void priv_initialize_cache(detail::true_) - { this->data_.internal_.bucket_hash_equal_.cached_begin_ = this->priv_invalid_bucket(); } - - void priv_initialize_cache(detail::false_) - {} - - void priv_insertion_update_cache(size_type insertion_bucket) - { this->priv_insertion_update_cache(insertion_bucket, cache_begin_t()); } - - void priv_insertion_update_cache(size_type insertion_bucket, detail::true_) - { - bucket_ptr p = this->priv_bucket_pointer() + insertion_bucket; - if(p < this->data_.internal_.bucket_hash_equal_.cached_begin_){ - this->data_.internal_.bucket_hash_equal_.cached_begin_ = p; - } - } - - void priv_insertion_update_cache(size_type, detail::false_) - {} - - void priv_erasure_update_cache(size_type first_bucket, size_type last_bucket) - { this->priv_erasure_update_cache(first_bucket, last_bucket, cache_begin_t()); } - - void priv_erasure_update_cache(size_type first_bucket_num, size_type last_bucket_num, detail::true_) - { - //If the last bucket is the end, the cache must be updated - //to the last position if all - if(this->priv_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->priv_erasure_update_cache(); - } - } - - void priv_erasure_update_cache(size_type, size_type, detail::false_) - {} - - void priv_erasure_update_cache() - { this->priv_erasure_update_cache(cache_begin_t()); } - - void priv_erasure_update_cache(detail::true_) - { - if(constant_time_size && !size()){ - this->priv_initialize_cache(); - } - else{ - size_type current_n = this->data_.internal_.bucket_hash_equal_.cached_begin_ - this->priv_bucket_pointer(); - for( const size_type num_buckets = this->priv_bucket_count() - ; current_n < num_buckets - ; ++current_n, ++this->data_.internal_.bucket_hash_equal_.cached_begin_){ - if(!this->data_.internal_.bucket_hash_equal_.cached_begin_->empty()){ - return; - } - } - this->priv_initialize_cache(); - } - } - - void priv_erasure_update_cache(detail::false_) - {} - - void priv_swap_cache(detail::true_, hashtable_impl &other) - { - std::swap( this->data_.internal_.bucket_hash_equal_.cached_begin_ - , other.data_.internal_.bucket_hash_equal_.cached_begin_); - } - - void priv_swap_cache(detail::false_, hashtable_impl &) - {} - - bucket_ptr priv_get_cache() - { return this->priv_get_cache(cache_begin_t()); } - - bucket_ptr priv_get_cache(detail::true_) - { return this->data_.internal_.bucket_hash_equal_.cached_begin_; } - - bucket_ptr priv_get_cache(detail::false_) - { return this->priv_bucket_pointer(); } - - void priv_set_cache(const bucket_ptr &p) - { this->data_.internal_.bucket_hash_equal_.set_cache(p); } - - size_type priv_get_cache_bucket_num() - { return this->priv_get_cache_bucket_num(cache_begin_t()); } - - size_type priv_get_cache_bucket_num(detail::true_) - { return this->data_.internal_.bucket_hash_equal_.cached_begin_ - this->priv_bucket_pointer(); } - - size_type priv_get_cache_bucket_num(detail::false_) - { return 0u; } - - void priv_clear_buckets() - { - this->priv_clear_buckets - ( this->priv_get_cache() - , this->priv_bucket_count() - (this->priv_get_cache() - this->priv_bucket_pointer())); - } - - void priv_initialize_buckets() - { this->priv_clear_buckets(this->priv_bucket_pointer(), this->priv_bucket_count()); } - - void priv_clear_buckets(bucket_ptr buckets_ptr, size_type bucket_cnt) - { - for(; bucket_cnt--; ++buckets_ptr){ - if(safemode_or_autounlink){ - hashtable_impl::priv_clear_group_nodes(*buckets_ptr, optimize_multikey_t()); - buckets_ptr->clear_and_dispose(detail::init_disposer()); - } - else{ - buckets_ptr->clear(); - } - } - this->priv_initialize_cache(); - } - template siterator priv_find ( const KeyType &key, KeyHasher hash_func @@ -2823,7 +2866,7 @@ class hashtable_impl if(optimize_multikey){ previt = bucket_type::s_iterator_to (*group_functions_t::get_last_in_group - (hashtable_impl::dcast_bucket_ptr(it.pointed_node()), optimize_multikey_t())); + (detail::dcast_bucket_ptr(it.pointed_node()), optimize_multikey_t())); it = previt; } else{ @@ -2857,17 +2900,17 @@ class hashtable_impl //Checks for some modes if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(n)); - //Shorcut for optimize_multikey cases + //Shortcut for optimize_multikey cases if(optimize_multikey){ node_ptr first_in_group = found_equal ? - hashtable_impl::dcast_bucket_ptr(it.pointed_node()) : node_ptr(); + detail::dcast_bucket_ptr(it.pointed_node()) : node_ptr(); group_functions_t::insert_in_group(first_in_group, n, optimize_multikey_t()); } //Update cache and increment size if needed this->priv_insertion_update_cache(bucket_num); this->priv_size_traits().increment(); //Insert the element in the bucket after it - return iterator(b.insert_after(it, *n), this); + return iterator(b.insert_after(it, *n), &this->get_bucket_value_traits()); } template @@ -2898,7 +2941,7 @@ class hashtable_impl if(optimize_multikey){ to_return.second = bucket_type::s_iterator_to (*node_traits::get_next(group_functions_t::get_last_in_group - (hashtable_impl::dcast_bucket_ptr(it.pointed_node()), optimize_multikey_t()))); + (detail::dcast_bucket_ptr(it.pointed_node()), optimize_multikey_t()))); cnt = std::distance(it, to_return.second); if(to_return.second != b.end()){ bucket_number_second = bucket_number_first; @@ -2951,39 +2994,21 @@ class hashtable_impl #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , bool UniqueKeys - , class O1 = none, class O2 = none - , class O3 = none, class O4 = none - , class O5 = none, class O6 = none - , class O7 = none, class O8 = none - , class O9 = none, class O10= none + , class PackedOptions > #else template #endif -struct make_hashtable_opt +struct make_real_bucket_traits { - typedef typename pack_options - < uset_defaults, - #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - O1, O2, O3, O4, O5, O6, O7, O8, O9, O10 - #else - Options... - #endif - >::type packed_options; - //Real value traits must be calculated from options typedef typename detail::get_value_traits - ::type value_traits; - static const bool external_value_traits = - detail::external_value_traits_bool_is_true::value;/* + ::type value_traits; +/* static const bool resizable_bucket_traits = detail::resizable_bool_is_true::value;*/ - typedef typename detail::eval_if_c - < external_value_traits - , detail::eval_value_traits - , detail::identity - >::type real_value_traits; - typedef typename packed_options::bucket_traits specified_bucket_traits; + 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 @@ -2998,21 +3023,7 @@ struct make_hashtable_opt >::value , detail::bucket_traits_impl , specified_bucket_traits - >::type real_bucket_traits; - - typedef detail::usetopt - < value_traits - , typename packed_options::hash - , typename packed_options::equal - , typename packed_options::size_type - , real_bucket_traits - , (std::size_t(UniqueKeys)*detail::hash_bool_flags::unique_keys_pos) - | (std::size_t(packed_options::constant_time_size)*detail::hash_bool_flags::constant_time_size_pos) - | (std::size_t(packed_options::power_2_buckets)*detail::hash_bool_flags::power_2_buckets_pos) - | (std::size_t(packed_options::cache_begin)*detail::hash_bool_flags::cache_begin_pos) - | (std::size_t(packed_options::compare_hash)*detail::hash_bool_flags::compare_hash_pos) - | (std::size_t(packed_options::incremental)*detail::hash_bool_flags::incremental_pos) - > type; + >::type type; }; /// @endcond @@ -3021,25 +3032,43 @@ struct make_hashtable_opt #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else -template #endif struct make_hashtable { /// @cond + typedef typename pack_options + < hashtable_defaults, + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3, O4, O5, O6, O7, O8, O9, O10 + #else + Options... + #endif + >::type packed_options; + + typedef typename detail::get_value_traits + ::type value_traits; + + typedef typename make_real_bucket_traits + ::type real_bucket_traits; + typedef hashtable_impl - < typename make_hashtable_opt - ::type + < value_traits + , typename packed_options::hash + , typename packed_options::equal + , typename packed_options::size_type + , real_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) + | (std::size_t(packed_options::cache_begin)*hash_bool_flags::cache_begin_pos) + | (std::size_t(packed_options::compare_hash)*hash_bool_flags::compare_hash_pos) + | (std::size_t(packed_options::incremental)*hash_bool_flags::incremental_pos) > implementation_defined; /// @endcond @@ -3097,7 +3126,7 @@ class hashtable {} hashtable& operator=(BOOST_RV_REF(hashtable) x) - { this->Base::operator=(::boost::move(static_cast(x))); return *this; } + { return static_cast(this->Base::operator=(::boost::move(static_cast(x)))); } }; #endif diff --git a/include/boost/intrusive/intrusive_fwd.hpp b/include/boost/intrusive/intrusive_fwd.hpp index c95767e..0e5e21c 100644 --- a/include/boost/intrusive/intrusive_fwd.hpp +++ b/include/boost/intrusive/intrusive_fwd.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 @@ -19,15 +19,6 @@ /// @cond -namespace boost { - -namespace intrusive { - -struct none; - -} //namespace intrusive{ -} //namespace boost{ - namespace boost { namespace intrusive { @@ -53,11 +44,11 @@ class rbtree_algorithms; #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T - , class O1 = none - , class O2 = none - , class O3 = none - , class O4 = none - , class O5 = none + , class O1 = void + , class O2 = void + , class O3 = void + , class O4 = void + , class O5 = void > #else template @@ -66,9 +57,9 @@ class slist; #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template - < class O1 = none - , class O2 = none - , class O3 = none + < class O1 = void + , class O2 = void + , class O3 = void > #else template @@ -77,9 +68,9 @@ class slist_base_hook; #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template - < class O1 = none - , class O2 = none - , class O3 = none + < class O1 = void + , class O2 = void + , class O3 = void > #else template @@ -90,9 +81,9 @@ class slist_member_hook; #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T - , class O1 = none - , class O2 = none - , class O3 = none + , class O1 = void + , class O2 = void + , class O3 = void > #else template @@ -101,9 +92,9 @@ class list; #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template - < class O1 = none - , class O2 = none - , class O3 = none + < class O1 = void + , class O2 = void + , class O3 = void > #else template @@ -112,9 +103,9 @@ class list_base_hook; #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template - < class O1 = none - , class O2 = none - , class O3 = none + < class O1 = void + , class O2 = void + , class O3 = void > #else template @@ -123,9 +114,9 @@ class list_member_hook; #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template - < class O1 = none - , class O2 = none - , class O3 = none + < class O1 = void + , class O2 = void + , class O3 = void > #else template @@ -136,10 +127,10 @@ class list_hook; #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T - , class O1 = none - , class O2 = none - , class O3 = none - , class O4 = none + , class O1 = void + , class O2 = void + , class O3 = void + , class O4 = void > #else template @@ -149,10 +140,10 @@ class rbtree; #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T - , class O1 = none - , class O2 = none - , class O3 = none - , class O4 = none + , class O1 = void + , class O2 = void + , class O3 = void + , class O4 = void > #else template @@ -162,10 +153,10 @@ class set; #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T - , class O1 = none - , class O2 = none - , class O3 = none - , class O4 = none + , class O1 = void + , class O2 = void + , class O3 = void + , class O4 = void > #else template @@ -174,10 +165,10 @@ class multiset; #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template - < class O1 = none - , class O2 = none - , class O3 = none - , class O4 = none + < class O1 = void + , class O2 = void + , class O3 = void + , class O4 = void > #else template @@ -186,10 +177,10 @@ class set_base_hook; #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template - < class O1 = none - , class O2 = none - , class O3 = none - , class O4 = none + < class O1 = void + , class O2 = void + , class O3 = void + , class O4 = void > #else template @@ -200,10 +191,10 @@ class set_member_hook; #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T - , class O1 = none - , class O2 = none - , class O3 = none - , class O4 = none + , class O1 = void + , class O2 = void + , class O3 = void + , class O4 = void > #else template @@ -213,10 +204,10 @@ class splaytree; #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T - , class O1 = none - , class O2 = none - , class O3 = none - , class O4 = none + , class O1 = void + , class O2 = void + , class O3 = void + , class O4 = void > #else template @@ -226,10 +217,10 @@ class splay_set; #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T - , class O1 = none - , class O2 = none - , class O3 = none - , class O4 = none + , class O1 = void + , class O2 = void + , class O3 = void + , class O4 = void > #else template @@ -238,9 +229,9 @@ class splay_multiset; #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template - < class O1 = none - , class O2 = none - , class O3 = none + < class O1 = void + , class O2 = void + , class O3 = void > #else template @@ -249,9 +240,9 @@ class splay_set_base_hook; #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template - < class O1 = none - , class O2 = none - , class O3 = none + < class O1 = void + , class O2 = void + , class O3 = void > #else template @@ -262,10 +253,10 @@ class splay_set_member_hook; #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T - , class O1 = none - , class O2 = none - , class O3 = none - , class O4 = none + , class O1 = void + , class O2 = void + , class O3 = void + , class O4 = void > #else template @@ -275,10 +266,10 @@ class avltree; #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T - , class O1 = none - , class O2 = none - , class O3 = none - , class O4 = none + , class O1 = void + , class O2 = void + , class O3 = void + , class O4 = void > #else template @@ -288,10 +279,10 @@ class avl_set; #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T - , class O1 = none - , class O2 = none - , class O3 = none - , class O4 = none + , class O1 = void + , class O2 = void + , class O3 = void + , class O4 = void > #else template @@ -300,10 +291,10 @@ class avl_multiset; #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template - < class O1 = none - , class O2 = none - , class O3 = none - , class O4 = none + < class O1 = void + , class O2 = void + , class O3 = void + , class O4 = void > #else template @@ -312,10 +303,10 @@ class avl_set_base_hook; #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template - < class O1 = none - , class O2 = none - , class O3 = none - , class O4 = none + < class O1 = void + , class O2 = void + , class O3 = void + , class O4 = void > #else template @@ -327,10 +318,10 @@ class avl_set_member_hook; #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T - , class O1 = none - , class O2 = none - , class O3 = none - , class O4 = none + , class O1 = void + , class O2 = void + , class O3 = void + , class O4 = void > #else template @@ -340,10 +331,10 @@ class treap; #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T - , class O1 = none - , class O2 = none - , class O3 = none - , class O4 = none + , class O1 = void + , class O2 = void + , class O3 = void + , class O4 = void > #else template @@ -353,10 +344,10 @@ class treap_set; #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T - , class O1 = none - , class O2 = none - , class O3 = none - , class O4 = none + , class O1 = void + , class O2 = void + , class O3 = void + , class O4 = void > #else template @@ -371,10 +362,10 @@ struct priority_compare; #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T - , class O1 = none - , class O2 = none - , class O3 = none - , class O4 = none + , class O1 = void + , class O2 = void + , class O3 = void + , class O4 = void > #else template @@ -384,10 +375,10 @@ class sgtree; #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T - , class O1 = none - , class O2 = none - , class O3 = none - , class O4 = none + , class O1 = void + , class O2 = void + , class O3 = void + , class O4 = void > #else template @@ -397,10 +388,10 @@ class sg_set; #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T - , class O1 = none - , class O2 = none - , class O3 = none - , class O4 = none + , class O1 = void + , class O2 = void + , class O3 = void + , class O4 = void > #else template @@ -409,9 +400,48 @@ class sg_multiset; #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template - < class O1 = none - , class O2 = none - , class O3 = none + < class T + , class O1 = void + , class O2 = void + , class O3 = void + , class O4 = void + > +#else +template +#endif +class bstree; + +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +template + < class T + , class O1 = void + , class O2 = void + , class O3 = void + , class O4 = void + > +#else +template +#endif +class bs_set; + +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +template + < class T + , class O1 = void + , class O2 = void + , class O3 = void + , class O4 = void + > +#else +template +#endif +class bs_multiset; + +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +template + < class O1 = void + , class O2 = void + , class O3 = void > #else template @@ -420,9 +450,9 @@ class bs_set_base_hook; #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template - < class O1 = none - , class O2 = none - , class O3 = none + < class O1 = void + , class O2 = void + , class O3 = void > #else template @@ -434,16 +464,16 @@ class bs_set_member_hook; #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T - , class O1 = none - , class O2 = none - , class O3 = none - , class O4 = none - , class O5 = none - , class O6 = none - , class O7 = none - , class O8 = none - , class O9 = none - , class O10 = none + , 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 > #else template @@ -453,16 +483,16 @@ class hashtable; #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T - , class O1 = none - , class O2 = none - , class O3 = none - , class O4 = none - , class O5 = none - , class O6 = none - , class O7 = none - , class O8 = none - , class O9 = none - , class O10 = none + , 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 > #else template @@ -472,16 +502,16 @@ class unordered_set; #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T - , class O1 = none - , class O2 = none - , class O3 = none - , class O4 = none - , class O5 = none - , class O6 = none - , class O7 = none - , class O8 = none - , class O9 = none - , class O10 = none + , 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 > #else template @@ -490,10 +520,10 @@ class unordered_multiset; #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template - < class O1 = none - , class O2 = none - , class O3 = none - , class O4 = none + < class O1 = void + , class O2 = void + , class O3 = void + , class O4 = void > #else template @@ -502,10 +532,10 @@ class unordered_set_base_hook; #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template - < class O1 = none - , class O2 = none - , class O3 = none - , class O4 = none + < class O1 = void + , class O2 = void + , class O3 = void + , class O4 = void > #else template @@ -514,9 +544,9 @@ class unordered_set_member_hook; #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template - < class O1 = none - , class O2 = none - , class O3 = none + < class O1 = void + , class O2 = void + , class O3 = void > #else template @@ -525,9 +555,9 @@ class any_base_hook; #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template - < class O1 = none - , class O2 = none - , class O3 = none + < class O1 = void + , class O2 = void + , class O3 = void > #else template diff --git a/include/boost/intrusive/linear_slist_algorithms.hpp b/include/boost/intrusive/linear_slist_algorithms.hpp index db4092d..86f9bb3 100644 --- a/include/boost/intrusive/linear_slist_algorithms.hpp +++ b/include/boost/intrusive/linear_slist_algorithms.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -319,6 +320,16 @@ class linear_slist_algorithms } }; +/// @cond + +template +struct get_algo +{ + typedef linear_slist_algorithms type; +}; + +/// @endcond + } //namespace intrusive } //namespace boost diff --git a/include/boost/intrusive/link_mode.hpp b/include/boost/intrusive/link_mode.hpp index c04f775..73d3044 100644 --- a/include/boost/intrusive/link_mode.hpp +++ b/include/boost/intrusive/link_mode.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 diff --git a/include/boost/intrusive/list.hpp b/include/boost/intrusive/list.hpp index 5909152..1f101a1 100644 --- a/include/boost/intrusive/list.hpp +++ b/include/boost/intrusive/list.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 @@ -38,24 +38,12 @@ namespace intrusive { /// @cond -template -struct listopt -{ - typedef ValueTraits value_traits; - typedef SizeType size_type; - static const bool constant_time_size = ConstantTimeSize; -}; - - -template struct list_defaults - : pack_options - < none - , base_hook - , constant_time_size - , size_type - >::type -{}; +{ + typedef detail::default_list_hook proto_value_traits; + static const bool constant_time_size = true; + typedef std::size_t size_type; +}; /// @endcond @@ -72,23 +60,19 @@ struct list_defaults #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class list_impl - : private detail::clear_on_destructor_base< list_impl > + : private detail::clear_on_destructor_base< list_impl > { template friend class detail::clear_on_destructor_base; //Public typedefs public: - typedef typename Config::value_traits value_traits; + typedef ValueTraits value_traits; /// @cond static const bool external_value_traits = detail::external_value_traits_bool_is_true::value; - typedef typename detail::eval_if_c - < external_value_traits - , detail::eval_value_traits - , detail::identity - >::type real_value_traits; + typedef typename detail::get_real_value_traits::type real_value_traits; /// @endcond typedef typename real_value_traits::pointer pointer; typedef typename real_value_traits::const_pointer const_pointer; @@ -96,9 +80,9 @@ class list_impl typedef typename pointer_traits::reference reference; typedef typename pointer_traits::reference const_reference; typedef typename pointer_traits::difference_type difference_type; - typedef typename Config::size_type size_type; - typedef list_iterator iterator; - typedef list_iterator const_iterator; + typedef SizeType size_type; + typedef list_iterator iterator; + typedef list_iterator const_iterator; typedef boost::intrusive::detail::reverse_iterator reverse_iterator; typedef boost::intrusive::detail::reverse_iteratorconst_reverse_iterator; typedef typename real_value_traits::node_traits node_traits; @@ -107,7 +91,7 @@ class list_impl typedef typename node_traits::const_node_ptr const_node_ptr; typedef circular_list_algorithms node_algorithms; - static const bool constant_time_size = Config::constant_time_size; + static const bool constant_time_size = ConstantTimeSize; static const bool stateful_value_traits = detail::is_stateful_value_traits::value; /// @cond @@ -118,19 +102,13 @@ class list_impl //noncopyable BOOST_MOVABLE_BUT_NOT_COPYABLE(list_impl) - enum { safemode_or_autounlink = - (int)real_value_traits::link_mode == (int)auto_unlink || - (int)real_value_traits::link_mode == (int)safe_link }; + 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) )); - //Const cast emulation for smart pointers - static node_ptr uncast(const const_node_ptr & ptr) - { return pointer_traits::const_cast_from(ptr); } - node_ptr get_root_node() { return pointer_traits::pointer_to(data_.root_plus_size_.root_); } @@ -196,6 +174,11 @@ class list_impl real_value_traits &get_real_value_traits() { return this->get_real_value_traits(detail::bool_()); } + typedef typename pointer_traits::template rebind_pointer::type const_real_value_traits_ptr; + + const_real_value_traits_ptr real_value_traits_ptr() const + { return pointer_traits::pointer_to(this->get_real_value_traits()); } + //! Effects: constructs an empty list. //! //! Complexity: Constant @@ -371,7 +354,7 @@ class list_impl //! //! Complexity: Constant. const_reference front() const - { return *get_real_value_traits().to_value_ptr(uncast(node_traits::get_next(this->get_root_node()))); } + { return *get_real_value_traits().to_value_ptr(detail::uncast(node_traits::get_next(this->get_root_node()))); } //! Effects: Returns a reference to the last element of the list. //! @@ -387,7 +370,7 @@ class list_impl //! //! Complexity: Constant. const_reference back() const - { return *get_real_value_traits().to_value_ptr(uncast(node_traits::get_previous(this->get_root_node()))); } + { return *get_real_value_traits().to_value_ptr(detail::uncast(node_traits::get_previous(this->get_root_node()))); } //! Effects: Returns an iterator to the first element contained in the list. //! @@ -395,7 +378,7 @@ class list_impl //! //! Complexity: Constant. iterator begin() - { return iterator(node_traits::get_next(this->get_root_node()), this); } + { return iterator(node_traits::get_next(this->get_root_node()), real_value_traits_ptr()); } //! Effects: Returns a const_iterator to the first element contained in the list. //! @@ -411,7 +394,7 @@ class list_impl //! //! Complexity: Constant. const_iterator cbegin() const - { return const_iterator(node_traits::get_next(this->get_root_node()), this); } + { return const_iterator(node_traits::get_next(this->get_root_node()), real_value_traits_ptr()); } //! Effects: Returns an iterator to the end of the list. //! @@ -419,7 +402,7 @@ class list_impl //! //! Complexity: Constant. iterator end() - { return iterator(this->get_root_node(), this); } + { return iterator(this->get_root_node(), real_value_traits_ptr()); } //! Effects: Returns a const_iterator to the end of the list. //! @@ -435,7 +418,7 @@ class list_impl //! //! Complexity: Constant. const_iterator cend() const - { return const_iterator(uncast(this->get_root_node()), this); } + { return const_iterator(detail::uncast(this->get_root_node()), real_value_traits_ptr()); } //! Effects: Returns a reverse_iterator pointing to the beginning //! of the reversed list. @@ -806,7 +789,7 @@ class list_impl BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(to_insert)); node_algorithms::link_before(p.pointed_node(), to_insert); this->priv_size_traits().increment(); - return iterator(to_insert, this); + return iterator(to_insert, real_value_traits_ptr()); } //! Requires: Dereferencing iterator must yield @@ -1240,7 +1223,7 @@ class list_impl { BOOST_STATIC_ASSERT((!stateful_value_traits)); BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(real_value_traits::to_node_ptr(value))); - return iterator(real_value_traits::to_node_ptr(value), 0); + return iterator(real_value_traits::to_node_ptr(value), const_real_value_traits_ptr()); } //! Requires: value must be a const reference to a value inserted in a list. @@ -1258,7 +1241,7 @@ class list_impl { BOOST_STATIC_ASSERT((!stateful_value_traits)); BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(real_value_traits::to_node_ptr(const_cast (value)))); - return const_iterator(real_value_traits::to_node_ptr(const_cast (value)), 0); + return const_iterator(real_value_traits::to_node_ptr(const_cast (value)), const_real_value_traits_ptr()); } //! Requires: value must be a reference to a value inserted in a list. @@ -1273,7 +1256,7 @@ class list_impl iterator iterator_to(reference value) { BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(real_value_traits::to_node_ptr(value))); - return iterator(real_value_traits::to_node_ptr(value), this); + return iterator(real_value_traits::to_node_ptr(value), real_value_traits_ptr()); } //! Requires: value must be a const reference to a value inserted in a list. @@ -1288,7 +1271,7 @@ class list_impl const_iterator iterator_to(const_reference value) const { BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(real_value_traits::to_node_ptr(const_cast (value)))); - return const_iterator(real_value_traits::to_node_ptr(const_cast (value)), this); + return const_iterator(real_value_traits::to_node_ptr(const_cast (value)), real_value_traits_ptr()); } /// @cond @@ -1309,29 +1292,29 @@ class list_impl #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif inline bool operator< #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const list_impl &x, const list_impl &y) #else -(const list_impl &x, const list_impl &y) +(const list_impl &x, const list_impl &y) #endif { return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif bool operator== #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const list_impl &x, const list_impl &y) #else -(const list_impl &x, const list_impl &y) +(const list_impl &x, const list_impl &y) #endif { - typedef list_impl list_type; + typedef list_impl list_type; typedef typename list_type::const_iterator const_iterator; const bool C = list_type::constant_time_size; if(C && x.size() != y.size()){ @@ -1361,65 +1344,65 @@ bool operator== #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif inline bool operator!= #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const list_impl &x, const list_impl &y) #else -(const list_impl &x, const list_impl &y) +(const list_impl &x, const list_impl &y) #endif { return !(x == y); } #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif inline bool operator> #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const list_impl &x, const list_impl &y) #else -(const list_impl &x, const list_impl &y) +(const list_impl &x, const list_impl &y) #endif { return y < x; } #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif inline bool operator<= #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const list_impl &x, const list_impl &y) #else -(const list_impl &x, const list_impl &y) +(const list_impl &x, const list_impl &y) #endif { return !(y < x); } #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif inline bool operator>= #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const list_impl &x, const list_impl &y) #else -(const list_impl &x, const list_impl &y) +(const list_impl &x, const list_impl &y) #endif { return !(x < y); } #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif inline void swap #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (list_impl &x, list_impl &y) #else -(list_impl &x, list_impl &y) +(list_impl &x, list_impl &y) #endif { x.swap(y); } @@ -1428,13 +1411,13 @@ inline void swap #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else -template +template #endif struct make_list { /// @cond typedef typename pack_options - < list_defaults, + < list_defaults, #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) O1, O2, O3 #else @@ -1443,15 +1426,13 @@ struct make_list >::type packed_options; typedef typename detail::get_value_traits - ::type value_traits; + ::type value_traits; typedef list_impl < - listopt - < value_traits - , typename packed_options::size_type - , packed_options::constant_time_size - > + value_traits, + typename packed_options::size_type, + packed_options::constant_time_size > implementation_defined; /// @endcond typedef implementation_defined type; @@ -1506,7 +1487,7 @@ class list {} list& operator=(BOOST_RV_REF(list) x) - { this->Base::operator=(::boost::move(static_cast(x))); return *this; } + { return static_cast(this->Base::operator=(::boost::move(static_cast(x)))); } static list &container_from_end_iterator(iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } diff --git a/include/boost/intrusive/list_hook.hpp b/include/boost/intrusive/list_hook.hpp index b674868..ef55425 100644 --- a/include/boost/intrusive/list_hook.hpp +++ b/include/boost/intrusive/list_hook.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 @@ -38,7 +38,7 @@ struct get_list_node_algo #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else -template +template #endif struct make_list_base_hook { @@ -52,11 +52,11 @@ struct make_list_base_hook #endif >::type packed_options; - typedef detail::generic_hook + typedef generic_hook < get_list_node_algo , typename packed_options::tag , packed_options::link_mode - , detail::ListBaseHook + , ListBaseHookId > implementation_defined; /// @endcond typedef implementation_defined type; @@ -165,7 +165,7 @@ class list_base_hook #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else -template +template #endif struct make_list_member_hook { @@ -179,11 +179,11 @@ struct make_list_member_hook #endif >::type packed_options; - typedef detail::generic_hook + typedef generic_hook < get_list_node_algo , member_tag , packed_options::link_mode - , detail::NoBaseHook + , NoBaseHookId > implementation_defined; /// @endcond typedef implementation_defined type; diff --git a/include/boost/intrusive/member_value_traits.hpp b/include/boost/intrusive/member_value_traits.hpp index 0462dbd..ce35fdc 100644 --- a/include/boost/intrusive/member_value_traits.hpp +++ b/include/boost/intrusive/member_value_traits.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 diff --git a/include/boost/intrusive/options.hpp b/include/boost/intrusive/options.hpp index 5449a44..6d06a79 100644 --- a/include/boost/intrusive/options.hpp +++ b/include/boost/intrusive/options.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 @@ -26,6 +26,7 @@ namespace intrusive { /// @cond +//typedef void default_tag; struct default_tag; struct member_tag; @@ -45,11 +46,13 @@ struct BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER : public default_hook_tag\ BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_list_hook); BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_slist_hook); -BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_set_hook); -BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_uset_hook); -BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_avl_set_hook); -BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_splay_set_hook); -BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_bs_set_hook); +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 @@ -61,6 +64,15 @@ 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 { @@ -70,29 +82,36 @@ struct eval_bucket_traits template struct concrete_hook_base_value_traits { - typedef typename BaseHook::boost_intrusive_tags tags; - typedef detail::base_hook_traits + typedef typename BaseHook::hooktags tags; + typedef bhtraits < T , typename tags::node_traits , tags::link_mode , typename tags::tag - , tags::hook_type> type; + , tags::type> type; }; template struct concrete_hook_base_node_traits -{ typedef typename BaseHook::boost_intrusive_tags::node_traits type; }; +{ typedef typename BaseHook::hooktags::node_traits type; }; -template +template struct any_hook_base_value_traits { - typedef typename BaseHook::boost_intrusive_tags tags; - typedef detail::base_hook_traits + //AnyToSomeHook value_traits derive from a generic_hook + //The generic_hook is configured with any_node_traits + //and AnyToSomeHook::value_traits with the correct + //node traits for the container, so use node_traits + //from AnyToSomeHook_ProtoValueTraits and the rest of + //elements from the hooktags member of the generic_hook + typedef AnyToSomeHook_ProtoValueTraits proto_value_traits; + typedef bhtraits < T - , typename BaseHook::node_traits - , tags::link_mode - , typename tags::tag - , tags::hook_type> type; + , typename proto_value_traits::node_traits + , proto_value_traits::hooktags::link_mode + , typename proto_value_traits::hooktags::tag + , proto_value_traits::hooktags::type + > type; }; template @@ -139,6 +158,7 @@ struct get_value_traits ,detail::apply ,detail::identity >::type supposed_value_traits; + //...if it's a default hook typedef typename detail::eval_if_c < internal_base_hook_bool_is_true::value @@ -183,16 +203,6 @@ struct get_node_traits } //namespace detail{ - -//!This type indicates that no option is being used -//!and that the default options should be used -struct none -{ - template - struct pack : Base - { }; -}; - /// @endcond //!This option setter specifies if the intrusive @@ -314,7 +324,7 @@ struct value_traits template struct pack : Base { - typedef ValueTraits value_traits; + typedef ValueTraits proto_value_traits; }; /// @endcond }; @@ -327,7 +337,22 @@ template< typename Parent struct member_hook { /// @cond - typedef detail::member_hook_traits +/* + 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 @@ -335,7 +360,7 @@ struct member_hook template struct pack : Base { - typedef member_value_traits value_traits; + typedef member_value_traits proto_value_traits; }; /// @endcond }; @@ -348,12 +373,12 @@ template< typename Functor> struct function_hook { /// @cond - typedef detail::function_hook_traits + typedef fhtraits function_value_traits; template struct pack : Base { - typedef function_value_traits value_traits; + typedef function_value_traits proto_value_traits; }; /// @endcond }; @@ -368,7 +393,7 @@ struct base_hook template struct pack : Base { - typedef BaseHook value_traits; + typedef BaseHook proto_value_traits; }; /// @endcond }; @@ -583,6 +608,13 @@ struct incremental /// @cond +struct none +{ + template + struct pack : Base + {}; +}; + //To-do: pass to variadic templates #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) @@ -594,25 +626,25 @@ struct do_pack }; template -struct do_pack +struct do_pack { - //Avoid packing "none" to shorten template names + //Avoid packing "void" to shorten template names typedef Prev type; }; template < class DefaultOptions - , class O1 = none - , class O2 = none - , class O3 = none - , class O4 = none - , class O5 = none - , class O6 = none - , class O7 = none - , class O8 = none - , class O9 = none - , class O10 = none - , class O11 = none + , 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 { @@ -788,17 +820,15 @@ struct pack_options #endif struct hook_defaults - : public pack_options - < none - , void_pointer - , link_mode - , tag - , optimize_size - , store_hash - , linear - , optimize_multikey - >::type -{}; +{ + typedef void* void_pointer; + static const link_mode_type link_mode = safe_link; + typedef default_tag tag; + static const bool optimize_size = false; + static const bool store_hash = false; + static const bool linear = false; + static const bool optimize_multikey = false; +}; /// @endcond diff --git a/include/boost/intrusive/parent_from_member.hpp b/include/boost/intrusive/parent_from_member.hpp index f4658e5..e06f156 100644 --- a/include/boost/intrusive/parent_from_member.hpp +++ b/include/boost/intrusive/parent_from_member.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2010-2012 +// (C) Copyright Ion Gaztanaga 2010-2013 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/intrusive/pointer_plus_bits.hpp b/include/boost/intrusive/pointer_plus_bits.hpp index 273452c..7b0a793 100644 --- a/include/boost/intrusive/pointer_plus_bits.hpp +++ b/include/boost/intrusive/pointer_plus_bits.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 diff --git a/include/boost/intrusive/pointer_traits.hpp b/include/boost/intrusive/pointer_traits.hpp index a19ee6d..d45c027 100644 --- a/include/boost/intrusive/pointer_traits.hpp +++ b/include/boost/intrusive/pointer_traits.hpp @@ -6,7 +6,7 @@ // ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2011-2012. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2011-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) // diff --git a/include/boost/intrusive/priority_compare.hpp b/include/boost/intrusive/priority_compare.hpp index abde27a..026af29 100644 --- a/include/boost/intrusive/priority_compare.hpp +++ b/include/boost/intrusive/priority_compare.hpp @@ -31,6 +31,23 @@ struct priority_compare } }; +/// @cond + +template +struct get_prio +{ + typedef Less type; +}; + + +template +struct get_prio +{ + typedef ::boost::intrusive::priority_compare type; +}; + +/// @endcond + } //namespace intrusive } //namespace boost diff --git a/include/boost/intrusive/rbtree.hpp b/include/boost/intrusive/rbtree.hpp index 32e6b9e..04a067a 100644 --- a/include/boost/intrusive/rbtree.hpp +++ b/include/boost/intrusive/rbtree.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 @@ -13,10 +13,8 @@ #define BOOST_INTRUSIVE_RBTREE_HPP #include -#include #include #include -#include #include #include @@ -24,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -41,26 +40,14 @@ namespace intrusive { /// @cond -template -struct setopt +struct rbtree_defaults { - typedef ValueTraits value_traits; - typedef Compare compare; - typedef SizeType size_type; - static const bool constant_time_size = ConstantTimeSize; + typedef detail::default_rbtree_hook proto_value_traits; + static const bool constant_time_size = true; + typedef std::size_t size_type; + typedef void compare; }; -template -struct set_defaults - : pack_options - < none - , base_hook - , constant_time_size - , size_type - , compare > - >::type -{}; - /// @endcond //! The class template rbtree is an intrusive red-black tree container, that @@ -79,1633 +66,395 @@ struct set_defaults #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class rbtree_impl - : private detail::clear_on_destructor_base > -{ - template friend class detail::clear_on_destructor_base; - public: - typedef typename Config::value_traits value_traits; /// @cond - static const bool external_value_traits = - detail::external_value_traits_bool_is_true::value; - typedef typename detail::eval_if_c - < external_value_traits - , detail::eval_value_traits - , detail::identity - >::type real_value_traits; + : public bstree_impl + /// @endcond +{ + public: + typedef ValueTraits value_traits; + /// @cond + typedef bstree_impl< ValueTraits, VoidOrKeyComp, SizeType + , ConstantTimeSize, RbTreeAlgorithms> tree_type; + typedef tree_type implementation_defined; /// @endcond - typedef typename real_value_traits::pointer pointer; - typedef typename real_value_traits::const_pointer const_pointer; - typedef typename pointer_traits::element_type value_type; - typedef value_type key_type; - typedef typename pointer_traits::reference reference; - typedef typename pointer_traits::reference const_reference; - typedef typename pointer_traits::difference_type difference_type; - typedef typename Config::size_type size_type; - typedef typename Config::compare value_compare; - typedef value_compare key_compare; - typedef tree_iterator iterator; - typedef tree_iterator const_iterator; - typedef boost::intrusive::detail::reverse_iterator reverse_iterator; - typedef boost::intrusive::detail::reverse_iteratorconst_reverse_iterator; - typedef typename real_value_traits::node_traits node_traits; - typedef typename node_traits::node node; - typedef typename node_traits::node_ptr node_ptr; - typedef typename node_traits::const_node_ptr const_node_ptr; - typedef rbtree_algorithms node_algorithms; + typedef typename implementation_defined::pointer pointer; + typedef typename implementation_defined::const_pointer const_pointer; + typedef typename implementation_defined::value_type value_type; + typedef typename implementation_defined::key_type key_type; + typedef typename implementation_defined::reference reference; + typedef typename implementation_defined::const_reference const_reference; + typedef typename implementation_defined::difference_type difference_type; + typedef typename implementation_defined::size_type size_type; + typedef typename implementation_defined::value_compare value_compare; + typedef typename implementation_defined::key_compare key_compare; + typedef typename implementation_defined::iterator iterator; + typedef typename implementation_defined::const_iterator const_iterator; + typedef typename implementation_defined::reverse_iterator reverse_iterator; + typedef typename implementation_defined::const_reverse_iterator const_reverse_iterator; + typedef typename implementation_defined::node_traits node_traits; + typedef typename implementation_defined::node node; + typedef typename implementation_defined::node_ptr node_ptr; + typedef typename implementation_defined::const_node_ptr const_node_ptr; + typedef typename implementation_defined::node_algorithms node_algorithms; - static const bool constant_time_size = Config::constant_time_size; - static const bool stateful_value_traits = detail::is_stateful_value_traits::value; + static const bool constant_time_size = implementation_defined::constant_time_size; /// @cond private: - typedef detail::size_holder size_traits; //noncopyable BOOST_MOVABLE_BUT_NOT_COPYABLE(rbtree_impl) - enum { safemode_or_autounlink = - (int)real_value_traits::link_mode == (int)auto_unlink || - (int)real_value_traits::link_mode == (int)safe_link }; - - //Constant-time size is incompatible with auto-unlink hooks! - BOOST_STATIC_ASSERT(!(constant_time_size && ((int)real_value_traits::link_mode == (int)auto_unlink))); - - struct header_plus_size : public size_traits - { node header_; }; - - struct node_plus_pred_t : public detail::ebo_functor_holder - { - node_plus_pred_t(const value_compare &comp) - : detail::ebo_functor_holder(comp) - {} - header_plus_size header_plus_size_; - }; - - struct data_t : public rbtree_impl::value_traits - { - typedef typename rbtree_impl::value_traits value_traits; - data_t(const value_compare & comp, const value_traits &val_traits) - : value_traits(val_traits), node_plus_pred_(comp) - {} - node_plus_pred_t node_plus_pred_; - } data_; - - const value_compare &priv_comp() const - { return data_.node_plus_pred_.get(); } - - value_compare &priv_comp() - { return data_.node_plus_pred_.get(); } - - const value_traits &priv_value_traits() const - { return data_; } - - value_traits &priv_value_traits() - { return data_; } - - node_ptr priv_header_ptr() - { return pointer_traits::pointer_to(data_.node_plus_pred_.header_plus_size_.header_); } - - const_node_ptr priv_header_ptr() const - { return pointer_traits::pointer_to(data_.node_plus_pred_.header_plus_size_.header_); } - - static node_ptr uncast(const const_node_ptr & ptr) - { return pointer_traits::const_cast_from(ptr); } - - size_traits &priv_size_traits() - { return data_.node_plus_pred_.header_plus_size_; } - - const size_traits &priv_size_traits() const - { return data_.node_plus_pred_.header_plus_size_; } - - const real_value_traits &get_real_value_traits(detail::bool_) const - { return data_; } - - const real_value_traits &get_real_value_traits(detail::bool_) const - { return data_.get_value_traits(*this); } - - real_value_traits &get_real_value_traits(detail::bool_) - { return data_; } - - real_value_traits &get_real_value_traits(detail::bool_) - { return data_.get_value_traits(*this); } - - protected: - value_compare &prot_comp() - { return priv_comp(); } - - const node &prot_header_node() const - { return data_.node_plus_pred_.header_plus_size_.header_; } - - node &prot_header_node() - { return data_.node_plus_pred_.header_plus_size_.header_; } - - void prot_set_size(size_type s) - { this->priv_size_traits().set_size(s); } - /// @endcond public: - const real_value_traits &get_real_value_traits() const - { return this->get_real_value_traits(detail::bool_()); } + typedef typename implementation_defined::insert_commit_data insert_commit_data; - real_value_traits &get_real_value_traits() - { return this->get_real_value_traits(detail::bool_()); } - - typedef typename node_algorithms::insert_commit_data insert_commit_data; - - //! Effects: Constructs an empty tree. - //! - //! Complexity: Constant. - //! - //! Throws: If value_traits::node_traits::node - //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) - //! or the copy constructorof the value_compare object throws. Basic guarantee. + //! @copydoc ::boost::intrusive::bstree::bstree(const value_compare &,const value_traits &) explicit rbtree_impl( const value_compare &cmp = value_compare() , const value_traits &v_traits = value_traits()) - : data_(cmp, v_traits) - { - node_algorithms::init_header(this->priv_header_ptr()); - this->priv_size_traits().set_size(size_type(0)); - } + : tree_type(cmp, v_traits) + {} - //! Requires: Dereferencing iterator must yield an lvalue of type value_type. - //! cmp must be a comparison function that induces a strict weak ordering. - //! - //! Effects: Constructs an empty tree and inserts elements from - //! [b, e). - //! - //! Complexity: Linear in N if [b, e) is already sorted using - //! comp and otherwise N * log N, where N is the distance between first and last. - //! - //! Throws: If value_traits::node_traits::node - //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) - //! or the copy constructor/operator() of the value_compare object throws. Basic guarantee. + //! @copydoc ::boost::intrusive::bstree::bstree(bool,Iterator,Iterator,const value_compare &,const value_traits &) template rbtree_impl( bool unique, Iterator b, Iterator e , const value_compare &cmp = value_compare() , const value_traits &v_traits = value_traits()) - : data_(cmp, v_traits) - { - node_algorithms::init_header(this->priv_header_ptr()); - this->priv_size_traits().set_size(size_type(0)); - if(unique) - this->insert_unique(b, e); - else - this->insert_equal(b, e); - } - - //! Effects: to-do - //! - rbtree_impl(BOOST_RV_REF(rbtree_impl) x) - : data_(::boost::move(x.priv_comp()), ::boost::move(x.priv_value_traits())) - { - node_algorithms::init_header(this->priv_header_ptr()); - this->priv_size_traits().set_size(size_type(0)); - this->swap(x); - } - - //! Effects: to-do - //! - rbtree_impl& operator=(BOOST_RV_REF(rbtree_impl) x) - { this->swap(x); return *this; } - - //! Effects: Detaches all elements from this. The objects in the set - //! are not deleted (i.e. no destructors are called), but the nodes according to - //! the value_traits template parameter are reinitialized and thus can be reused. - //! - //! Complexity: Linear to elements contained in *this. - //! - //! Throws: Nothing. - ~rbtree_impl() + : tree_type(unique, b, e, cmp, v_traits) {} - //! Effects: Returns an iterator pointing to the beginning of the tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator begin() - { return iterator (node_traits::get_left(this->priv_header_ptr()), this); } + //! @copydoc ::boost::intrusive::bstree::bstree(bstree &&) + rbtree_impl(BOOST_RV_REF(rbtree_impl) x) + : tree_type(::boost::move(static_cast(x))) + {} - //! Effects: Returns a const_iterator pointing to the beginning of the tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator begin() const - { return cbegin(); } + //! @copydoc ::boost::intrusive::bstree::operator=(bstree &&) + rbtree_impl& operator=(BOOST_RV_REF(rbtree_impl) x) + { return static_cast(tree_type::operator=(::boost::move(static_cast(x)))); } - //! Effects: Returns a const_iterator pointing to the beginning of the tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator cbegin() const - { return const_iterator (node_traits::get_left(this->priv_header_ptr()), this); } + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::bstree::~bstree() + ~rbtree_impl(); - //! Effects: Returns an iterator pointing to the end of the tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator end() - { return iterator (this->priv_header_ptr(), this); } + //! @copydoc ::boost::intrusive::bstree::begin() + iterator begin(); - //! Effects: Returns a const_iterator pointing to the end of the tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator end() const - { return cend(); } + //! @copydoc ::boost::intrusive::bstree::begin()const + const_iterator begin() const; - //! Effects: Returns a const_iterator pointing to the end of the tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator cend() const - { return const_iterator (uncast(this->priv_header_ptr()), this); } + //! @copydoc ::boost::intrusive::bstree::cbegin()const + const_iterator cbegin() const; - //! Effects: Returns a reverse_iterator pointing to the beginning of the - //! reversed tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - reverse_iterator rbegin() - { return reverse_iterator(end()); } + //! @copydoc ::boost::intrusive::bstree::end() + iterator end(); - //! Effects: Returns a const_reverse_iterator pointing to the beginning - //! of the reversed tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator rbegin() const - { return const_reverse_iterator(end()); } + //! @copydoc ::boost::intrusive::bstree::end()const + const_iterator end() const; - //! Effects: Returns a const_reverse_iterator pointing to the beginning - //! of the reversed tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator crbegin() const - { return const_reverse_iterator(end()); } + //! @copydoc ::boost::intrusive::bstree::cend()const + const_iterator cend() const; - //! Effects: Returns a reverse_iterator pointing to the end - //! of the reversed tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - reverse_iterator rend() - { return reverse_iterator(begin()); } + //! @copydoc ::boost::intrusive::bstree::rbegin() + reverse_iterator rbegin(); - //! Effects: Returns a const_reverse_iterator pointing to the end - //! of the reversed tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator rend() const - { return const_reverse_iterator(begin()); } + //! @copydoc ::boost::intrusive::bstree::rbegin()const + const_reverse_iterator rbegin() const; - //! Effects: Returns a const_reverse_iterator pointing to the end - //! of the reversed tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator crend() const - { return const_reverse_iterator(begin()); } + //! @copydoc ::boost::intrusive::bstree::crbegin()const + const_reverse_iterator crbegin() const; - //! Precondition: end_iterator must be a valid end iterator - //! of rbtree. - //! - //! Effects: Returns a const reference to the rbtree associated to the end iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - static rbtree_impl &container_from_end_iterator(iterator end_iterator) - { return priv_container_from_end_iterator(end_iterator); } + //! @copydoc ::boost::intrusive::bstree::rend() + reverse_iterator rend(); - //! Precondition: end_iterator must be a valid end const_iterator - //! of rbtree. - //! - //! Effects: Returns a const reference to the rbtree associated to the iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - static const rbtree_impl &container_from_end_iterator(const_iterator end_iterator) - { return priv_container_from_end_iterator(end_iterator); } + //! @copydoc ::boost::intrusive::bstree::rend()const + const_reverse_iterator rend() const; - //! Precondition: it must be a valid iterator - //! of rbtree. - //! - //! Effects: Returns a const reference to the tree associated to the iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Logarithmic. - static rbtree_impl &container_from_iterator(iterator it) - { return priv_container_from_iterator(it); } + //! @copydoc ::boost::intrusive::bstree::crend()const + const_reverse_iterator crend() const; - //! Precondition: it must be a valid end const_iterator - //! of rbtree. - //! - //! Effects: Returns a const reference to the tree associated to the end iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Logarithmic. - static const rbtree_impl &container_from_iterator(const_iterator it) - { return priv_container_from_iterator(it); } + //! @copydoc ::boost::intrusive::bstree::container_from_end_iterator(iterator) + static rbtree_impl &container_from_end_iterator(iterator end_iterator); - //! Effects: Returns the value_compare object used by the tree. - //! - //! Complexity: Constant. - //! - //! Throws: If value_compare copy-constructor throws. - value_compare value_comp() const - { return priv_comp(); } + //! @copydoc ::boost::intrusive::bstree::container_from_end_iterator(const_iterator) + static const rbtree_impl &container_from_end_iterator(const_iterator end_iterator); - //! Effects: Returns true if the container is empty. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - bool empty() const - { return node_algorithms::unique(this->priv_header_ptr()); } + //! @copydoc ::boost::intrusive::bstree::container_from_iterator(iterator) + static rbtree_impl &container_from_iterator(iterator it); - //! Effects: Returns the number of elements stored in the tree. - //! - //! Complexity: Linear to elements contained in *this - //! if constant-time size option is disabled. Constant time otherwise. - //! - //! Throws: Nothing. - size_type size() const - { - if(constant_time_size) - return this->priv_size_traits().get_size(); - else{ - return (size_type)node_algorithms::size(this->priv_header_ptr()); - } - } + //! @copydoc ::boost::intrusive::bstree::container_from_iterator(const_iterator) + static const rbtree_impl &container_from_iterator(const_iterator it); - //! Effects: Swaps the contents of two rbtrees. - //! - //! Complexity: Constant. - //! - //! Throws: If the comparison functor's swap call throws. - void swap(rbtree_impl& other) - { - //This can throw - using std::swap; - swap(priv_comp(), priv_comp()); - //These can't throw - node_algorithms::swap_tree(this->priv_header_ptr(), node_ptr(other.priv_header_ptr())); - if(constant_time_size){ - size_type backup = this->priv_size_traits().get_size(); - this->priv_size_traits().set_size(other.priv_size_traits().get_size()); - other.priv_size_traits().set_size(backup); - } - } + //! @copydoc ::boost::intrusive::bstree::key_comp()const + key_compare key_comp() const; - //! Requires: value must be an lvalue - //! - //! Effects: Inserts value into the tree before the upper bound. - //! - //! Complexity: Average complexity for insert element is at - //! most logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. Strong guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. - iterator insert_equal(reference value) - { - detail::key_nodeptr_comp - key_node_comp(priv_comp(), this); - node_ptr to_insert(get_real_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->priv_header_ptr(), to_insert, key_node_comp), this); - this->priv_size_traits().increment(); - return ret; - } + //! @copydoc ::boost::intrusive::bstree::value_comp()const + value_compare value_comp() const; - //! Requires: value must be an lvalue, and "hint" must be - //! a valid iterator. - //! - //! Effects: Inserts x into the tree, using "hint" as a hint to - //! where it will be inserted. If "hint" is the upper_bound - //! the insertion takes constant time (two comparisons in the worst case) - //! - //! Complexity: Logarithmic in general, but it is amortized - //! constant time if t is inserted immediately before hint. - //! - //! Throws: If the internal value_compare ordering function throws. Strong guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. - iterator insert_equal(const_iterator hint, reference value) - { - detail::key_nodeptr_comp - key_node_comp(priv_comp(), this); - node_ptr to_insert(get_real_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->priv_header_ptr(), hint.pointed_node(), to_insert, key_node_comp), this); - this->priv_size_traits().increment(); - return ret; - } + //! @copydoc ::boost::intrusive::bstree::empty()const + bool empty() const; - //! Requires: Dereferencing iterator must yield an lvalue - //! of type value_type. - //! - //! Effects: Inserts a each element of a range into the tree - //! before the upper bound of the key of each element. - //! - //! Complexity: Insert range is in general O(N * log(N)), where N is the - //! size of the range. However, it is linear in N if the range is already sorted - //! by value_comp(). - //! - //! Throws: Nothing. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + //! @copydoc ::boost::intrusive::bstree::size()const + size_type size() const; + + //! @copydoc ::boost::intrusive::bstree::swap + void swap(rbtree_impl& other); + + //! @copydoc ::boost::intrusive::bstree::clone_from + template + void clone_from(const rbtree_impl &src, Cloner cloner, Disposer disposer); + + //! @copydoc ::boost::intrusive::bstree::insert_equal(reference) + iterator insert_equal(reference value); + + //! @copydoc ::boost::intrusive::bstree::insert_equal(const_iterator,reference) + iterator insert_equal(const_iterator hint, reference value); + + //! @copydoc ::boost::intrusive::bstree::insert_equal(Iterator,Iterator) template - void insert_equal(Iterator b, Iterator e) - { - iterator iend(this->end()); - for (; b != e; ++b) - this->insert_equal(iend, *b); - } + void insert_equal(Iterator b, Iterator e); - //! Requires: value must be an lvalue - //! - //! Effects: Inserts value into the tree if the value - //! is not already present. - //! - //! Complexity: Average complexity for insert element is at - //! most logarithmic. - //! - //! Throws: Nothing. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. - std::pair insert_unique(reference value) - { - insert_commit_data commit_data; - std::pair ret = insert_unique_check(value, priv_comp(), commit_data); - if(!ret.second) - return ret; - return std::pair (insert_unique_commit(value, commit_data), true); - } + //! @copydoc ::boost::intrusive::bstree::insert_unique(reference) + std::pair insert_unique(reference value); - //! Requires: value must be an lvalue, and "hint" must be - //! a valid iterator - //! - //! Effects: Tries to insert x into the tree, using "hint" as a hint - //! to where it will be inserted. - //! - //! Complexity: Logarithmic in general, but it is amortized - //! constant time (two comparisons in the worst case) - //! if t is inserted immediately before hint. - //! - //! Throws: Nothing. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. - iterator insert_unique(const_iterator hint, reference value) - { - insert_commit_data commit_data; - std::pair ret = insert_unique_check(hint, value, priv_comp(), commit_data); - if(!ret.second) - return ret.first; - return insert_unique_commit(value, commit_data); - } + //! @copydoc ::boost::intrusive::bstree::insert_unique(const_iterator,reference) + iterator insert_unique(const_iterator hint, reference value); - //! Requires: Dereferencing iterator must yield an lvalue - //! of type value_type. - //! - //! Effects: Tries to insert each element of a range into the tree. - //! - //! Complexity: Insert range is in general O(N * log(N)), where N is the - //! size of the range. However, it is linear in N if the range is already sorted - //! by value_comp(). - //! - //! Throws: Nothing. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. - template - void insert_unique(Iterator b, Iterator e) - { - if(this->empty()){ - iterator iend(this->end()); - for (; b != e; ++b) - this->insert_unique(iend, *b); - } - else{ - for (; b != e; ++b) - this->insert_unique(*b); - } - } - - //! Requires: key_value_comp must be a comparison function that induces - //! the same strict weak ordering as value_compare. The difference is that - //! key_value_comp compares an arbitrary key with the contained values. - //! - //! Effects: Checks if a value can be inserted in the container, using - //! a user provided key instead of the value itself. - //! - //! Returns: If there is an equivalent value - //! returns a pair containing an iterator to the already present value - //! and false. If the value can be inserted returns true in the returned - //! pair boolean and fills "commit_data" that is meant to be used with - //! the "insert_commit" function. - //! - //! Complexity: Average complexity is at most logarithmic. - //! - //! Throws: If the key_value_comp ordering function throws. Strong guarantee. - //! - //! Notes: This function is used to improve performance when constructing - //! a value_type is expensive: if there is an equivalent value - //! the constructed object must be discarded. Many times, the part of the - //! node that is used to impose the order is much cheaper to construct - //! than the value_type and this function offers the possibility to use that - //! part to check if the insertion will be successful. - //! - //! If the check is successful, the user can construct the value_type and use - //! "insert_commit" to insert the object in constant-time. This gives a total - //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)). - //! - //! "commit_data" remains valid for a subsequent "insert_commit" only if no more - //! objects are inserted or erased from the container. + //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const KeyType&,KeyValueCompare,insert_commit_data&) template 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); - std::pair ret = - (node_algorithms::insert_unique_check - (this->priv_header_ptr(), key, comp, commit_data)); - return std::pair(iterator(ret.first, this), ret.second); - } + (const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data); - //! Requires: key_value_comp must be a comparison function that induces - //! the same strict weak ordering as value_compare. The difference is that - //! key_value_comp compares an arbitrary key with the contained values. - //! - //! Effects: Checks if a value can be inserted in the container, using - //! a user provided key instead of the value itself, using "hint" - //! as a hint to where it will be inserted. - //! - //! Returns: If there is an equivalent value - //! returns a pair containing an iterator to the already present value - //! and false. If the value can be inserted returns true in the returned - //! pair boolean and fills "commit_data" that is meant to be used with - //! the "insert_commit" function. - //! - //! Complexity: Logarithmic in general, but it's amortized - //! constant time if t is inserted immediately before hint. - //! - //! Throws: If the key_value_comp ordering function throws. Strong guarantee. - //! - //! Notes: This function is used to improve performance when constructing - //! a value_type is expensive: if there is an equivalent value - //! the constructed object must be discarded. Many times, the part of the - //! constructing that is used to impose the order is much cheaper to construct - //! than the value_type and this function offers the possibility to use that key - //! to check if the insertion will be successful. - //! - //! If the check is successful, the user can construct the value_type and use - //! "insert_commit" to insert the object in constant-time. This can give a total - //! constant-time complexity to the insertion: check(O(1)) + commit(O(1)). - //! - //! "commit_data" remains valid for a subsequent "insert_commit" only if no more - //! objects are inserted or erased from the container. + //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const_iterator,const KeyType&,KeyValueCompare,insert_commit_data&) template std::pair insert_unique_check (const_iterator hint, const KeyType &key - ,KeyValueCompare key_value_comp, insert_commit_data &commit_data) - { - detail::key_nodeptr_comp - comp(key_value_comp, this); - std::pair ret = - (node_algorithms::insert_unique_check - (this->priv_header_ptr(), hint.pointed_node(), key, comp, commit_data)); - return std::pair(iterator(ret.first, this), ret.second); - } + ,KeyValueCompare key_value_comp, insert_commit_data &commit_data); - //! Requires: value must be an lvalue of type value_type. commit_data - //! must have been obtained from a previous call to "insert_check". - //! No objects should have been inserted or erased from the container between - //! the "insert_check" that filled "commit_data" and the call to "insert_commit". - //! - //! Effects: Inserts the value in the avl_set using the information obtained - //! from the "commit_data" that a previous "insert_check" filled. - //! - //! Returns: An iterator to the newly inserted object. - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Notes: This function has only sense if a "insert_check" has been - //! previously executed to fill "commit_data". No value should be inserted or - //! 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(get_real_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->priv_header_ptr(), to_insert, commit_data); - this->priv_size_traits().increment(); - return iterator(to_insert, this); - } + //! @copydoc ::boost::intrusive::bstree::insert_unique_commit + iterator insert_unique_commit(reference value, const insert_commit_data &commit_data); - //! Requires: value must be an lvalue, "pos" must be - //! a valid iterator (or end) and must be the succesor of value - //! once inserted according to the predicate - //! - //! Effects: Inserts x into the tree before "pos". - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Note: This function does not check preconditions so if "pos" is not - //! the successor of "value" tree ordering invariant will be broken. - //! This is a low-level function to be used only for performance reasons - //! by advanced users. - iterator insert_before(const_iterator pos, reference value) - { - node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); - if(safemode_or_autounlink) - BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); - this->priv_size_traits().increment(); - return iterator(node_algorithms::insert_before - (this->priv_header_ptr(), pos.pointed_node(), to_insert), this); - } + //! @copydoc ::boost::intrusive::bstree::insert_unique(Iterator,Iterator) + template + void insert_unique(Iterator b, Iterator e); - //! Requires: value must be an lvalue, and it must be no less - //! than the greatest inserted key - //! - //! Effects: Inserts x into the tree in the last position. - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Note: This function does not check preconditions so if value is - //! less than the greatest inserted key tree ordering invariant will be broken. - //! This function is slightly more efficient than using "insert_before". - //! This is a low-level function to be used only for performance reasons - //! by advanced users. - void push_back(reference value) - { - node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); - if(safemode_or_autounlink) - BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); - this->priv_size_traits().increment(); - node_algorithms::push_back(this->priv_header_ptr(), to_insert); - } + //! @copydoc ::boost::intrusive::bstree::insert_before + iterator insert_before(const_iterator pos, reference value); - //! Requires: value must be an lvalue, and it must be no greater - //! than the minimum inserted key - //! - //! Effects: Inserts x into the tree in the first position. - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Note: This function does not check preconditions so if value is - //! greater than the minimum inserted key tree ordering invariant will be broken. - //! This function is slightly more efficient than using "insert_before". - //! This is a low-level function to be used only for performance reasons - //! by advanced users. - void push_front(reference value) - { - node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); - if(safemode_or_autounlink) - BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); - this->priv_size_traits().increment(); - node_algorithms::push_front(this->priv_header_ptr(), to_insert); - } + //! @copydoc ::boost::intrusive::bstree::push_back + void push_back(reference value); - //! Effects: Erases the element pointed to by pos. - //! - //! Complexity: Average complexity for erase element is constant time. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - iterator erase(const_iterator i) - { - const_iterator ret(i); - ++ret; - node_ptr to_erase(i.pointed_node()); - if(safemode_or_autounlink) - BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!node_algorithms::unique(to_erase)); - node_algorithms::erase(this->priv_header_ptr(), to_erase); - this->priv_size_traits().decrement(); - if(safemode_or_autounlink) - node_algorithms::init(to_erase); - return ret.unconst(); - } + //! @copydoc ::boost::intrusive::bstree::push_front + void push_front(reference value); - //! Effects: Erases the range pointed to by b end e. - //! - //! Complexity: Average complexity for erase range is at most - //! O(log(size() + N)), where N is the number of elements in the range. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - iterator erase(const_iterator b, const_iterator e) - { size_type n; return private_erase(b, e, n); } + //! @copydoc ::boost::intrusive::bstree::erase(const_iterator) + iterator erase(const_iterator i); - //! Effects: Erases all the elements with the given value. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: O(log(size() + N). - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - size_type erase(const_reference value) - { return this->erase(value, priv_comp()); } + //! @copydoc ::boost::intrusive::bstree::erase(const_iterator,const_iterator) + iterator erase(const_iterator b, const_iterator e); - //! Effects: Erases all the elements with the given key. - //! according to the comparison functor "comp". - //! - //! Returns: The number of erased elements. - //! - //! Complexity: O(log(size() + N). - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. + //! @copydoc ::boost::intrusive::bstree::erase(const_reference) + size_type erase(const_reference value); + + //! @copydoc ::boost::intrusive::bstree::erase(const KeyType&,KeyValueCompare) template - size_type erase(const KeyType& key, KeyValueCompare comp - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) - { - std::pair p = this->equal_range(key, comp); - size_type n; - private_erase(p.first, p.second, n); - return n; - } + size_type erase(const KeyType& key, KeyValueCompare comp); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases the element pointed to by pos. - //! Disposer::operator()(pointer) is called for the removed element. - //! - //! Complexity: Average complexity for erase element is constant time. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_iterator,Disposer) template - iterator erase_and_dispose(const_iterator i, Disposer disposer) - { - node_ptr to_erase(i.pointed_node()); - iterator ret(this->erase(i)); - disposer(get_real_value_traits().to_value_ptr(to_erase)); - return ret; - } + iterator erase_and_dispose(const_iterator i, Disposer disposer); - #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_iterator,const_iterator,Disposer) template - iterator erase_and_dispose(iterator i, Disposer disposer) - { return this->erase_and_dispose(const_iterator(i), disposer); } - #endif + iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements with the given value. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: O(log(size() + N). - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. + //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_reference, Disposer) template - size_type erase_and_dispose(const_reference value, Disposer disposer) - { - std::pair p = this->equal_range(value); - size_type n; - private_erase(p.first, p.second, n, disposer); - return n; - } + size_type erase_and_dispose(const_reference value, Disposer disposer); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases the range pointed to by b end e. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Complexity: Average complexity for erase range is at most - //! O(log(size() + N)), where N is the number of elements in the range. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators - //! to the erased elements. - template - iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer) - { size_type n; return private_erase(b, e, n, disposer); } - - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements with the given key. - //! according to the comparison functor "comp". - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: O(log(size() + N). - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const KeyType&,KeyValueCompare,Disposer) template - size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) - { - std::pair p = this->equal_range(key, comp); - size_type n; - private_erase(p.first, p.second, n, disposer); - return n; - } + size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer); - //! Effects: Erases all of the elements. - //! - //! Complexity: Linear to the number of elements on the container. - //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - void clear() - { - if(safemode_or_autounlink){ - this->clear_and_dispose(detail::null_disposer()); - } - else{ - node_algorithms::init_header(this->priv_header_ptr()); - this->priv_size_traits().set_size(0); - } - } + //! @copydoc ::boost::intrusive::bstree::clear + void clear(); - //! Effects: Erases all of the elements calling disposer(p) for - //! each node to be erased. - //! Complexity: Average complexity for is at most O(log(size() + N)), - //! where N is the number of elements in the container. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. Calls N times to disposer functor. + //! @copydoc ::boost::intrusive::bstree::clear_and_dispose template - void clear_and_dispose(Disposer disposer) - { - node_algorithms::clear_and_dispose(this->priv_header_ptr() - , detail::node_disposer(disposer, this)); - node_algorithms::init_header(this->priv_header_ptr()); - this->priv_size_traits().set_size(0); - } + void clear_and_dispose(Disposer disposer); - //! Effects: Returns the number of contained elements with the given value - //! - //! Complexity: Logarithmic to the number of elements contained plus lineal - //! to number of objects with the given value. - //! - //! Throws: Nothing. - size_type count(const_reference value) const - { return this->count(value, priv_comp()); } + //! @copydoc ::boost::intrusive::bstree::count(const_reference)const + size_type count(const_reference value) const; - //! Effects: Returns the number of contained elements with the given key - //! - //! Complexity: Logarithmic to the number of elements contained plus lineal - //! to number of objects with the given key. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const template - size_type count(const KeyType &key, KeyValueCompare comp) const - { - std::pair ret = this->equal_range(key, comp); - return std::distance(ret.first, ret.second); - } - - //! Effects: Returns an iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - iterator lower_bound(const_reference value) - { return this->lower_bound(value, priv_comp()); } - - //! Effects: Returns an iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - const_iterator lower_bound(const_reference value) const - { return this->lower_bound(value, priv_comp()); } - - //! Effects: Returns an iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + size_type count(const KeyType& key, KeyValueCompare comp) const; + + //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference) + iterator lower_bound(const_reference value); + + //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare) template - iterator lower_bound(const KeyType &key, KeyValueCompare comp) - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - return iterator(node_algorithms::lower_bound - (this->priv_header_ptr(), key, key_node_comp), this); - } + iterator lower_bound(const KeyType& key, KeyValueCompare comp); - //! Effects: Returns a const iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference)const + const_iterator lower_bound(const_reference value) const; + + //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare)const template - const_iterator lower_bound(const KeyType &key, KeyValueCompare comp) const - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - return const_iterator(node_algorithms::lower_bound - (this->priv_header_ptr(), key, key_node_comp), this); - } + const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Returns an iterator to the first element whose - //! key is greater than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - iterator upper_bound(const_reference value) - { return this->upper_bound(value, priv_comp()); } + //! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference) + iterator upper_bound(const_reference value); - //! Effects: Returns an iterator to the first element whose - //! key is greater than k according to comp or end() if that element - //! does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare) template - iterator upper_bound(const KeyType &key, KeyValueCompare comp) - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - return iterator(node_algorithms::upper_bound - (this->priv_header_ptr(), key, key_node_comp), this); - } + iterator upper_bound(const KeyType& key, KeyValueCompare comp); - //! Effects: Returns an iterator to the first element whose - //! key is greater than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - const_iterator upper_bound(const_reference value) const - { return this->upper_bound(value, priv_comp()); } + //! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference)const + const_iterator upper_bound(const_reference value) const; - //! Effects: Returns an iterator to the first element whose - //! key is greater than k according to comp or end() if that element - //! does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare)const template - const_iterator upper_bound(const KeyType &key, KeyValueCompare comp) const - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - return const_iterator(node_algorithms::upper_bound - (this->priv_header_ptr(), key, key_node_comp), this); - } + const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Finds an iterator to the first element whose key is - //! k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - iterator find(const_reference value) - { return this->find(value, priv_comp()); } + //! @copydoc ::boost::intrusive::bstree::find(const_reference) + iterator find(const_reference value); - //! Effects: Finds an iterator to the first element whose key is - //! k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare) template - iterator find(const KeyType &key, KeyValueCompare comp) - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - return iterator - (node_algorithms::find(this->priv_header_ptr(), key, key_node_comp), this); - } + iterator find(const KeyType& key, KeyValueCompare comp); - //! Effects: Finds a const_iterator to the first element whose key is - //! k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - const_iterator find(const_reference value) const - { return this->find(value, priv_comp()); } + //! @copydoc ::boost::intrusive::bstree::find(const_reference)const + const_iterator find(const_reference value) const; - //! Effects: Finds a const_iterator to the first element whose key is - //! k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare)const template - const_iterator find(const KeyType &key, KeyValueCompare comp) const - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - return const_iterator - (node_algorithms::find(this->priv_header_ptr(), key, key_node_comp), this); - } + const_iterator find(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - std::pair equal_range(const_reference value) - { return this->equal_range(value, priv_comp()); } + //! @copydoc ::boost::intrusive::bstree::equal_range(const_reference) + std::pair equal_range(const_reference value); - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare) template - std::pair equal_range(const KeyType &key, KeyValueCompare comp) - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - std::pair ret - (node_algorithms::equal_range(this->priv_header_ptr(), key, key_node_comp)); - return std::pair(iterator(ret.first, this), iterator(ret.second, this)); - } + std::pair equal_range(const KeyType& key, KeyValueCompare comp); - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::equal_range(const_reference)const std::pair - equal_range(const_reference value) const - { return this->equal_range(value, priv_comp()); } + equal_range(const_reference value) const; - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare)const template std::pair - equal_range(const KeyType &key, KeyValueCompare comp) const - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - std::pair ret - (node_algorithms::equal_range(this->priv_header_ptr(), key, key_node_comp)); - return std::pair(const_iterator(ret.first, this), const_iterator(ret.second, this)); - } + equal_range(const KeyType& key, KeyValueCompare comp) const; - //! Requires: 'lower_value' must not be greater than 'upper_value'. If - //! 'lower_value' == 'upper_value', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise - //! - //! second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the predicate throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_value and upper_value. + //! @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) - { return this->bounded_range(lower_value, upper_value, priv_comp(), left_closed, right_closed); } + (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); - //! Requires: KeyValueCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. - //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If - //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key, comp) if left_closed, upper_bound(lower_key, comp) otherwise - //! - //! second = upper_bound(upper_key, comp) if right_closed, lower_bound(upper_key, comp) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_key and upper_key. + //! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool) template std::pair bounded_range - (const KeyType &lower_key, const KeyType &upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - std::pair ret - (node_algorithms::bounded_range - (this->priv_header_ptr(), lower_key, upper_key, key_node_comp, left_closed, right_closed)); - return std::pair(iterator(ret.first, this), iterator(ret.second, this)); - } + (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed); - //! Requires: 'lower_value' must not be greater than 'upper_value'. If - //! 'lower_value' == 'upper_value', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise - //! - //! second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the predicate throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_value and upper_value. - std::pair bounded_range - (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const - { return this->bounded_range(lower_value, upper_value, priv_comp(), left_closed, right_closed); } + //! @copydoc ::boost::intrusive::bstree::bounded_range(const_reference,const_reference,bool,bool)const + std::pair + bounded_range(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; - //! Requires: KeyValueCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. - //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If - //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key, comp) if left_closed, upper_bound(lower_key, comp) otherwise - //! - //! second = upper_bound(upper_key, comp) if right_closed, lower_bound(upper_key, comp) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_key and upper_key. + //! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const template - std::pair bounded_range - (const KeyType &lower_key, const KeyType &upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - std::pair ret - (node_algorithms::bounded_range - (this->priv_header_ptr(), lower_key, upper_key, key_node_comp, left_closed, right_closed)); - return std::pair(const_iterator(ret.first, this), const_iterator(ret.second, this)); - } + std::pair bounded_range + (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! Cloner should yield to nodes equivalent to the original nodes. - //! - //! Effects: Erases all the elements from *this - //! calling Disposer::operator()(pointer), clones all the - //! elements from src calling Cloner::operator()(const_reference ) - //! and inserts them on *this. Copies the predicate from the source container. - //! - //! If cloner throws, all cloned elements are unlinked and disposed - //! calling Disposer::operator()(pointer). - //! - //! Complexity: Linear to erased plus inserted elements. - //! - //! Throws: If cloner throws or predicate copy assignment throws. Basic guarantee. - template - void clone_from(const rbtree_impl &src, Cloner cloner, Disposer disposer) - { - this->clear_and_dispose(disposer); - if(!src.empty()){ - detail::exception_disposer - rollback(*this, disposer); - node_algorithms::clone - (const_node_ptr(src.priv_header_ptr()) - ,node_ptr(this->priv_header_ptr()) - ,detail::node_cloner(cloner, this) - ,detail::node_disposer(disposer, this)); - this->priv_size_traits().set_size(src.priv_size_traits().get_size()); - this->priv_comp() = src.priv_comp(); - rollback.release(); - } - } + //! @copydoc ::boost::intrusive::bstree::s_iterator_to(reference) + static iterator s_iterator_to(reference value); - //! Effects: Unlinks the leftmost node from the tree. - //! - //! Complexity: Average complexity is constant time. - //! - //! Throws: Nothing. - //! - //! Notes: This function breaks the tree and the tree can - //! only be used for more unlink_leftmost_without_rebalance calls. - //! This function is normally used to achieve a step by step - //! controlled destruction of the tree. - pointer unlink_leftmost_without_rebalance() - { - node_ptr to_be_disposed(node_algorithms::unlink_leftmost_without_rebalance - (this->priv_header_ptr())); - if(!to_be_disposed) - return 0; - this->priv_size_traits().decrement(); - if(safemode_or_autounlink)//If this is commented does not work with normal_link - node_algorithms::init(to_be_disposed); - return get_real_value_traits().to_value_ptr(to_be_disposed); - } + //! @copydoc ::boost::intrusive::bstree::s_iterator_to(const_reference) + static const_iterator s_iterator_to(const_reference value); - //! Requires: replace_this must be a valid iterator of *this - //! and with_this must not be inserted in any tree. - //! - //! Effects: Replaces replace_this in its position in the - //! tree with with_this. The tree does not need to be rebalanced. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This function will break container ordering invariants if - //! with_this is not equivalent to *replace_this according to the - //! ordering rules. This function is faster than erasing and inserting - //! the node, since no rebalancing or comparison is needed. - void replace_node(iterator replace_this, reference with_this) - { - node_algorithms::replace_node( get_real_value_traits().to_node_ptr(*replace_this) - , this->priv_header_ptr() - , get_real_value_traits().to_node_ptr(with_this)); - if(safemode_or_autounlink) - node_algorithms::init(replace_this.pointed_node()); - } + //! @copydoc ::boost::intrusive::bstree::iterator_to(reference) + iterator iterator_to(reference value); - //! Requires: value must be an lvalue and shall be in a set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid iterator i belonging to the set - //! that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This static function is available only if the value traits - //! is stateless. - static iterator s_iterator_to(reference value) - { - BOOST_STATIC_ASSERT((!stateful_value_traits)); - return iterator (value_traits::to_node_ptr(value), 0); - } + //! @copydoc ::boost::intrusive::bstree::iterator_to(const_reference)const + const_iterator iterator_to(const_reference value) const; - //! Requires: value must be an lvalue and shall be in a set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid const_iterator i belonging to the - //! set that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This static function is available only if the value traits - //! is stateless. - static const_iterator s_iterator_to(const_reference value) - { - BOOST_STATIC_ASSERT((!stateful_value_traits)); - return const_iterator (value_traits::to_node_ptr(const_cast (value)), 0); - } + //! @copydoc ::boost::intrusive::bstree::init_node(reference) + static void init_node(reference value); - //! Requires: value must be an lvalue and shall be in a set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid iterator i belonging to the set - //! that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator iterator_to(reference value) - { return iterator (value_traits::to_node_ptr(value), this); } + //! @copydoc ::boost::intrusive::bstree::unlink_leftmost_without_rebalance + pointer unlink_leftmost_without_rebalance(); - //! Requires: value must be an lvalue and shall be in a set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid const_iterator i belonging to the - //! set that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator iterator_to(const_reference value) const - { return const_iterator (value_traits::to_node_ptr(const_cast (value)), this); } + //! @copydoc ::boost::intrusive::bstree::replace_node + void replace_node(iterator replace_this, reference with_this); - //! Requires: value shall not be in a tree. - //! - //! Effects: init_node puts the hook of a value in a well-known default - //! state. - //! - //! Throws: Nothing. - //! - //! Complexity: Constant time. - //! - //! Note: This function puts the hook in the well-known default state - //! used by auto_unlink and safe hooks. - static void init_node(reference value) - { node_algorithms::init(value_traits::to_node_ptr(value)); } - - //! Effects: removes "value" from the container. - //! - //! Throws: Nothing. - //! - //! Complexity: Logarithmic time. - //! - //! Note: This static function is only usable with non-constant - //! time size containers that have stateless comparison functors. - //! - //! If the user calls - //! this function with a constant time size container or stateful comparison - //! functor a compilation error will be issued. - static void remove_node(reference value) - { - BOOST_STATIC_ASSERT((!constant_time_size)); - node_ptr to_remove(value_traits::to_node_ptr(value)); - node_algorithms::unlink(to_remove); - if(safemode_or_autounlink) - node_algorithms::init(to_remove); - } - - /// @cond - private: - template - iterator private_erase(const_iterator b, const_iterator e, size_type &n, Disposer disposer) - { - for(n = 0; b != e; ++n) - this->erase_and_dispose(b++, disposer); - return b.unconst(); - } - - iterator private_erase(const_iterator b, const_iterator e, size_type &n) - { - for(n = 0; b != e; ++n) - this->erase(b++); - return b.unconst(); - } - /// @endcond - - private: - static rbtree_impl &priv_container_from_end_iterator(const const_iterator &end_iterator) - { - header_plus_size *r = detail::parent_from_member - ( boost::intrusive::detail::to_raw_pointer(end_iterator.pointed_node()), &header_plus_size::header_); - node_plus_pred_t *n = detail::parent_from_member - (r, &node_plus_pred_t::header_plus_size_); - data_t *d = detail::parent_from_member(n, &data_t::node_plus_pred_); - rbtree_impl *rb = detail::parent_from_member(d, &rbtree_impl::data_); - return *rb; - } - - static rbtree_impl &priv_container_from_iterator(const const_iterator &it) - { return priv_container_from_end_iterator(it.end_iterator_from_it()); } + //! @copydoc ::boost::intrusive::bstree::remove_node + void remove_node(reference value); + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED }; #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + template -#else -template -#endif -inline bool operator< -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const rbtree_impl &x, const rbtree_impl &y) -#else -(const rbtree_impl &x, const rbtree_impl &y) -#endif -{ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } +bool operator< (const rbtree_impl &x, const rbtree_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -bool operator== -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const rbtree_impl &x, const rbtree_impl &y) -#else -(const rbtree_impl &x, const rbtree_impl &y) -#endif -{ - typedef rbtree_impl tree_type; - typedef typename tree_type::const_iterator const_iterator; +bool operator==(const rbtree_impl &x, const rbtree_impl &y); - if(tree_type::constant_time_size && x.size() != y.size()){ - return false; - } - const_iterator end1 = x.end(); - const_iterator i1 = x.begin(); - const_iterator i2 = y.begin(); - if(tree_type::constant_time_size){ - while (i1 != end1 && *i1 == *i2) { - ++i1; - ++i2; - } - return i1 == end1; - } - else{ - const_iterator end2 = y.end(); - while (i1 != end1 && i2 != end2 && *i1 == *i2) { - ++i1; - ++i2; - } - return i1 == end1 && i2 == end2; - } -} - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator!= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const rbtree_impl &x, const rbtree_impl &y) -#else -(const rbtree_impl &x, const rbtree_impl &y) -#endif -{ return !(x == y); } +bool operator!= (const rbtree_impl &x, const rbtree_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator> -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const rbtree_impl &x, const rbtree_impl &y) -#else -(const rbtree_impl &x, const rbtree_impl &y) -#endif -{ return y < x; } +bool operator>(const rbtree_impl &x, const rbtree_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator<= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const rbtree_impl &x, const rbtree_impl &y) -#else -(const rbtree_impl &x, const rbtree_impl &y) -#endif -{ return !(y < x); } +bool operator<=(const rbtree_impl &x, const rbtree_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator>= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const rbtree_impl &x, const rbtree_impl &y) -#else -(const rbtree_impl &x, const rbtree_impl &y) -#endif -{ return !(x < y); } +bool operator>=(const rbtree_impl &x, const rbtree_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline void swap -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(rbtree_impl &x, rbtree_impl &y) -#else -(rbtree_impl &x, rbtree_impl &y) -#endif -{ x.swap(y); } +void swap(rbtree_impl &x, rbtree_impl &y); -/// @cond -#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) -template -#else -template -#endif -struct make_rbtree_opt -{ - typedef typename pack_options - < set_defaults, - #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - O1, O2, O3, O4 - #else - Options... - #endif - >::type packed_options; - typedef typename detail::get_value_traits - ::type value_traits; - - typedef setopt - < value_traits - , typename packed_options::compare - , typename packed_options::size_type - , packed_options::constant_time_size - > type; -}; -/// @endcond +#endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Helper metafunction to define a \c rbtree that yields to the same type when the //! same options (either explicitly or implicitly) are used. #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else -template +template #endif struct make_rbtree { /// @cond + typedef typename pack_options + < rbtree_defaults, + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3, O4 + #else + Options... + #endif + >::type packed_options; + + typedef typename detail::get_value_traits + ::type value_traits; + typedef rbtree_impl - < typename make_rbtree_opt::type - > implementation_defined; + < value_traits + , typename packed_options::compare + , typename packed_options::size_type + , packed_options::constant_time_size + > implementation_defined; /// @endcond typedef implementation_defined type; }; + #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) @@ -1738,6 +487,8 @@ class rbtree 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)); @@ -1759,7 +510,7 @@ class rbtree {} rbtree& operator=(BOOST_RV_REF(rbtree) x) - { this->Base::operator=(::boost::move(static_cast(x))); return *this; } + { return static_cast(this->Base::operator=(::boost::move(static_cast(x)))); } static rbtree &container_from_end_iterator(iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } @@ -1767,16 +518,15 @@ class rbtree static const rbtree &container_from_end_iterator(const_iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } - static rbtree &container_from_it(iterator it) + static rbtree &container_from_iterator(iterator it) { return static_cast(Base::container_from_iterator(it)); } - static const rbtree &container_from_it(const_iterator it) + static const rbtree &container_from_iterator(const_iterator it) { return static_cast(Base::container_from_iterator(it)); } }; #endif - } //namespace intrusive } //namespace boost diff --git a/include/boost/intrusive/rbtree_algorithms.hpp b/include/boost/intrusive/rbtree_algorithms.hpp index fc28630..dc01826 100644 --- a/include/boost/intrusive/rbtree_algorithms.hpp +++ b/include/boost/intrusive/rbtree_algorithms.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2012. +// (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 @@ -55,12 +55,50 @@ #include #include -#include +#include #include namespace boost { namespace intrusive { +#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + +template +struct rbtree_node_cloner + : private detail::ebo_functor_holder +{ + typedef typename NodeTraits::node_ptr node_ptr; + typedef detail::ebo_functor_holder base_t; + + rbtree_node_cloner(F f) + : base_t(f) + {} + + node_ptr operator()(const node_ptr & p) + { + node_ptr n = base_t::get()(p); + NodeTraits::set_color(n, NodeTraits::get_color(p)); + return n; + } +}; + +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 //! nodes forming a red-black tree. The insertion and deletion algorithms are //! based on those in Cormen, Leiserson, and Rivest, Introduction to Algorithms @@ -82,7 +120,7 @@ namespace intrusive { //! //! Typedefs: //! -//! node: The type of the node that forms the circular list +//! node: The type of the node that forms the binary search tree //! //! node_ptr: A pointer to a node //! @@ -113,6 +151,9 @@ namespace intrusive { //! static color red(); template class rbtree_algorithms + #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + : public bstree_algorithms + #endif { public: typedef NodeTraits node_traits; @@ -124,167 +165,71 @@ class rbtree_algorithms /// @cond private: - typedef detail::tree_algorithms tree_algorithms; + typedef bstree_algorithms bstree_algorithms; - template - struct rbtree_node_cloner - : private detail::ebo_functor_holder - { - typedef detail::ebo_functor_holder base_t; - - rbtree_node_cloner(F f) - : base_t(f) - {} - - node_ptr operator()(const node_ptr & p) - { - node_ptr n = base_t::get()(p); - NodeTraits::set_color(n, NodeTraits::get_color(p)); - return n; - } - }; - - struct rbtree_erase_fixup - { - 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); - } - }; - - static node_ptr uncast(const const_node_ptr & ptr) - { return pointer_traits::const_cast_from(ptr); } /// @endcond public: - static node_ptr begin_node(const const_node_ptr & header) - { return tree_algorithms::begin_node(header); } - - static node_ptr end_node(const const_node_ptr & header) - { return tree_algorithms::end_node(header); } //! This type is the information that will be //! filled by insert_unique_check - typedef typename tree_algorithms::insert_commit_data insert_commit_data; + typedef typename bstree_algorithms::insert_commit_data insert_commit_data; - //! Requires: header1 and header2 must be the header nodes - //! of two trees. - //! - //! Effects: Swaps two trees. After the function header1 will contain - //! links to the second tree and header2 will have links to the first tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - static void swap_tree(const node_ptr & header1, const node_ptr & header2) - { return tree_algorithms::swap_tree(header1, header2); } + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! Requires: node1 and node2 can't be header nodes - //! of two trees. - //! - //! Effects: Swaps two nodes. After the function node1 will be inserted - //! in the position node2 before the function. node2 will be inserted in the - //! position node1 had before the function. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - //! - //! Note: This function will break container ordering invariants if - //! node1 and node2 are not equivalent according to the ordering rules. - //! - //!Experimental function + //! @copydoc ::boost::intrusive::bstree_algorithms::get_header(const const_node_ptr&) + static node_ptr get_header(const const_node_ptr & n); + + //! @copydoc ::boost::intrusive::bstree_algorithms::begin_node + static node_ptr begin_node(const const_node_ptr & header); + + //! @copydoc ::boost::intrusive::bstree_algorithms::end_node + static node_ptr end_node(const const_node_ptr & header); + + //! @copydoc ::boost::intrusive::bstree_algorithms::swap_tree + static void swap_tree(const node_ptr & header1, const node_ptr & header2); + + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + + //! @copydoc ::boost::intrusive::bstree_algorithms::swap_nodes(const node_ptr&,const node_ptr&) static void swap_nodes(const node_ptr & node1, const node_ptr & node2) { if(node1 == node2) return; - node_ptr header1(tree_algorithms::get_header(node1)), header2(tree_algorithms::get_header(node2)); + node_ptr header1(bstree_algorithms::get_header(node1)), header2(bstree_algorithms::get_header(node2)); swap_nodes(node1, header1, node2, header2); } - //! Requires: node1 and node2 can't be header nodes - //! of two trees with header header1 and header2. - //! - //! Effects: Swaps two nodes. After the function node1 will be inserted - //! in the position node2 before the function. node2 will be inserted in the - //! position node1 had before the function. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This function will break container ordering invariants if - //! node1 and node2 are not equivalent according to the ordering rules. - //! - //!Experimental function + //! @copydoc ::boost::intrusive::bstree_algorithms::swap_nodes(const node_ptr&,const node_ptr&,const node_ptr&,const node_ptr&) static void swap_nodes(const node_ptr & node1, const node_ptr & header1, const node_ptr & node2, const node_ptr & header2) { if(node1 == node2) return; - tree_algorithms::swap_nodes(node1, header1, node2, header2); + bstree_algorithms::swap_nodes(node1, header1, node2, header2); //Swap color color c = NodeTraits::get_color(node1); NodeTraits::set_color(node1, NodeTraits::get_color(node2)); NodeTraits::set_color(node2, c); } - //! Requires: node_to_be_replaced must be inserted in a tree - //! and new_node must not be inserted in a tree. - //! - //! Effects: Replaces node_to_be_replaced in its position in the - //! tree with new_node. The tree does not need to be rebalanced - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - //! - //! Note: This function will break container ordering invariants if - //! new_node is not equivalent to node_to_be_replaced according to the - //! ordering rules. This function is faster than erasing and inserting - //! the node, since no rebalancing and comparison is needed. - //! - //!Experimental function + //! @copydoc ::boost::intrusive::bstree_algorithms::replace_node(const node_ptr&,const node_ptr&) static void replace_node(const node_ptr & node_to_be_replaced, const node_ptr & new_node) { if(node_to_be_replaced == new_node) return; - replace_node(node_to_be_replaced, tree_algorithms::get_header(node_to_be_replaced), new_node); + replace_node(node_to_be_replaced, bstree_algorithms::get_header(node_to_be_replaced), new_node); } - //! Requires: node_to_be_replaced must be inserted in a tree - //! with header "header" and new_node must not be inserted in a tree. - //! - //! Effects: Replaces node_to_be_replaced in its position in the - //! tree with new_node. The tree does not need to be rebalanced - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This function will break container ordering invariants if - //! new_node is not equivalent to node_to_be_replaced according to the - //! ordering rules. This function is faster than erasing and inserting - //! the node, since no rebalancing or comparison is needed. - //! - //!Experimental function + //! @copydoc ::boost::intrusive::bstree_algorithms::replace_node(const node_ptr&,const node_ptr&,const node_ptr&) static void replace_node(const node_ptr & node_to_be_replaced, const node_ptr & header, const node_ptr & new_node) { - tree_algorithms::replace_node(node_to_be_replaced, header, new_node); + bstree_algorithms::replace_node(node_to_be_replaced, header, new_node); NodeTraits::set_color(new_node, NodeTraits::get_color(node_to_be_replaced)); } - //! Requires: node is a tree node but not the header. - //! - //! Effects: Unlinks the node and rebalances the tree. - //! - //! Complexity: Average complexity is constant time. - //! - //! Throws: Nothing. - static void unlink(const node_ptr & node) + //! @copydoc ::boost::intrusive::bstree_algorithms::unlink(const node_ptr&) + static void unlink(const node_ptr& node) { node_ptr x = NodeTraits::get_parent(node); if(x){ @@ -294,517 +239,176 @@ class rbtree_algorithms } } - //! Requires: header is the header of a tree. - //! - //! Effects: Unlinks the leftmost node from the tree, and - //! updates the header link to the new leftmost node. - //! - //! Complexity: Average complexity is constant time. - //! - //! Throws: Nothing. - //! - //! Notes: This function breaks the tree and the tree can - //! only be used for more unlink_leftmost_without_rebalance calls. - //! This function is normally used to achieve a step by step - //! controlled destruction of the tree. - static node_ptr unlink_leftmost_without_rebalance(const node_ptr & header) - { return tree_algorithms::unlink_leftmost_without_rebalance(header); } + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::bstree_algorithms::unlink_leftmost_without_rebalance + static node_ptr unlink_leftmost_without_rebalance(const node_ptr & header); - //! Requires: node is a node of the tree or an node initialized - //! by init(...). - //! - //! Effects: Returns true if the node is initialized by init(). - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - static bool unique(const const_node_ptr & node) - { return tree_algorithms::unique(node); } + //! @copydoc ::boost::intrusive::bstree_algorithms::unique(const const_node_ptr&) + static bool unique(const const_node_ptr & node); - //! Requires: node is a node of the tree but it's not the header. - //! - //! Effects: Returns the number of nodes of the subtree. - //! - //! Complexity: Linear time. - //! - //! Throws: Nothing. - static std::size_t count(const const_node_ptr & node) - { return tree_algorithms::count(node); } + //! @copydoc ::boost::intrusive::bstree_algorithms::size(const const_node_ptr&) + static std::size_t size(const const_node_ptr & header); - //! Requires: header is the header node of the tree. - //! - //! Effects: Returns the number of nodes above the header. - //! - //! Complexity: Linear time. - //! - //! Throws: Nothing. - static std::size_t size(const const_node_ptr & header) - { return tree_algorithms::size(header); } + //! @copydoc ::boost::intrusive::bstree_algorithms::next_node(const node_ptr&) + static node_ptr next_node(const node_ptr & node); - //! Requires: p is a node from the tree except the header. - //! - //! Effects: Returns the next node of the tree. - //! - //! Complexity: Average constant time. - //! - //! Throws: Nothing. - static node_ptr next_node(const node_ptr & p) - { return tree_algorithms::next_node(p); } + //! @copydoc ::boost::intrusive::bstree_algorithms::prev_node(const node_ptr&) + static node_ptr prev_node(const node_ptr & node); - //! Requires: p is a node from the tree except the leftmost node. - //! - //! Effects: Returns the previous node of the tree. - //! - //! Complexity: Average constant time. - //! - //! Throws: Nothing. - static node_ptr prev_node(const node_ptr & p) - { return tree_algorithms::prev_node(p); } + //! @copydoc ::boost::intrusive::bstree_algorithms::init(const node_ptr&) + static void init(const node_ptr & node); + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! Requires: node must not be part of any tree. - //! - //! Effects: After the function unique(node) == true. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Nodes: If node is inserted in a tree, this function corrupts the tree. - static void init(const node_ptr & node) - { tree_algorithms::init(node); } - - //! Requires: node must not be part of any tree. - //! - //! Effects: Initializes the header to represent an empty tree. - //! unique(header) == true. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Nodes: If node is inserted in a tree, this function corrupts the tree. + //! @copydoc ::boost::intrusive::bstree_algorithms::init_header(const node_ptr&) static void init_header(const node_ptr & header) { - tree_algorithms::init_header(header); + bstree_algorithms::init_header(header); NodeTraits::set_color(header, NodeTraits::red()); } - //! Requires: header must be the header of a tree, z a node - //! of that tree and z != header. - //! - //! Effects: Erases node "z" from the tree with header "header". - //! - //! Complexity: Amortized constant time. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree_algorithms::erase(const node_ptr&,const node_ptr&) static node_ptr erase(const node_ptr & header, const node_ptr & z) { - typename tree_algorithms::data_for_rebalance info; - tree_algorithms::erase(header, z, rbtree_erase_fixup(), info); - node_ptr x = info.x; - node_ptr x_parent = info.x_parent; + typename bstree_algorithms::data_for_rebalance info; + bstree_algorithms::erase(header, z, rbtree_erase_fixup(), info); //Rebalance rbtree if(NodeTraits::get_color(z) != NodeTraits::red()){ - rebalance_after_erasure(header, x, x_parent); + rebalance_after_erasure(header, info.x, info.x_parent); } return z; } - //! Requires: "cloner" must be a function - //! object taking a node_ptr and returning a new cloned node of it. "disposer" must - //! take a node_ptr and shouldn't throw. - //! - //! Effects: First empties target tree calling - //! void disposer::operator()(const node_ptr &) for every node of the tree - //! except the header. - //! - //! Then, duplicates the entire tree pointed by "source_header" cloning each - //! source node with node_ptr Cloner::operator()(const node_ptr &) to obtain - //! the nodes of the target tree. If "cloner" throws, the cloned target nodes - //! are disposed using void disposer(const node_ptr &). - //! - //! Complexity: Linear to the number of element of the source tree plus the. - //! number of elements of tree target tree when calling this function. - //! - //! Throws: If cloner functor throws. If this happens target nodes are disposed. + //! @copydoc ::boost::intrusive::bstree_algorithms::clone(const const_node_ptr&,const node_ptr&,Cloner,Disposer) template static void clone (const const_node_ptr & source_header, const node_ptr & target_header, Cloner cloner, Disposer disposer) { - rbtree_node_cloner new_cloner(cloner); - tree_algorithms::clone(source_header, target_header, new_cloner, disposer); + rbtree_node_cloner new_cloner(cloner); + bstree_algorithms::clone(source_header, target_header, new_cloner, disposer); } - //! Requires: "disposer" must be an object function - //! taking a node_ptr parameter and shouldn't throw. - //! - //! Effects: Empties the target tree calling - //! void disposer::operator()(const node_ptr &) for every node of the tree - //! except the header. - //! - //! Complexity: Linear to the number of element of the source tree plus the. - //! number of elements of tree target tree when calling this function. - //! - //! Throws: If cloner functor throws. If this happens target nodes are disposed. + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::bstree_algorithms::clear_and_dispose(const node_ptr&,Disposer) template - static void clear_and_dispose(const node_ptr & header, Disposer disposer) - { tree_algorithms::clear_and_dispose(header, disposer); } + static void clear_and_dispose(const node_ptr & header, Disposer disposer); - //! 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 an node_ptr to the first element that is - //! not less than "key" according to "comp" or "header" if that element does - //! not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. + //! @copydoc ::boost::intrusive::bstree_algorithms::lower_bound(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) template static node_ptr lower_bound - (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) - { return tree_algorithms::lower_bound(header, key, comp); } + (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp); - //! 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 an node_ptr to the first element that is greater - //! than "key" according to "comp" or "header" if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. + //! @copydoc ::boost::intrusive::bstree_algorithms::upper_bound(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) template static node_ptr upper_bound - (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) - { return tree_algorithms::upper_bound(header, key, comp); } + (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp); - //! 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 an node_ptr to the element that is equivalent to - //! "key" according to "comp" or "header" if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. + //! @copydoc ::boost::intrusive::bstree_algorithms::find(const const_node_ptr&, const KeyType&,KeyNodePtrCompare) template static node_ptr find - (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) - { return tree_algorithms::find(header, key, comp); } + (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp); - //! 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 an a pair of node_ptr delimiting a range containing - //! all elements that are equivalent to "key" according to "comp" or an - //! empty range that indicates the position where those elements would be - //! if they there are no equivalent elements. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. + //! @copydoc ::boost::intrusive::bstree_algorithms::equal_range(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) template static std::pair equal_range - (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) - { return tree_algorithms::equal_range(header, key, comp); } + (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp); - //! 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. - //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If - //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise - //! - //! second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_key and upper_key. + //! @copydoc ::boost::intrusive::bstree_algorithms::bounded_range(const const_node_ptr&,const KeyType&,const KeyType&,KeyNodePtrCompare,bool,bool) template static std::pair bounded_range (const const_node_ptr & header, const KeyType &lower_key, const KeyType &upper_key, KeyNodePtrCompare comp - , bool left_closed, bool right_closed) - { return tree_algorithms::bounded_range(header, lower_key, upper_key, comp, left_closed, right_closed); } + , bool left_closed, bool right_closed); - //! Requires: "h" must be the header node of a tree. - //! NodePtrCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. NodePtrCompare compares two node_ptrs. - //! - //! Effects: Inserts new_node into the tree before the upper bound - //! according to "comp". - //! - //! Complexity: Average complexity for insert element is at - //! most logarithmic. - //! - //! Throws: If "comp" throws. + //! @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) template static node_ptr insert_equal_upper_bound (const node_ptr & h, const node_ptr & new_node, NodePtrCompare comp) { - tree_algorithms::insert_equal_upper_bound(h, new_node, comp); + bstree_algorithms::insert_equal_upper_bound(h, new_node, comp); rebalance_after_insertion(h, new_node); return new_node; } - //! Requires: "h" must be the header node of a tree. - //! NodePtrCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. NodePtrCompare compares two node_ptrs. - //! - //! Effects: Inserts new_node into the tree before the lower bound - //! according to "comp". - //! - //! Complexity: Average complexity for insert element is at - //! most logarithmic. - //! - //! Throws: If "comp" throws. + //! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal_lower_bound(const node_ptr&,const node_ptr&,NodePtrCompare) template static node_ptr insert_equal_lower_bound (const node_ptr & h, const node_ptr & new_node, NodePtrCompare comp) { - tree_algorithms::insert_equal_lower_bound(h, new_node, comp); + bstree_algorithms::insert_equal_lower_bound(h, new_node, comp); rebalance_after_insertion(h, new_node); return new_node; } - //! Requires: "header" must be the header node of a tree. - //! NodePtrCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. NodePtrCompare compares two node_ptrs. "hint" is node from - //! the "header"'s tree. - //! - //! Effects: Inserts new_node into the tree, using "hint" as a hint to - //! where it will be inserted. If "hint" is the upper_bound - //! the insertion takes constant time (two comparisons in the worst case). - //! - //! Complexity: Logarithmic in general, but it is amortized - //! constant time if new_node is inserted immediately before "hint". - //! - //! Throws: If "comp" throws. + //! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal(const node_ptr&,const node_ptr&,const node_ptr&,NodePtrCompare) template static node_ptr insert_equal (const node_ptr & header, const node_ptr & hint, const node_ptr & new_node, NodePtrCompare comp) { - tree_algorithms::insert_equal(header, hint, new_node, comp); + bstree_algorithms::insert_equal(header, hint, new_node, comp); rebalance_after_insertion(header, new_node); return new_node; } - //! Requires: "header" must be the header node of a tree. - //! "pos" must be a valid iterator or header (end) node. - //! "pos" must be an iterator pointing to the successor to "new_node" - //! once inserted according to the order of already inserted nodes. This function does not - //! check "pos" and this precondition must be guaranteed by the caller. - //! - //! Effects: Inserts new_node into the tree before "pos". - //! - //! Complexity: Constant-time. - //! - //! Throws: Nothing. - //! - //! Note: If "pos" is not the successor of the newly inserted "new_node" - //! tree invariants might be broken. + //! @copydoc ::boost::intrusive::bstree_algorithms::insert_before(const node_ptr&,const node_ptr&,const node_ptr&) static node_ptr insert_before (const node_ptr & header, const node_ptr & pos, const node_ptr & new_node) { - tree_algorithms::insert_before(header, pos, new_node); + bstree_algorithms::insert_before(header, pos, new_node); rebalance_after_insertion(header, new_node); return new_node; } - //! Requires: "header" must be the header node of a tree. - //! "new_node" must be, according to the used ordering no less than the - //! greatest inserted key. - //! - //! Effects: Inserts new_node into the tree before "pos". - //! - //! Complexity: Constant-time. - //! - //! Throws: Nothing. - //! - //! Note: If "new_node" is less than the greatest inserted key - //! tree invariants are broken. This function is slightly faster than - //! using "insert_before". + //! @copydoc ::boost::intrusive::bstree_algorithms::push_back(const node_ptr&,const node_ptr&) static void push_back(const node_ptr & header, const node_ptr & new_node) { - tree_algorithms::push_back(header, new_node); + bstree_algorithms::push_back(header, new_node); rebalance_after_insertion(header, new_node); } - //! Requires: "header" must be the header node of a tree. - //! "new_node" must be, according to the used ordering, no greater than the - //! lowest inserted key. - //! - //! Effects: Inserts new_node into the tree before "pos". - //! - //! Complexity: Constant-time. - //! - //! Throws: Nothing. - //! - //! Note: If "new_node" is greater than the lowest inserted key - //! tree invariants are broken. This function is slightly faster than - //! using "insert_before". + //! @copydoc ::boost::intrusive::bstree_algorithms::push_front(const node_ptr&,const node_ptr&) static void push_front(const node_ptr & header, const node_ptr & new_node) { - tree_algorithms::push_front(header, new_node); + bstree_algorithms::push_front(header, new_node); rebalance_after_insertion(header, new_node); } - //! 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. NodePtrCompare compares KeyType with a node_ptr. - //! - //! Effects: Checks if there is an equivalent node to "key" in the - //! tree according to "comp" and obtains the needed information to realize - //! a constant-time node insertion if there is no equivalent node. - //! - //! Returns: If there is an equivalent value - //! returns a pair containing a node_ptr to the already present node - //! and false. If there is not equivalent key can be inserted returns true - //! in the returned pair's boolean and fills "commit_data" that is meant to - //! be used with the "insert_commit" function to achieve a constant-time - //! insertion function. - //! - //! Complexity: Average complexity is at most logarithmic. - //! - //! Throws: If "comp" throws. - //! - //! Notes: This function is used to improve performance when constructing - //! a node is expensive and the user does not want to have two equivalent nodes - //! in the tree: if there is an equivalent value - //! the constructed object must be discarded. Many times, the part of the - //! node that is used to impose the order is much cheaper to construct - //! than the node and this function offers the possibility to use that part - //! to check if the insertion will be successful. - //! - //! If the check is successful, the user can construct the node and use - //! "insert_commit" to insert the node in constant-time. This gives a total - //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)). - //! - //! "commit_data" remains valid for a subsequent "insert_unique_commit" only - //! if no more objects are inserted or erased from the set. + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::bstree_algorithms::insert_unique_check(const const_node_ptr&,const KeyType&,KeyNodePtrCompare,insert_commit_data&) template static std::pair insert_unique_check (const const_node_ptr & header, const KeyType &key - ,KeyNodePtrCompare comp, insert_commit_data &commit_data) - { return tree_algorithms::insert_unique_check(header, key, comp, commit_data); } + ,KeyNodePtrCompare comp, insert_commit_data &commit_data); - //! 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. NodePtrCompare compares KeyType with a node_ptr. - //! "hint" is node from the "header"'s tree. - //! - //! Effects: Checks if there is an equivalent node to "key" in the - //! tree according to "comp" using "hint" as a hint to where it should be - //! inserted and obtains the needed information to realize - //! a constant-time node insertion if there is no equivalent node. - //! If "hint" is the upper_bound the function has constant time - //! complexity (two comparisons in the worst case). - //! - //! Returns: If there is an equivalent value - //! returns a pair containing a node_ptr to the already present node - //! and false. If there is not equivalent key can be inserted returns true - //! in the returned pair's boolean and fills "commit_data" that is meant to - //! be used with the "insert_commit" function to achieve a constant-time - //! insertion function. - //! - //! Complexity: Average complexity is at most logarithmic, but it is - //! amortized constant time if new_node should be inserted immediately before "hint". - //! - //! Throws: If "comp" throws. - //! - //! Notes: This function is used to improve performance when constructing - //! a node is expensive and the user does not want to have two equivalent nodes - //! in the tree: if there is an equivalent value - //! the constructed object must be discarded. Many times, the part of the - //! node that is used to impose the order is much cheaper to construct - //! than the node and this function offers the possibility to use that part - //! to check if the insertion will be successful. - //! - //! If the check is successful, the user can construct the node and use - //! "insert_commit" to insert the node in constant-time. This gives a total - //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)). - //! - //! "commit_data" remains valid for a subsequent "insert_unique_commit" only - //! if no more objects are inserted or erased from the set. + //! @copydoc ::boost::intrusive::bstree_algorithms::insert_unique_check(const const_node_ptr&,const node_ptr&,const KeyType&,KeyNodePtrCompare,insert_commit_data&) template static std::pair insert_unique_check (const const_node_ptr & header, const node_ptr &hint, const KeyType &key - ,KeyNodePtrCompare comp, insert_commit_data &commit_data) - { return tree_algorithms::insert_unique_check(header, hint, key, comp, commit_data); } + ,KeyNodePtrCompare comp, insert_commit_data &commit_data); + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! Requires: "header" must be the header node of a tree. - //! "commit_data" must have been obtained from a previous call to - //! "insert_unique_check". No objects should have been inserted or erased - //! from the set between the "insert_unique_check" that filled "commit_data" - //! and the call to "insert_commit". - //! - //! - //! Effects: Inserts new_node in the set using the information obtained - //! from the "commit_data" that a previous "insert_check" filled. - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Notes: This function has only sense if a "insert_unique_check" has been - //! previously executed to fill "commit_data". No value should be inserted or - //! erased between the "insert_check" and "insert_commit" calls. + //! @copydoc ::boost::intrusive::bstree_algorithms::insert_unique_commit(const node_ptr&,const node_ptr&,const insert_commit_data&) static void insert_unique_commit (const node_ptr & header, const node_ptr & new_value, const insert_commit_data &commit_data) { - tree_algorithms::insert_unique_commit(header, new_value, commit_data); + bstree_algorithms::insert_unique_commit(header, new_value, commit_data); rebalance_after_insertion(header, new_value); } - //! Requires: "n" must be a node inserted in a tree. - //! - //! Effects: Returns a pointer to the header node of the tree. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - static node_ptr get_header(const node_ptr & n) - { return tree_algorithms::get_header(n); } - - /// @cond - private: - - //! Requires: p is a node of a tree. - //! - //! Effects: Returns true if p is the header of the tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree_algorithms::is_header static bool is_header(const const_node_ptr & p) { return NodeTraits::get_color(p) == NodeTraits::red() && - tree_algorithms::is_header(p); - //return NodeTraits::get_color(p) == NodeTraits::red() && - // NodeTraits::get_parent(NodeTraits::get_parent(p)) == p; + bstree_algorithms::is_header(p); } + /// @cond + private: + 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())){ @@ -814,7 +418,7 @@ class rbtree_algorithms if(NodeTraits::get_color(w) == NodeTraits::red()){ NodeTraits::set_color(w, NodeTraits::black()); NodeTraits::set_color(x_parent, NodeTraits::red()); - tree_algorithms::rotate_left(x_parent, header); + bstree_algorithms::rotate_left(x_parent, header); w = NodeTraits::get_right(x_parent); } if((!NodeTraits::get_left(w) || NodeTraits::get_color(NodeTraits::get_left(w)) == NodeTraits::black()) && @@ -827,14 +431,14 @@ class rbtree_algorithms if(!NodeTraits::get_right(w) || NodeTraits::get_color(NodeTraits::get_right(w)) == NodeTraits::black()){ NodeTraits::set_color(NodeTraits::get_left(w), NodeTraits::black()); NodeTraits::set_color(w, NodeTraits::red()); - tree_algorithms::rotate_right(w, header); + bstree_algorithms::rotate_right(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()); - tree_algorithms::rotate_left(x_parent, header); + bstree_algorithms::rotate_left(x_parent, header); break; } } @@ -844,7 +448,7 @@ class rbtree_algorithms if(NodeTraits::get_color(w) == NodeTraits::red()){ NodeTraits::set_color(w, NodeTraits::black()); NodeTraits::set_color(x_parent, NodeTraits::red()); - tree_algorithms::rotate_right(x_parent, header); + bstree_algorithms::rotate_right(x_parent, header); w = NodeTraits::get_left(x_parent); } if((!NodeTraits::get_right(w) || NodeTraits::get_color(NodeTraits::get_right(w)) == NodeTraits::black()) && @@ -857,14 +461,14 @@ class rbtree_algorithms if(!NodeTraits::get_left(w) || NodeTraits::get_color(NodeTraits::get_left(w)) == NodeTraits::black()){ NodeTraits::set_color(NodeTraits::get_right(w), NodeTraits::black()); NodeTraits::set_color(w, NodeTraits::red()); - tree_algorithms::rotate_left(w, header); + bstree_algorithms::rotate_left(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()); - tree_algorithms::rotate_right(x_parent, header); + bstree_algorithms::rotate_right(x_parent, header); break; } } @@ -873,14 +477,13 @@ class rbtree_algorithms NodeTraits::set_color(x, NodeTraits::black()); } - 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()){ node_ptr p_parent(NodeTraits::get_parent(p)); node_ptr p_parent_parent(NodeTraits::get_parent(p_parent)); - if(tree_algorithms::is_left_child(p_parent)){ + if(bstree_algorithms::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()); @@ -889,15 +492,15 @@ class rbtree_algorithms p = p_parent_parent; } else { - if(!tree_algorithms::is_left_child(p)){ + if(!bstree_algorithms::is_left_child(p)){ p = p_parent; - tree_algorithms::rotate_left(p, header); + bstree_algorithms::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()); - tree_algorithms::rotate_right(new_p_parent_parent, header); + bstree_algorithms::rotate_right(new_p_parent_parent, header); } } else{ @@ -909,15 +512,15 @@ class rbtree_algorithms p = p_parent_parent; } else{ - if(tree_algorithms::is_left_child(p)){ + if(bstree_algorithms::is_left_child(p)){ p = p_parent; - tree_algorithms::rotate_right(p, header); + bstree_algorithms::rotate_right(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()); - tree_algorithms::rotate_left(new_p_parent_parent, header); + bstree_algorithms::rotate_left(new_p_parent_parent, header); } } } @@ -926,6 +529,16 @@ class rbtree_algorithms /// @endcond }; +/// @cond + +template +struct get_algo +{ + typedef rbtree_algorithms type; +}; + +/// @endcond + } //namespace intrusive } //namespace boost diff --git a/include/boost/intrusive/set.hpp b/include/boost/intrusive/set.hpp index f753a2c..72742e5 100644 --- a/include/boost/intrusive/set.hpp +++ b/include/boost/intrusive/set.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 @@ -37,12 +37,15 @@ namespace intrusive { #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class set_impl +#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + : public bstree_impl +#endif { /// @cond - typedef rbtree_impl tree_type; + typedef bstree_impl tree_type; BOOST_MOVABLE_BUT_NOT_COPYABLE(set_impl) typedef tree_type implementation_defined; @@ -70,1189 +73,338 @@ class set_impl typedef typename implementation_defined::const_node_ptr const_node_ptr; typedef typename implementation_defined::node_algorithms node_algorithms; - static const bool constant_time_size = Config::constant_time_size; - //static const bool stateful_value_traits = detail::is_stateful_value_traits::value; - - /// @cond - private: - tree_type tree_; - - protected: - node &prot_header_node(){ return tree_.prot_header_node(); } - node const &prot_header_node() const{ return tree_.prot_header_node(); } - void prot_set_size(size_type s){ tree_.prot_set_size(s); } - value_compare &prot_comp(){ return tree_.prot_comp(); } - - /// @endcond + static const bool constant_time_size = tree_type::constant_time_size; public: - //! Effects: Constructs an empty set. - //! - //! Complexity: Constant. - //! - //! Throws: If value_traits::node_traits::node - //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) - //! or the copy constructor of the value_compare object throws. + //! @copydoc ::boost::intrusive::rbtree::rbtree(const value_compare &,const value_traits &) explicit set_impl( const value_compare &cmp = value_compare() , const value_traits &v_traits = value_traits()) - : tree_(cmp, v_traits) + : tree_type(cmp, v_traits) {} - //! Requires: Dereferencing iterator must yield an lvalue of type value_type. - //! cmp must be a comparison function that induces a strict weak ordering. - //! - //! Effects: Constructs an empty set and inserts elements from - //! [b, e). - //! - //! Complexity: Linear in N if [b, e) is already sorted using - //! comp and otherwise N * log N, where N is std::distance(last, first). - //! - //! Throws: If value_traits::node_traits::node - //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) - //! or the copy constructor/operator() of the value_compare object throws. + //! @copydoc ::boost::intrusive::rbtree::rbtree(bool,Iterator,Iterator,const value_compare &,const value_traits &) template set_impl( Iterator b, Iterator e , const value_compare &cmp = value_compare() , const value_traits &v_traits = value_traits()) - : tree_(true, b, e, cmp, v_traits) + : tree_type(true, b, e, cmp, v_traits) {} - //! Effects: to-do - //! + //! @copydoc ::boost::intrusive::rbtree::rbtree(rbtree &&) set_impl(BOOST_RV_REF(set_impl) x) - : tree_(::boost::move(x.tree_)) + : tree_type(::boost::move(static_cast(x))) {} - //! Effects: to-do - //! + //! @copydoc ::boost::intrusive::rbtree::operator=(rbtree &&) set_impl& operator=(BOOST_RV_REF(set_impl) x) - { tree_ = ::boost::move(x.tree_); return *this; } + { return static_cast(tree_type::operator=(::boost::move(static_cast(x)))); } - //! Effects: Detaches all elements from this. The objects in the set - //! are not deleted (i.e. no destructors are called). - //! - //! Complexity: Linear to the number of elements on the container. - //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. - //! - //! Throws: Nothing. - ~set_impl() - {} + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::rbtree::~rbtree() + ~set_impl(); - //! Effects: Returns an iterator pointing to the beginning of the set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator begin() - { return tree_.begin(); } + //! @copydoc ::boost::intrusive::rbtree::begin() + iterator begin(); - //! Effects: Returns a const_iterator pointing to the beginning of the set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator begin() const - { return tree_.begin(); } + //! @copydoc ::boost::intrusive::rbtree::begin()const + const_iterator begin() const; - //! Effects: Returns a const_iterator pointing to the beginning of the set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator cbegin() const - { return tree_.cbegin(); } + //! @copydoc ::boost::intrusive::rbtree::cbegin()const + const_iterator cbegin() const; - //! Effects: Returns an iterator pointing to the end of the set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator end() - { return tree_.end(); } + //! @copydoc ::boost::intrusive::rbtree::end() + iterator end(); - //! Effects: Returns a const_iterator pointing to the end of the set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator end() const - { return tree_.end(); } + //! @copydoc ::boost::intrusive::rbtree::end()const + const_iterator end() const; - //! Effects: Returns a const_iterator pointing to the end of the set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator cend() const - { return tree_.cend(); } + //! @copydoc ::boost::intrusive::rbtree::cend()const + const_iterator cend() const; - //! Effects: Returns a reverse_iterator pointing to the beginning of the - //! reversed set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - reverse_iterator rbegin() - { return tree_.rbegin(); } + //! @copydoc ::boost::intrusive::rbtree::rbegin() + reverse_iterator rbegin(); - //! Effects: Returns a const_reverse_iterator pointing to the beginning - //! of the reversed set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator rbegin() const - { return tree_.rbegin(); } + //! @copydoc ::boost::intrusive::rbtree::rbegin()const + const_reverse_iterator rbegin() const; - //! Effects: Returns a const_reverse_iterator pointing to the beginning - //! of the reversed set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator crbegin() const - { return tree_.crbegin(); } + //! @copydoc ::boost::intrusive::rbtree::crbegin()const + const_reverse_iterator crbegin() const; - //! Effects: Returns a reverse_iterator pointing to the end - //! of the reversed set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - reverse_iterator rend() - { return tree_.rend(); } + //! @copydoc ::boost::intrusive::rbtree::rend() + reverse_iterator rend(); - //! Effects: Returns a const_reverse_iterator pointing to the end - //! of the reversed set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator rend() const - { return tree_.rend(); } + //! @copydoc ::boost::intrusive::rbtree::rend()const + const_reverse_iterator rend() const; - //! Effects: Returns a const_reverse_iterator pointing to the end - //! of the reversed set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator crend() const - { return tree_.crend(); } + //! @copydoc ::boost::intrusive::rbtree::crend()const + const_reverse_iterator crend() const; - //! Precondition: end_iterator must be a valid end iterator - //! of set. - //! - //! Effects: Returns a reference to the set associated to the end iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - static set_impl &container_from_end_iterator(iterator end_iterator) - { - return *detail::parent_from_member - ( &tree_type::container_from_end_iterator(end_iterator) - , &set_impl::tree_); - } + //! @copydoc ::boost::intrusive::rbtree::container_from_end_iterator(iterator) + static set_impl &container_from_end_iterator(iterator end_iterator); - //! Precondition: end_iterator must be a valid end const_iterator - //! of set. - //! - //! Effects: Returns a const reference to the set associated to the end iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - static const set_impl &container_from_end_iterator(const_iterator end_iterator) - { - return *detail::parent_from_member - ( &tree_type::container_from_end_iterator(end_iterator) - , &set_impl::tree_); - } + //! @copydoc ::boost::intrusive::rbtree::container_from_end_iterator(const_iterator) + static const set_impl &container_from_end_iterator(const_iterator end_iterator); - //! Precondition: it must be a valid iterator of set. - //! - //! Effects: Returns a reference to the set associated to the iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Logarithmic. - static set_impl &container_from_iterator(iterator it) - { - return *detail::parent_from_member - ( &tree_type::container_from_iterator(it) - , &set_impl::tree_); - } + //! @copydoc ::boost::intrusive::rbtree::container_from_iterator(iterator) + static set_impl &container_from_iterator(iterator it); - //! Precondition: it must be a valid const_iterator of set. - //! - //! Effects: Returns a const reference to the set associated to the iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Logarithmic. - static const set_impl &container_from_iterator(const_iterator it) - { - return *detail::parent_from_member - ( &tree_type::container_from_iterator(it) - , &set_impl::tree_); - } + //! @copydoc ::boost::intrusive::rbtree::container_from_iterator(const_iterator) + static const set_impl &container_from_iterator(const_iterator it); - //! Effects: Returns the key_compare object used by the set. - //! - //! Complexity: Constant. - //! - //! Throws: If key_compare copy-constructor throws. - key_compare key_comp() const - { return tree_.value_comp(); } + //! @copydoc ::boost::intrusive::rbtree::key_comp()const + key_compare key_comp() const; - //! Effects: Returns the value_compare object used by the set. - //! - //! Complexity: Constant. - //! - //! Throws: If value_compare copy-constructor throws. - value_compare value_comp() const - { return tree_.value_comp(); } + //! @copydoc ::boost::intrusive::rbtree::value_comp()const + value_compare value_comp() const; - //! Effects: Returns true if the container is empty. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - bool empty() const - { return tree_.empty(); } + //! @copydoc ::boost::intrusive::rbtree::empty()const + bool empty() const; - //! Effects: Returns the number of elements stored in the set. - //! - //! Complexity: Linear to elements contained in *this if, - //! constant-time size option is enabled. Constant-time otherwise. - //! - //! Throws: Nothing. - size_type size() const - { return tree_.size(); } + //! @copydoc ::boost::intrusive::rbtree::size()const + size_type size() const; - //! Effects: Swaps the contents of two sets. - //! - //! Complexity: Constant. - //! - //! Throws: If the swap() call for the comparison functor - //! found using ADL throws. Strong guarantee. - void swap(set_impl& other) - { tree_.swap(other.tree_); } + //! @copydoc ::boost::intrusive::rbtree::swap + void swap(set_impl& other); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! Cloner should yield to nodes equivalent to the original nodes. - //! - //! Effects: Erases all the elements from *this - //! calling Disposer::operator()(pointer), clones all the - //! elements from src calling Cloner::operator()(const_reference ) - //! and inserts them on *this. Copies the predicate from the source container. - //! - //! If cloner throws, all cloned elements are unlinked and disposed - //! calling Disposer::operator()(pointer). - //! - //! Complexity: Linear to erased plus inserted elements. - //! - //! Throws: If cloner throws or predicate copy assignment throws. Basic guarantee. + //! @copydoc ::boost::intrusive::rbtree::clone_from template - void clone_from(const set_impl &src, Cloner cloner, Disposer disposer) - { tree_.clone_from(src.tree_, cloner, disposer); } + void clone_from(const set_impl &src, Cloner cloner, Disposer disposer); + + #endif //#ifdef BOOST_iNTRUSIVE_DOXYGEN_INVOKED - //! Requires: value must be an lvalue - //! - //! Effects: Tries to inserts value into the set. - //! - //! Returns: If the value - //! is not already present inserts it and returns a pair containing the - //! iterator to the new value and true. If there is an equivalent value - //! returns a pair containing an iterator to the already present value - //! and false. - //! - //! Complexity: Average complexity for insert element is at - //! most logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. Strong guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + //! @copydoc ::boost::intrusive::rbtree::insert_unique(reference) std::pair insert(reference value) - { return tree_.insert_unique(value); } + { return tree_type::insert_unique(value); } - //! Requires: value must be an lvalue - //! - //! Effects: Tries to to insert x into the set, using "hint" - //! as a hint to where it will be inserted. - //! - //! Returns: An iterator that points to the position where the - //! new element was inserted into the set. - //! - //! Complexity: Logarithmic in general, but it's amortized - //! constant time if t is inserted immediately before hint. - //! - //! Throws: If the internal value_compare ordering function throws. Strong guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + //! @copydoc ::boost::intrusive::rbtree::insert_unique(const_iterator,reference) iterator insert(const_iterator hint, reference value) - { return tree_.insert_unique(hint, value); } + { return tree_type::insert_unique(hint, value); } - //! Requires: key_value_comp must be a comparison function that induces - //! the same strict weak ordering as value_compare. The difference is that - //! key_value_comp compares an arbitrary key with the contained values. - //! - //! Effects: Checks if a value can be inserted in the set, using - //! a user provided key instead of the value itself. - //! - //! Returns: If there is an equivalent value - //! returns a pair containing an iterator to the already present value - //! and false. If the value can be inserted returns true in the returned - //! pair boolean and fills "commit_data" that is meant to be used with - //! the "insert_commit" function. - //! - //! Complexity: Average complexity is at most logarithmic. - //! - //! Throws: If the key_value_comp ordering function throws. Strong guarantee. - //! - //! Notes: This function is used to improve performance when constructing - //! a value_type is expensive: if there is an equivalent value - //! the constructed object must be discarded. Many times, the part of the - //! node that is used to impose the order is much cheaper to construct - //! than the value_type and this function offers the possibility to use that - //! part to check if the insertion will be successful. - //! - //! If the check is successful, the user can construct the value_type and use - //! "insert_commit" to insert the object in constant-time. This gives a total - //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)). - //! - //! "commit_data" remains valid for a subsequent "insert_commit" only if no more - //! objects are inserted or erased from the set. + //! @copydoc ::boost::intrusive::rbtree::insert_unique_check(const KeyType&,KeyValueCompare,insert_commit_data&) template std::pair insert_check (const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data) - { return tree_.insert_unique_check(key, key_value_comp, commit_data); } + { return tree_type::insert_unique_check(key, key_value_comp, commit_data); } - //! Requires: key_value_comp must be a comparison function that induces - //! the same strict weak ordering as value_compare. The difference is that - //! key_value_comp compares an arbitrary key with the contained values. - //! - //! Effects: Checks if a value can be inserted in the set, using - //! a user provided key instead of the value itself, using "hint" - //! as a hint to where it will be inserted. - //! - //! Returns: If there is an equivalent value - //! returns a pair containing an iterator to the already present value - //! and false. If the value can be inserted returns true in the returned - //! pair boolean and fills "commit_data" that is meant to be used with - //! the "insert_commit" function. - //! - //! Complexity: Logarithmic in general, but it's amortized - //! constant time if t is inserted immediately before hint. - //! - //! Throws: If the key_value_comp ordering function throws. Strong guarantee. - //! - //! Notes: This function is used to improve performance when constructing - //! a value_type is expensive: if there is an equivalent value - //! the constructed object must be discarded. Many times, the part of the - //! constructing that is used to impose the order is much cheaper to construct - //! than the value_type and this function offers the possibility to use that key - //! to check if the insertion will be successful. - //! - //! If the check is successful, the user can construct the value_type and use - //! "insert_commit" to insert the object in constant-time. This can give a total - //! constant-time complexity to the insertion: check(O(1)) + commit(O(1)). - //! - //! "commit_data" remains valid for a subsequent "insert_commit" only if no more - //! objects are inserted or erased from the set. + //! @copydoc ::boost::intrusive::rbtree::insert_unique_check(const_iterator,const KeyType&,KeyValueCompare,insert_commit_data&) template std::pair insert_check (const_iterator hint, const KeyType &key ,KeyValueCompare key_value_comp, insert_commit_data &commit_data) - { return tree_.insert_unique_check(hint, key, key_value_comp, commit_data); } + { return tree_type::insert_unique_check(hint, key, key_value_comp, commit_data); } - //! Requires: value must be an lvalue of type value_type. commit_data - //! must have been obtained from a previous call to "insert_check". - //! No objects should have been inserted or erased from the set between - //! the "insert_check" that filled "commit_data" and the call to "insert_commit". - //! - //! Effects: Inserts the value in the set using the information obtained - //! from the "commit_data" that a previous "insert_check" filled. - //! - //! Returns: An iterator to the newly inserted object. - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Notes: This function has only sense if a "insert_check" has been - //! previously executed to fill "commit_data". No value should be inserted or - //! erased between the "insert_check" and "insert_commit" calls. - iterator insert_commit(reference value, const insert_commit_data &commit_data) - { return tree_.insert_unique_commit(value, commit_data); } - - //! Requires: Dereferencing iterator must yield an lvalue - //! of type value_type. - //! - //! Effects: Inserts a range into the set. - //! - //! Complexity: Insert range is in general O(N * log(N)), where N is the - //! size of the range. However, it is linear in N if the range is already sorted - //! by value_comp(). - //! - //! Throws: If the internal value_compare ordering function throws. Basic guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + //! @copydoc ::boost::intrusive::rbtree::insert_unique(Iterator,Iterator) template void insert(Iterator b, Iterator e) - { tree_.insert_unique(b, e); } + { tree_type::insert_unique(b, e); } - //! Requires: value must be an lvalue, "pos" must be - //! a valid iterator (or end) and must be the succesor of value - //! once inserted according to the predicate. "value" must not be equal to any - //! inserted key according to the predicate. - //! - //! Effects: Inserts x into the tree before "pos". - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Note: This function does not check preconditions so if "pos" is not - //! the successor of "value" or "value" is not unique tree ordering and uniqueness - //! invariants will be broken respectively. - //! This is a low-level function to be used only for performance reasons - //! by advanced users. - iterator insert_before(const_iterator pos, reference value) - { return tree_.insert_before(pos, value); } + //! @copydoc ::boost::intrusive::rbtree::insert_unique_commit + iterator insert_commit(reference value, const insert_commit_data &commit_data) + { return tree_type::insert_unique_commit(value, commit_data); } - //! Requires: value must be an lvalue, and it must be greater than - //! any inserted key according to the predicate. - //! - //! Effects: Inserts x into the tree in the last position. - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Note: This function does not check preconditions so if value is - //! less than or equal to the greatest inserted key tree ordering invariant will be broken. - //! This function is slightly more efficient than using "insert_before". - //! This is a low-level function to be used only for performance reasons - //! by advanced users. - void push_back(reference value) - { tree_.push_back(value); } + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::rbtree::insert_before + iterator insert_before(const_iterator pos, reference value); - //! Requires: value must be an lvalue, and it must be less - //! than any inserted key according to the predicate. - //! - //! Effects: Inserts x into the tree in the first position. - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Note: This function does not check preconditions so if value is - //! greater than or equal to the the mimum inserted key tree ordering or uniqueness - //! invariants will be broken. - //! This function is slightly more efficient than using "insert_before". - //! This is a low-level function to be used only for performance reasons - //! by advanced users. - void push_front(reference value) - { tree_.push_front(value); } + //! @copydoc ::boost::intrusive::rbtree::push_back + void push_back(reference value); - //! Effects: Erases the element pointed to by pos. - //! - //! Complexity: Average complexity is constant time. - //! - //! Returns: An iterator to the element after the erased element. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - iterator erase(const_iterator i) - { return tree_.erase(i); } + //! @copydoc ::boost::intrusive::rbtree::push_front + void push_front(reference value); - //! Effects: Erases the range pointed to by b end e. - //! - //! Complexity: Average complexity for erase range is at most - //! O(log(size() + N)), where N is the number of elements in the range. - //! - //! Returns: An iterator to the element after the erased elements. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - iterator erase(const_iterator b, const_iterator e) - { return tree_.erase(b, e); } + //! @copydoc ::boost::intrusive::rbtree::erase(const_iterator) + iterator erase(const_iterator i); - //! Effects: Erases all the elements with the given value. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: O(log(size()) + this->count(value)). - //! - //! Throws: If the internal value_compare ordering function throws. Basic guarantee. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - size_type erase(const_reference value) - { return tree_.erase(value); } + //! @copydoc ::boost::intrusive::rbtree::erase(const_iterator,const_iterator) + iterator erase(const_iterator b, const_iterator e); - //! Effects: Erases all the elements that compare equal with - //! the given key and the given comparison functor. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: O(log(size() + this->count(key, comp)). - //! - //! Throws: If the comp ordering function throws. Basic guarantee. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. + //! @copydoc ::boost::intrusive::rbtree::erase(const_reference) + size_type erase(const_reference value); + + //! @copydoc ::boost::intrusive::rbtree::erase(const KeyType&,KeyValueCompare) template - size_type erase(const KeyType& key, KeyValueCompare comp - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) - { return tree_.erase(key, comp); } + size_type erase(const KeyType& key, KeyValueCompare comp); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases the element pointed to by pos. - //! Disposer::operator()(pointer) is called for the removed element. - //! - //! Complexity: Average complexity for erase element is constant time. - //! - //! Returns: An iterator to the element after the erased element. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::rbtree::erase_and_dispose(const_iterator,Disposer) template - iterator erase_and_dispose(const_iterator i, Disposer disposer) - { return tree_.erase_and_dispose(i, disposer); } + iterator erase_and_dispose(const_iterator i, Disposer disposer); - #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + //! @copydoc ::boost::intrusive::rbtree::erase_and_dispose(const_iterator,const_iterator,Disposer) template - iterator erase_and_dispose(iterator i, Disposer disposer) - { return this->erase_and_dispose(const_iterator(i), disposer); } - #endif + iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases the range pointed to by b end e. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Complexity: Average complexity for erase range is at most - //! O(log(size() + N)), where N is the number of elements in the range. - //! - //! Returns: An iterator to the element after the erased elements. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::rbtree::erase_and_dispose(const_reference, Disposer) template - iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer) - { return tree_.erase_and_dispose(b, e, disposer); } + size_type erase_and_dispose(const_reference value, Disposer disposer); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements with the given value. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Throws: If the internal value_compare ordering function throws. - //! - //! Complexity: O(log(size() + this->count(value)). Basic guarantee. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - template - size_type erase_and_dispose(const_reference value, Disposer disposer) - { return tree_.erase_and_dispose(value, disposer); } - - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements with the given key. - //! according to the comparison functor "comp". - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: O(log(size() + this->count(key, comp)). - //! - //! Throws: If comp ordering function throws. Basic guarantee. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::rbtree::erase_and_dispose(const KeyType&,KeyValueCompare,Disposer) template - size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) - { return tree_.erase_and_dispose(key, comp, disposer); } + size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer); - //! Effects: Erases all the elements of the container. - //! - //! Complexity: Linear to the number of elements on the container. - //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - void clear() - { return tree_.clear(); } + //! @copydoc ::boost::intrusive::rbtree::clear + void clear(); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements of the container. - //! - //! Complexity: Linear to the number of elements on the container. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. + //! @copydoc ::boost::intrusive::rbtree::clear_and_dispose template - void clear_and_dispose(Disposer disposer) - { return tree_.clear_and_dispose(disposer); } + void clear_and_dispose(Disposer disposer); - //! Effects: Returns the number of contained elements with the given key - //! - //! Complexity: Logarithmic to the number of elements contained plus lineal - //! to number of objects with the given key. - //! - //! Throws: If the internal value_compare ordering function throws. - size_type count(const_reference value) const - { return tree_.find(value) != end(); } + //! @copydoc ::boost::intrusive::rbtree::count(const_reference)const + size_type count(const_reference value) const; - //! Effects: Returns the number of contained elements with the same key - //! compared with the given comparison functor. - //! - //! Complexity: Logarithmic to the number of elements contained plus lineal - //! to number of objects with the given key. - //! - //! Throws: If comp ordering function throws. + //! @copydoc ::boost::intrusive::rbtree::count(const KeyType&,KeyValueCompare)const template - size_type count(const KeyType& key, KeyValueCompare comp) const - { return tree_.find(key, comp) != end(); } - - //! Effects: Returns an iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - iterator lower_bound(const_reference value) - { return tree_.lower_bound(value); } - - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Returns an iterator to the first element whose - //! key according to the comparison functor is not less than k or - //! end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + size_type count(const KeyType& key, KeyValueCompare comp) const; + + //! @copydoc ::boost::intrusive::rbtree::lower_bound(const_reference) + iterator lower_bound(const_reference value); + + //! @copydoc ::boost::intrusive::rbtree::lower_bound(const KeyType&,KeyValueCompare) template - iterator lower_bound(const KeyType& key, KeyValueCompare comp) - { return tree_.lower_bound(key, comp); } + iterator lower_bound(const KeyType& key, KeyValueCompare comp); - //! Effects: Returns a const iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - const_iterator lower_bound(const_reference value) const - { return tree_.lower_bound(value); } + //! @copydoc ::boost::intrusive::rbtree::lower_bound(const_reference)const + const_iterator lower_bound(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Returns a const_iterator to the first element whose - //! key according to the comparison functor is not less than k or - //! end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::rbtree::lower_bound(const KeyType&,KeyValueCompare)const template - const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const - { return tree_.lower_bound(key, comp); } + const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Returns an iterator to the first element whose - //! key is greater than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - iterator upper_bound(const_reference value) - { return tree_.upper_bound(value); } + //! @copydoc ::boost::intrusive::rbtree::upper_bound(const_reference) + iterator upper_bound(const_reference value); - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Returns an iterator to the first element whose - //! key according to the comparison functor is greater than key or - //! end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::rbtree::upper_bound(const KeyType&,KeyValueCompare) template - iterator upper_bound(const KeyType& key, KeyValueCompare comp) - { return tree_.upper_bound(key, comp); } + iterator upper_bound(const KeyType& key, KeyValueCompare comp); - //! Effects: Returns an iterator to the first element whose - //! key is greater than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - const_iterator upper_bound(const_reference value) const - { return tree_.upper_bound(value); } + //! @copydoc ::boost::intrusive::rbtree::upper_bound(const_reference)const + const_iterator upper_bound(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Returns a const_iterator to the first element whose - //! key according to the comparison functor is greater than key or - //! end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::rbtree::upper_bound(const KeyType&,KeyValueCompare)const template - const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const - { return tree_.upper_bound(key, comp); } + const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Finds an iterator to the first element whose value is - //! "value" or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - iterator find(const_reference value) - { return tree_.find(value); } + //! @copydoc ::boost::intrusive::rbtree::find(const_reference) + iterator find(const_reference value); - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Finds an iterator to the first element whose key is - //! "key" according to the comparison functor or end() if that element - //! does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::rbtree::find(const KeyType&,KeyValueCompare) template - iterator find(const KeyType& key, KeyValueCompare comp) - { return tree_.find(key, comp); } + iterator find(const KeyType& key, KeyValueCompare comp); - //! Effects: Finds a const_iterator to the first element whose value is - //! "value" or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - const_iterator find(const_reference value) const - { return tree_.find(value); } + //! @copydoc ::boost::intrusive::rbtree::find(const_reference)const + const_iterator find(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Finds a const_iterator to the first element whose key is - //! "key" according to the comparison functor or end() if that element - //! does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::rbtree::find(const KeyType&,KeyValueCompare)const template - const_iterator find(const KeyType& key, KeyValueCompare comp) const - { return tree_.find(key, comp); } + const_iterator find(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - std::pair equal_range(const_reference value) - { return tree_.equal_range(value); } + //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference) + std::pair equal_range(const_reference value); - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Finds a range containing all elements whose key is k - //! according to the comparison functor or an empty range - //! that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare) template - std::pair equal_range(const KeyType& key, KeyValueCompare comp) - { return tree_.equal_range(key, comp); } + std::pair equal_range(const KeyType& key, KeyValueCompare comp); - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. + //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference)const std::pair - equal_range(const_reference value) const - { return tree_.equal_range(value); } + equal_range(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Finds a range containing all elements whose key is k - //! according to the comparison functor or an empty range - //! that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare)const template std::pair - equal_range(const KeyType& key, KeyValueCompare comp) const - { return tree_.equal_range(key, comp); } + equal_range(const KeyType& key, KeyValueCompare comp) const; - //! Requires: 'lower_value' must not be greater than 'upper_value'. If - //! 'lower_value' == 'upper_value', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise - //! - //! second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the predicate throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_value and upper_value. + //! @copydoc ::boost::intrusive::rbtree::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) - { return tree_.bounded_range(lower_value, upper_value, left_closed, right_closed); } + (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); - //! Requires: KeyValueCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. - //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If - //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key, comp) if left_closed, upper_bound(lower_key, comp) otherwise - //! - //! second = upper_bound(upper_key, comp) if right_closed, lower_bound(upper_key, comp) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_key and upper_key. + //! @copydoc ::boost::intrusive::rbtree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool) template std::pair bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) - { return tree_.bounded_range(lower_key, upper_key, comp, left_closed, right_closed); } + (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed); - //! Requires: 'lower_value' must not be greater than 'upper_value'. If - //! 'lower_value' == 'upper_value', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise - //! - //! second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the predicate throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_value and upper_value. + //! @copydoc ::boost::intrusive::rbtree::bounded_range(const_reference,const_reference,bool,bool)const std::pair - bounded_range(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const - { return tree_.bounded_range(lower_value, upper_value, left_closed, right_closed); } + bounded_range(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; - //! Requires: KeyValueCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. - //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If - //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key, comp) if left_closed, upper_bound(lower_key, comp) otherwise - //! - //! second = upper_bound(upper_key, comp) if right_closed, lower_bound(upper_key, comp) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_key and upper_key. + //! @copydoc ::boost::intrusive::rbtree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const template - std::pair - bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const - { return tree_.bounded_range(lower_key, upper_key, comp, left_closed, right_closed); } + std::pair bounded_range + (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; - //! Requires: value must be an lvalue and shall be in a set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid iterator i belonging to the set - //! that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This static function is available only if the value traits - //! is stateless. - static iterator s_iterator_to(reference value) - { return tree_type::s_iterator_to(value); } + //! @copydoc ::boost::intrusive::rbtree::s_iterator_to(reference) + static iterator s_iterator_to(reference value); - //! Requires: value must be an lvalue and shall be in a set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid const_iterator i belonging to the - //! set that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This static function is available only if the value traits - //! is stateless. - static const_iterator s_iterator_to(const_reference value) - { return tree_type::s_iterator_to(value); } + //! @copydoc ::boost::intrusive::rbtree::s_iterator_to(const_reference) + static const_iterator s_iterator_to(const_reference value); - //! Requires: value must be an lvalue and shall be in a set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid iterator i belonging to the set - //! that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator iterator_to(reference value) - { return tree_.iterator_to(value); } + //! @copydoc ::boost::intrusive::rbtree::iterator_to(reference) + iterator iterator_to(reference value); - //! Requires: value must be an lvalue and shall be in a set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid const_iterator i belonging to the - //! set that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator iterator_to(const_reference value) const - { return tree_.iterator_to(value); } + //! @copydoc ::boost::intrusive::rbtree::iterator_to(const_reference)const + const_iterator iterator_to(const_reference value) const; - //! Requires: value shall not be in a set/multiset. - //! - //! Effects: init_node puts the hook of a value in a well-known default - //! state. - //! - //! Throws: Nothing. - //! - //! Complexity: Constant time. - //! - //! Note: This function puts the hook in the well-known default state - //! used by auto_unlink and safe hooks. - static void init_node(reference value) - { tree_type::init_node(value); } + //! @copydoc ::boost::intrusive::rbtree::init_node(reference) + static void init_node(reference value); - //! Effects: Unlinks the leftmost node from the tree. - //! - //! Complexity: Average complexity is constant time. - //! - //! Throws: Nothing. - //! - //! Notes: This function breaks the tree and the tree can - //! only be used for more unlink_leftmost_without_rebalance calls. - //! This function is normally used to achieve a step by step - //! controlled destruction of the tree. - pointer unlink_leftmost_without_rebalance() - { return tree_.unlink_leftmost_without_rebalance(); } + //! @copydoc ::boost::intrusive::rbtree::unlink_leftmost_without_rebalance + pointer unlink_leftmost_without_rebalance(); - //! Requires: replace_this must be a valid iterator of *this - //! and with_this must not be inserted in any tree. - //! - //! Effects: Replaces replace_this in its position in the - //! tree with with_this. The tree does not need to be rebalanced. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This function will break container ordering invariants if - //! with_this is not equivalent to *replace_this according to the - //! ordering rules. This function is faster than erasing and inserting - //! the node, since no rebalancing or comparison is needed. - void replace_node(iterator replace_this, reference with_this) - { tree_.replace_node(replace_this, with_this); } + //! @copydoc ::boost::intrusive::rbtree::replace_node + void replace_node(iterator replace_this, reference with_this); - /// @cond - friend bool operator==(const set_impl &x, const set_impl &y) - { return x.tree_ == y.tree_; } - - friend bool operator<(const set_impl &x, const set_impl &y) - { return x.tree_ < y.tree_; } - /// @endcond + //! @copydoc ::boost::intrusive::rbtree::remove_node + void remove_node(reference value); + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED }; #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator!= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const set_impl &x, const set_impl &y) -#else -(const set_impl &x, const set_impl &y) -#endif -{ return !(x == y); } -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator> -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const set_impl &x, const set_impl &y) -#else -(const set_impl &x, const set_impl &y) -#endif -{ return y < x; } +bool operator!= (const set_impl &x, const set_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator<= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const set_impl &x, const set_impl &y) -#else -(const set_impl &x, const set_impl &y) -#endif -{ return !(y < x); } +bool operator>(const set_impl &x, const set_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator>= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const set_impl &x, const set_impl &y) -#else -(const set_impl &x, const set_impl &y) -#endif -{ return !(x < y); } +bool operator<=(const set_impl &x, const set_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline void swap -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(set_impl &x, set_impl &y) -#else -(set_impl &x, set_impl &y) -#endif -{ x.swap(y); } +bool operator>=(const set_impl &x, const set_impl &y); + +template +void swap(set_impl &x, set_impl &y); + +#endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Helper metafunction to define a \c set that yields to the same type when the //! same options (either explicitly or implicitly) are used. #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else -template +template #endif struct make_set { /// @cond - typedef set_impl - < typename make_rbtree_opt::type - > implementation_defined; + >::type packed_options; + + typedef typename detail::get_value_traits + ::type value_traits; + + typedef set_impl + < value_traits + , typename packed_options::compare + , typename packed_options::size_type + , packed_options::constant_time_size + > implementation_defined; /// @endcond typedef implementation_defined type; }; @@ -1308,7 +460,7 @@ class set {} set& operator=(BOOST_RV_REF(set) x) - { this->Base::operator=(::boost::move(static_cast(x))); return *this; } + { return static_cast(this->Base::operator=(::boost::move(static_cast(x)))); } static set &container_from_end_iterator(iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } @@ -1339,12 +491,15 @@ class set #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class multiset_impl +#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + : public bstree_impl +#endif { /// @cond - typedef rbtree_impl tree_type; + typedef bstree_impl tree_type; BOOST_MOVABLE_BUT_NOT_COPYABLE(multiset_impl) typedef tree_type implementation_defined; @@ -1372,1107 +527,321 @@ class multiset_impl typedef typename implementation_defined::const_node_ptr const_node_ptr; typedef typename implementation_defined::node_algorithms node_algorithms; - static const bool constant_time_size = Config::constant_time_size; - //static const bool stateful_value_traits = detail::is_stateful_value_traits::value; - - /// @cond - private: - tree_type tree_; - - protected: - node &prot_header_node(){ return tree_.prot_header_node(); } - node const &prot_header_node() const{ return tree_.prot_header_node(); } - void prot_set_size(size_type s){ tree_.prot_set_size(s); } - value_compare &prot_comp(){ return tree_.prot_comp(); } - /// @endcond + static const bool constant_time_size = tree_type::constant_time_size; public: - //! Effects: Constructs an empty multiset. - //! - //! Complexity: Constant. - //! - //! Throws: If value_traits::node_traits::node - //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) - //! or the copy constructor/operator() of the value_compare object throws. + //! @copydoc ::boost::intrusive::rbtree::rbtree(const value_compare &,const value_traits &) explicit multiset_impl( const value_compare &cmp = value_compare() , const value_traits &v_traits = value_traits()) - : tree_(cmp, v_traits) + : tree_type(cmp, v_traits) {} - //! Requires: Dereferencing iterator must yield an lvalue of type value_type. - //! cmp must be a comparison function that induces a strict weak ordering. - //! - //! Effects: Constructs an empty multiset and inserts elements from - //! [b, e). - //! - //! Complexity: Linear in N if [b, e) is already sorted using - //! comp and otherwise N * log N, where N is the distance between first and last - //! - //! Throws: If value_traits::node_traits::node - //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) - //! or the copy constructor/operator() of the value_compare object throws. + //! @copydoc ::boost::intrusive::rbtree::rbtree(bool,Iterator,Iterator,const value_compare &,const value_traits &) template multiset_impl( Iterator b, Iterator e , const value_compare &cmp = value_compare() , const value_traits &v_traits = value_traits()) - : tree_(false, b, e, cmp, v_traits) + : tree_type(false, b, e, cmp, v_traits) {} - //! Effects: to-do - //! + //! @copydoc ::boost::intrusive::rbtree::rbtree(rbtree &&) multiset_impl(BOOST_RV_REF(multiset_impl) x) - : tree_(::boost::move(x.tree_)) + : tree_type(::boost::move(static_cast(x))) {} - //! Effects: to-do - //! + //! @copydoc ::boost::intrusive::rbtree::operator=(rbtree &&) multiset_impl& operator=(BOOST_RV_REF(multiset_impl) x) - { tree_ = ::boost::move(x.tree_); return *this; } + { return static_cast(tree_type::operator=(::boost::move(static_cast(x)))); } - //! Effects: Detaches all elements from this. The objects in the set - //! are not deleted (i.e. no destructors are called). - //! - //! Complexity: Linear to the number of elements on the container. - //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. - //! - //! Throws: Nothing. - ~multiset_impl() - {} + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::rbtree::~rbtree() + ~multiset_impl(); - //! Effects: Returns an iterator pointing to the beginning of the multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator begin() - { return tree_.begin(); } + //! @copydoc ::boost::intrusive::rbtree::begin() + iterator begin(); - //! Effects: Returns a const_iterator pointing to the beginning of the multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator begin() const - { return tree_.begin(); } + //! @copydoc ::boost::intrusive::rbtree::begin()const + const_iterator begin() const; - //! Effects: Returns a const_iterator pointing to the beginning of the multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator cbegin() const - { return tree_.cbegin(); } + //! @copydoc ::boost::intrusive::rbtree::cbegin()const + const_iterator cbegin() const; - //! Effects: Returns an iterator pointing to the end of the multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator end() - { return tree_.end(); } + //! @copydoc ::boost::intrusive::rbtree::end() + iterator end(); - //! Effects: Returns a const_iterator pointing to the end of the multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator end() const - { return tree_.end(); } + //! @copydoc ::boost::intrusive::rbtree::end()const + const_iterator end() const; - //! Effects: Returns a const_iterator pointing to the end of the multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator cend() const - { return tree_.cend(); } + //! @copydoc ::boost::intrusive::rbtree::cend()const + const_iterator cend() const; - //! Effects: Returns a reverse_iterator pointing to the beginning of the - //! reversed multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - reverse_iterator rbegin() - { return tree_.rbegin(); } + //! @copydoc ::boost::intrusive::rbtree::rbegin() + reverse_iterator rbegin(); - //! Effects: Returns a const_reverse_iterator pointing to the beginning - //! of the reversed multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator rbegin() const - { return tree_.rbegin(); } + //! @copydoc ::boost::intrusive::rbtree::rbegin()const + const_reverse_iterator rbegin() const; - //! Effects: Returns a const_reverse_iterator pointing to the beginning - //! of the reversed multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator crbegin() const - { return tree_.crbegin(); } + //! @copydoc ::boost::intrusive::rbtree::crbegin()const + const_reverse_iterator crbegin() const; - //! Effects: Returns a reverse_iterator pointing to the end - //! of the reversed multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - reverse_iterator rend() - { return tree_.rend(); } + //! @copydoc ::boost::intrusive::rbtree::rend() + reverse_iterator rend(); - //! Effects: Returns a const_reverse_iterator pointing to the end - //! of the reversed multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator rend() const - { return tree_.rend(); } + //! @copydoc ::boost::intrusive::rbtree::rend()const + const_reverse_iterator rend() const; - //! Effects: Returns a const_reverse_iterator pointing to the end - //! of the reversed multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator crend() const - { return tree_.crend(); } + //! @copydoc ::boost::intrusive::rbtree::crend()const + const_reverse_iterator crend() const; - //! Precondition: end_iterator must be a valid end iterator - //! of multiset. - //! - //! Effects: Returns a const reference to the multiset associated to the end iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - static multiset_impl &container_from_end_iterator(iterator end_iterator) - { - return *detail::parent_from_member - ( &tree_type::container_from_end_iterator(end_iterator) - , &multiset_impl::tree_); - } + //! @copydoc ::boost::intrusive::rbtree::container_from_end_iterator(iterator) + static multiset_impl &container_from_end_iterator(iterator end_iterator); - //! Precondition: end_iterator must be a valid end const_iterator - //! of multiset. - //! - //! Effects: Returns a const reference to the multiset associated to the end iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - static const multiset_impl &container_from_end_iterator(const_iterator end_iterator) - { - return *detail::parent_from_member - ( &tree_type::container_from_end_iterator(end_iterator) - , &multiset_impl::tree_); - } + //! @copydoc ::boost::intrusive::rbtree::container_from_end_iterator(const_iterator) + static const multiset_impl &container_from_end_iterator(const_iterator end_iterator); - //! Precondition: it must be a valid iterator of multiset. - //! - //! Effects: Returns a const reference to the multiset associated to the iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Logarithmic. - static multiset_impl &container_from_iterator(iterator it) - { - return *detail::parent_from_member - ( &tree_type::container_from_iterator(it) - , &multiset_impl::tree_); - } + //! @copydoc ::boost::intrusive::rbtree::container_from_iterator(iterator) + static multiset_impl &container_from_iterator(iterator it); - //! Precondition: it must be a valid const_iterator of multiset. - //! - //! Effects: Returns a const reference to the multiset associated to the iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Logarithmic. - static const multiset_impl &container_from_iterator(const_iterator it) - { - return *detail::parent_from_member - ( &tree_type::container_from_iterator(it) - , &multiset_impl::tree_); - } + //! @copydoc ::boost::intrusive::rbtree::container_from_iterator(const_iterator) + static const multiset_impl &container_from_iterator(const_iterator it); - //! Effects: Returns the key_compare object used by the multiset. - //! - //! Complexity: Constant. - //! - //! Throws: If key_compare copy-constructor throws. - key_compare key_comp() const - { return tree_.value_comp(); } + //! @copydoc ::boost::intrusive::rbtree::key_comp()const + key_compare key_comp() const; - //! Effects: Returns the value_compare object used by the multiset. - //! - //! Complexity: Constant. - //! - //! Throws: If value_compare copy-constructor throws. - value_compare value_comp() const - { return tree_.value_comp(); } + //! @copydoc ::boost::intrusive::rbtree::value_comp()const + value_compare value_comp() const; - //! Effects: Returns true if the container is empty. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - bool empty() const - { return tree_.empty(); } + //! @copydoc ::boost::intrusive::rbtree::empty()const + bool empty() const; - //! Effects: Returns the number of elements stored in the multiset. - //! - //! Complexity: Linear to elements contained in *this if, - //! constant-time size option is enabled. Constant-time otherwise. - //! - //! Throws: Nothing. - size_type size() const - { return tree_.size(); } + //! @copydoc ::boost::intrusive::rbtree::size()const + size_type size() const; - //! Effects: Swaps the contents of two multisets. - //! - //! Complexity: Constant. - //! - //! Throws: If the swap() call for the comparison functor - //! found using ADL throws. Strong guarantee. - void swap(multiset_impl& other) - { tree_.swap(other.tree_); } + //! @copydoc ::boost::intrusive::rbtree::swap + void swap(multiset_impl& other); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! Cloner should yield to nodes equivalent to the original nodes. - //! - //! Effects: Erases all the elements from *this - //! calling Disposer::operator()(pointer), clones all the - //! elements from src calling Cloner::operator()(const_reference ) - //! and inserts them on *this. Copies the predicate from the source container. - //! - //! If cloner throws, all cloned elements are unlinked and disposed - //! calling Disposer::operator()(pointer). - //! - //! Complexity: Linear to erased plus inserted elements. - //! - //! Throws: If cloner throws or predicate copy assignment throws. Basic guarantee. + //! @copydoc ::boost::intrusive::rbtree::clone_from template - void clone_from(const multiset_impl &src, Cloner cloner, Disposer disposer) - { tree_.clone_from(src.tree_, cloner, disposer); } + void clone_from(const multiset_impl &src, Cloner cloner, Disposer disposer); - //! Requires: value must be an lvalue - //! - //! Effects: Inserts value into the multiset. - //! - //! Returns: An iterator that points to the position where the new - //! element was inserted. - //! - //! Complexity: Average complexity for insert element is at - //! most logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. Strong guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + #endif //#ifdef BOOST_iNTRUSIVE_DOXYGEN_INVOKED + + //! @copydoc ::boost::intrusive::rbtree::insert_equal(reference) iterator insert(reference value) - { return tree_.insert_equal(value); } + { return tree_type::insert_equal(value); } - //! Requires: value must be an lvalue - //! - //! Effects: Inserts x into the multiset, using pos as a hint to - //! where it will be inserted. - //! - //! Returns: An iterator that points to the position where the new - //! element was inserted. - //! - //! Complexity: Logarithmic in general, but it is amortized - //! constant time if t is inserted immediately before hint. - //! - //! Throws: If the internal value_compare ordering function throws. Strong guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + //! @copydoc ::boost::intrusive::rbtree::insert_equal(const_iterator,reference) iterator insert(const_iterator hint, reference value) - { return tree_.insert_equal(hint, value); } + { return tree_type::insert_equal(hint, value); } - //! Requires: Dereferencing iterator must yield an lvalue - //! of type value_type. - //! - //! Effects: Inserts a range into the multiset. - //! - //! Returns: An iterator that points to the position where the new - //! element was inserted. - //! - //! Complexity: Insert range is in general O(N * log(N)), where N is the - //! size of the range. However, it is linear in N if the range is already sorted - //! by value_comp(). - //! - //! Throws: If the internal value_compare ordering function throws. Basic guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + //! @copydoc ::boost::intrusive::rbtree::insert_equal(Iterator,Iterator) template void insert(Iterator b, Iterator e) - { tree_.insert_equal(b, e); } + { tree_type::insert_equal(b, e); } - //! Requires: value must be an lvalue, "pos" must be - //! a valid iterator (or end) and must be the succesor of value - //! once inserted according to the predicate - //! - //! Effects: Inserts x into the tree before "pos". - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Note: This function does not check preconditions so if "pos" is not - //! the successor of "value" tree ordering invariant will be broken. - //! This is a low-level function to be used only for performance reasons - //! by advanced users. - iterator insert_before(const_iterator pos, reference value) - { return tree_.insert_before(pos, value); } + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::rbtree::insert_before + iterator insert_before(const_iterator pos, reference value); - //! Requires: value must be an lvalue, and it must be no less - //! than the greatest inserted key - //! - //! Effects: Inserts x into the tree in the last position. - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Note: This function does not check preconditions so if value is - //! less than the greatest inserted key tree ordering invariant will be broken. - //! This function is slightly more efficient than using "insert_before". - //! This is a low-level function to be used only for performance reasons - //! by advanced users. - void push_back(reference value) - { tree_.push_back(value); } + //! @copydoc ::boost::intrusive::rbtree::push_back + void push_back(reference value); - //! Requires: value must be an lvalue, and it must be no greater - //! than the minimum inserted key - //! - //! Effects: Inserts x into the tree in the first position. - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Note: This function does not check preconditions so if value is - //! greater than the minimum inserted key tree ordering invariant will be broken. - //! This function is slightly more efficient than using "insert_before". - //! This is a low-level function to be used only for performance reasons - //! by advanced users. - void push_front(reference value) - { tree_.push_front(value); } + //! @copydoc ::boost::intrusive::rbtree::push_front + void push_front(reference value); - //! Effects: Erases the element pointed to by pos. - //! - //! Complexity: Average complexity is constant time. - //! - //! Returns: An iterator to the element after the erased element. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - iterator erase(const_iterator i) - { return tree_.erase(i); } + //! @copydoc ::boost::intrusive::rbtree::erase(const_iterator) + iterator erase(const_iterator i); - //! Effects: Erases the range pointed to by b end e. - //! - //! Returns: An iterator to the element after the erased elements. - //! - //! Complexity: Average complexity for erase range is at most - //! O(log(size() + N)), where N is the number of elements in the range. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - iterator erase(const_iterator b, iterator e) - { return tree_.erase(b, e); } + //! @copydoc ::boost::intrusive::rbtree::erase(const_iterator,const_iterator) + iterator erase(const_iterator b, const_iterator e); - //! Effects: Erases all the elements with the given value. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: O(log(size() + this->count(value)). - //! - //! Throws: If the internal value_compare ordering function throws. Basic guarantee. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - size_type erase(const_reference value) - { return tree_.erase(value); } + //! @copydoc ::boost::intrusive::rbtree::erase(const_reference) + size_type erase(const_reference value); - //! Effects: Erases all the elements that compare equal with - //! the given key and the given comparison functor. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: O(log(size() + this->count(key, comp)). - //! - //! Throws: If comp ordering function throws. Basic guarantee. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. + //! @copydoc ::boost::intrusive::rbtree::erase(const KeyType&,KeyValueCompare) template - size_type erase(const KeyType& key, KeyValueCompare comp - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) - { return tree_.erase(key, comp); } + size_type erase(const KeyType& key, KeyValueCompare comp); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Returns: An iterator to the element after the erased element. - //! - //! Effects: Erases the element pointed to by pos. - //! Disposer::operator()(pointer) is called for the removed element. - //! - //! Complexity: Average complexity for erase element is constant time. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::rbtree::erase_and_dispose(const_iterator,Disposer) template - iterator erase_and_dispose(const_iterator i, Disposer disposer) - { return tree_.erase_and_dispose(i, disposer); } + iterator erase_and_dispose(const_iterator i, Disposer disposer); - #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + //! @copydoc ::boost::intrusive::rbtree::erase_and_dispose(const_iterator,const_iterator,Disposer) template - iterator erase_and_dispose(iterator i, Disposer disposer) - { return this->erase_and_dispose(const_iterator(i), disposer); } - #endif + iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Returns: An iterator to the element after the erased elements. - //! - //! Effects: Erases the range pointed to by b end e. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Complexity: Average complexity for erase range is at most - //! O(log(size() + N)), where N is the number of elements in the range. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::rbtree::erase_and_dispose(const_reference, Disposer) template - iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer) - { return tree_.erase_and_dispose(b, e, disposer); } + size_type erase_and_dispose(const_reference value, Disposer disposer); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements with the given value. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: O(log(size() + this->count(value)). - //! - //! Throws: If the internal value_compare ordering function throws. Basic guarantee. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - template - size_type erase_and_dispose(const_reference value, Disposer disposer) - { return tree_.erase_and_dispose(value, disposer); } - - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements with the given key. - //! according to the comparison functor "comp". - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: O(log(size() + this->count(key, comp)). - //! - //! Throws: If comp ordering function throws. Basic guarantee. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::rbtree::erase_and_dispose(const KeyType&,KeyValueCompare,Disposer) template - size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) - { return tree_.erase_and_dispose(key, comp, disposer); } + size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer); - //! Effects: Erases all the elements of the container. - //! - //! Complexity: Linear to the number of elements on the container. - //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - void clear() - { return tree_.clear(); } + //! @copydoc ::boost::intrusive::rbtree::clear + void clear(); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements of the container. - //! - //! Complexity: Linear to the number of elements on the container. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. + //! @copydoc ::boost::intrusive::rbtree::clear_and_dispose template - void clear_and_dispose(Disposer disposer) - { return tree_.clear_and_dispose(disposer); } + void clear_and_dispose(Disposer disposer); - //! Effects: Returns the number of contained elements with the given key - //! - //! Complexity: Logarithmic to the number of elements contained plus lineal - //! to number of objects with the given key. - //! - //! Throws: If the internal value_compare ordering function throws. - size_type count(const_reference value) const - { return tree_.count(value); } + //! @copydoc ::boost::intrusive::rbtree::count(const_reference)const + size_type count(const_reference value) const; - //! Effects: Returns the number of contained elements with the same key - //! compared with the given comparison functor. - //! - //! Complexity: Logarithmic to the number of elements contained plus lineal - //! to number of objects with the given key. - //! - //! Throws: If comp ordering function throws. + //! @copydoc ::boost::intrusive::rbtree::count(const KeyType&,KeyValueCompare)const template - size_type count(const KeyType& key, KeyValueCompare comp) const - { return tree_.count(key, comp); } - - //! Effects: Returns an iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - iterator lower_bound(const_reference value) - { return tree_.lower_bound(value); } - - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Returns an iterator to the first element whose - //! key according to the comparison functor is not less than k or - //! end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + size_type count(const KeyType& key, KeyValueCompare comp) const; + + //! @copydoc ::boost::intrusive::rbtree::lower_bound(const_reference) + iterator lower_bound(const_reference value); + + //! @copydoc ::boost::intrusive::rbtree::lower_bound(const KeyType&,KeyValueCompare) template - iterator lower_bound(const KeyType& key, KeyValueCompare comp) - { return tree_.lower_bound(key, comp); } + iterator lower_bound(const KeyType& key, KeyValueCompare comp); - //! Effects: Returns a const iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - const_iterator lower_bound(const_reference value) const - { return tree_.lower_bound(value); } + //! @copydoc ::boost::intrusive::rbtree::lower_bound(const_reference)const + const_iterator lower_bound(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Returns a const_iterator to the first element whose - //! key according to the comparison functor is not less than k or - //! end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::rbtree::lower_bound(const KeyType&,KeyValueCompare)const template - const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const - { return tree_.lower_bound(key, comp); } + const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Returns an iterator to the first element whose - //! key is greater than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - iterator upper_bound(const_reference value) - { return tree_.upper_bound(value); } + //! @copydoc ::boost::intrusive::rbtree::upper_bound(const_reference) + iterator upper_bound(const_reference value); - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Returns an iterator to the first element whose - //! key according to the comparison functor is greater than key or - //! end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::rbtree::upper_bound(const KeyType&,KeyValueCompare) template - iterator upper_bound(const KeyType& key, KeyValueCompare comp) - { return tree_.upper_bound(key, comp); } + iterator upper_bound(const KeyType& key, KeyValueCompare comp); - //! Effects: Returns an iterator to the first element whose - //! key is greater than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - const_iterator upper_bound(const_reference value) const - { return tree_.upper_bound(value); } + //! @copydoc ::boost::intrusive::rbtree::upper_bound(const_reference)const + const_iterator upper_bound(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Returns a const_iterator to the first element whose - //! key according to the comparison functor is greater than key or - //! end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::rbtree::upper_bound(const KeyType&,KeyValueCompare)const template - const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const - { return tree_.upper_bound(key, comp); } + const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Finds an iterator to the first element whose value is - //! "value" or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - iterator find(const_reference value) - { return tree_.find(value); } + //! @copydoc ::boost::intrusive::rbtree::find(const_reference) + iterator find(const_reference value); - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Finds an iterator to the first element whose key is - //! "key" according to the comparison functor or end() if that element - //! does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::rbtree::find(const KeyType&,KeyValueCompare) template - iterator find(const KeyType& key, KeyValueCompare comp) - { return tree_.find(key, comp); } + iterator find(const KeyType& key, KeyValueCompare comp); - //! Effects: Finds a const_iterator to the first element whose value is - //! "value" or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - const_iterator find(const_reference value) const - { return tree_.find(value); } + //! @copydoc ::boost::intrusive::rbtree::find(const_reference)const + const_iterator find(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Finds a const_iterator to the first element whose key is - //! "key" according to the comparison functor or end() if that element - //! does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::rbtree::find(const KeyType&,KeyValueCompare)const template - const_iterator find(const KeyType& key, KeyValueCompare comp) const - { return tree_.find(key, comp); } + const_iterator find(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - std::pair equal_range(const_reference value) - { return tree_.equal_range(value); } + //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference) + std::pair equal_range(const_reference value); - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Finds a range containing all elements whose key is k - //! according to the comparison functor or an empty range - //! that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare) template - std::pair equal_range(const KeyType& key, KeyValueCompare comp) - { return tree_.equal_range(key, comp); } + std::pair equal_range(const KeyType& key, KeyValueCompare comp); - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. + //! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference)const std::pair - equal_range(const_reference value) const - { return tree_.equal_range(value); } + equal_range(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Finds a range containing all elements whose key is k - //! according to the comparison functor or an empty range - //! that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare)const template std::pair - equal_range(const KeyType& key, KeyValueCompare comp) const - { return tree_.equal_range(key, comp); } + equal_range(const KeyType& key, KeyValueCompare comp) const; - //! Requires: 'lower_value' must not be greater than 'upper_value'. If - //! 'lower_value' == 'upper_value', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise - //! - //! second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the predicate throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_value and upper_value. + //! @copydoc ::boost::intrusive::rbtree::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) - { return tree_.bounded_range(lower_value, upper_value, left_closed, right_closed); } + (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); - //! Requires: KeyValueCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. - //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If - //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key, comp) if left_closed, upper_bound(lower_key, comp) otherwise - //! - //! second = upper_bound(upper_key, comp) if right_closed, lower_bound(upper_key, comp) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_key and upper_key. + //! @copydoc ::boost::intrusive::rbtree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool) template std::pair bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) - { return tree_.bounded_range(lower_key, upper_key, comp, left_closed, right_closed); } + (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed); - //! Requires: 'lower_value' must not be greater than 'upper_value'. If - //! 'lower_value' == 'upper_value', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise - //! - //! second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the predicate throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_value and upper_value. + //! @copydoc ::boost::intrusive::rbtree::bounded_range(const_reference,const_reference,bool,bool)const std::pair - bounded_range(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const - { return tree_.bounded_range(lower_value, upper_value, left_closed, right_closed); } + bounded_range(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; - //! Requires: KeyValueCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. - //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If - //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key, comp) if left_closed, upper_bound(lower_key, comp) otherwise - //! - //! second = upper_bound(upper_key, comp) if right_closed, lower_bound(upper_key, comp) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_key and upper_key. + //! @copydoc ::boost::intrusive::rbtree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const template - std::pair - bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const - { return tree_.bounded_range(lower_key, upper_key, comp, left_closed, right_closed); } + std::pair bounded_range + (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; - //! Requires: value must be an lvalue and shall be in a set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid iterator i belonging to the set - //! that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This static function is available only if the value traits - //! is stateless. - static iterator s_iterator_to(reference value) - { return tree_type::s_iterator_to(value); } + //! @copydoc ::boost::intrusive::rbtree::s_iterator_to(reference) + static iterator s_iterator_to(reference value); - //! Requires: value must be an lvalue and shall be in a set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid const_iterator i belonging to the - //! set that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This static function is available only if the value traits - //! is stateless. - static const_iterator s_iterator_to(const_reference value) - { return tree_type::s_iterator_to(value); } + //! @copydoc ::boost::intrusive::rbtree::s_iterator_to(const_reference) + static const_iterator s_iterator_to(const_reference value); - //! Requires: value must be an lvalue and shall be in a set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid iterator i belonging to the set - //! that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator iterator_to(reference value) - { return tree_.iterator_to(value); } + //! @copydoc ::boost::intrusive::rbtree::iterator_to(reference) + iterator iterator_to(reference value); - //! Requires: value must be an lvalue and shall be in a set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid const_iterator i belonging to the - //! set that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator iterator_to(const_reference value) const - { return tree_.iterator_to(value); } + //! @copydoc ::boost::intrusive::rbtree::iterator_to(const_reference)const + const_iterator iterator_to(const_reference value) const; - //! Requires: value shall not be in a set/multiset. - //! - //! Effects: init_node puts the hook of a value in a well-known default - //! state. - //! - //! Throws: Nothing. - //! - //! Complexity: Constant time. - //! - //! Note: This function puts the hook in the well-known default state - //! used by auto_unlink and safe hooks. - static void init_node(reference value) - { tree_type::init_node(value); } + //! @copydoc ::boost::intrusive::rbtree::init_node(reference) + static void init_node(reference value); - //! Effects: Unlinks the leftmost node from the tree. - //! - //! Complexity: Average complexity is constant time. - //! - //! Throws: Nothing. - //! - //! Notes: This function breaks the tree and the tree can - //! only be used for more unlink_leftmost_without_rebalance calls. - //! This function is normally used to achieve a step by step - //! controlled destruction of the tree. - pointer unlink_leftmost_without_rebalance() - { return tree_.unlink_leftmost_without_rebalance(); } + //! @copydoc ::boost::intrusive::rbtree::unlink_leftmost_without_rebalance + pointer unlink_leftmost_without_rebalance(); - //! Requires: replace_this must be a valid iterator of *this - //! and with_this must not be inserted in any tree. - //! - //! Effects: Replaces replace_this in its position in the - //! tree with with_this. The tree does not need to be rebalanced. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This function will break container ordering invariants if - //! with_this is not equivalent to *replace_this according to the - //! ordering rules. This function is faster than erasing and inserting - //! the node, since no rebalancing or comparison is needed. - void replace_node(iterator replace_this, reference with_this) - { tree_.replace_node(replace_this, with_this); } + //! @copydoc ::boost::intrusive::rbtree::replace_node + void replace_node(iterator replace_this, reference with_this); - //! Effects: removes "value" from the container. - //! - //! Throws: Nothing. - //! - //! Complexity: Logarithmic time. - //! - //! Note: This static function is only usable with non-constant - //! time size containers that have stateless comparison functors. - //! - //! If the user calls - //! this function with a constant time size container or stateful comparison - //! functor a compilation error will be issued. - static void remove_node(reference value) - { tree_type::remove_node(value); } - - /// @cond - friend bool operator==(const multiset_impl &x, const multiset_impl &y) - { return x.tree_ == y.tree_; } - - friend bool operator<(const multiset_impl &x, const multiset_impl &y) - { return x.tree_ < y.tree_; } - /// @endcond + //! @copydoc ::boost::intrusive::rbtree::remove_node + void remove_node(reference value); + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED }; #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator!= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const multiset_impl &x, const multiset_impl &y) -#else -(const multiset_impl &x, const multiset_impl &y) -#endif -{ return !(x == y); } -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator> -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const multiset_impl &x, const multiset_impl &y) -#else -(const multiset_impl &x, const multiset_impl &y) -#endif -{ return y < x; } +bool operator!= (const multiset_impl &x, const multiset_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator<= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const multiset_impl &x, const multiset_impl &y) -#else -(const multiset_impl &x, const multiset_impl &y) -#endif -{ return !(y < x); } +bool operator>(const multiset_impl &x, const multiset_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator>= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const multiset_impl &x, const multiset_impl &y) -#else -(const multiset_impl &x, const multiset_impl &y) -#endif -{ return !(x < y); } +bool operator<=(const multiset_impl &x, const multiset_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline void swap -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(multiset_impl &x, multiset_impl &y) -#else -(multiset_impl &x, multiset_impl &y) -#endif -{ x.swap(y); } +bool operator>=(const multiset_impl &x, const multiset_impl &y); + +template +void swap(multiset_impl &x, multiset_impl &y); + +#endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Helper metafunction to define a \c multiset that yields to the same type when the //! same options (either explicitly or implicitly) are used. #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else -template +template #endif struct make_multiset { /// @cond - typedef multiset_impl - < typename make_rbtree_opt::type - > implementation_defined; + >::type packed_options; + + typedef typename detail::get_value_traits + ::type value_traits; + + typedef multiset_impl + < value_traits + , typename packed_options::compare + , typename packed_options::size_type + , packed_options::constant_time_size + > implementation_defined; /// @endcond typedef implementation_defined type; }; @@ -2529,7 +898,7 @@ class multiset {} multiset& operator=(BOOST_RV_REF(multiset) x) - { this->Base::operator=(::boost::move(static_cast(x))); return *this; } + { return static_cast(this->Base::operator=(::boost::move(static_cast(x)))); } static multiset &container_from_end_iterator(iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } diff --git a/include/boost/intrusive/set_hook.hpp b/include/boost/intrusive/set_hook.hpp index 2634b42..38da7bc 100644 --- a/include/boost/intrusive/set_hook.hpp +++ b/include/boost/intrusive/set_hook.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 @@ -38,7 +38,7 @@ struct get_set_node_algo #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else -template +template #endif struct make_set_base_hook { @@ -52,12 +52,12 @@ struct make_set_base_hook #endif >::type packed_options; - typedef detail::generic_hook + typedef generic_hook < get_set_node_algo , typename packed_options::tag , packed_options::link_mode - , detail::SetBaseHook + , RbTreeBaseHookId > implementation_defined; /// @endcond typedef implementation_defined type; @@ -170,7 +170,7 @@ class set_base_hook #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else -template +template #endif struct make_set_member_hook { @@ -184,12 +184,12 @@ struct make_set_member_hook #endif >::type packed_options; - typedef detail::generic_hook + typedef generic_hook < get_set_node_algo , member_tag , packed_options::link_mode - , detail::NoBaseHook + , NoBaseHookId > implementation_defined; /// @endcond typedef implementation_defined type; diff --git a/include/boost/intrusive/sg_set.hpp b/include/boost/intrusive/sg_set.hpp index e18b021..f42fab8 100644 --- a/include/boost/intrusive/sg_set.hpp +++ b/include/boost/intrusive/sg_set.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 @@ -14,16 +14,16 @@ #include #include -#include #include -#include +#include #include +#include namespace boost { namespace intrusive { //! The class template sg_set is an intrusive container, that mimics most of -//! the interface of std::set as described in the C++ standard. +//! the interface of std::sg_set as described in the C++ standard. //! //! The template parameter \c T is the type to be managed by the container. //! The user can specify additional options and if no options are provided @@ -31,19 +31,20 @@ namespace intrusive { //! //! The container supports the following options: //! \c base_hook<>/member_hook<>/value_traits<>, -//! \c constant_time_size<>, \c size_type<> and +//! \c floating_point<>, \c size_type<> and //! \c compare<>. #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class sg_set_impl +#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + : public sgtree_impl +#endif { /// @cond - typedef sgtree_impl tree_type; - //! This class is - //! movable + typedef sgtree_impl tree_type; BOOST_MOVABLE_BUT_NOT_COPYABLE(sg_set_impl) typedef tree_type implementation_defined; @@ -71,1224 +72,356 @@ class sg_set_impl typedef typename implementation_defined::const_node_ptr const_node_ptr; typedef typename implementation_defined::node_algorithms node_algorithms; - /// @cond - private: - tree_type tree_; - /// @endcond + static const bool constant_time_size = tree_type::constant_time_size; public: - //! Effects: Constructs an empty sg_set. - //! - //! Complexity: Constant. - //! - //! Throws: If value_traits::node_traits::node - //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) - //! or the copy constructor of the value_compare object throws. + //! @copydoc ::boost::intrusive::sgtree::sgtree(const value_compare &,const value_traits &) explicit sg_set_impl( const value_compare &cmp = value_compare() - , const value_traits &v_traits = value_traits()) - : tree_(cmp, v_traits) + , const value_traits &v_traits = value_traits()) + : tree_type(cmp, v_traits) {} - //! Requires: Dereferencing iterator must yield an lvalue of type value_type. - //! cmp must be a comparison function that induces a strict weak ordering. - //! - //! Effects: Constructs an empty sg_set and inserts elements from - //! [b, e). - //! - //! Complexity: Linear in N if [b, e) is already sorted using - //! comp and otherwise N * log N, where N is std::distance(last, first). - //! - //! Throws: If value_traits::node_traits::node - //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) - //! or the copy constructor/operator() of the value_compare object throws. + //! @copydoc ::boost::intrusive::sgtree::sgtree(bool,Iterator,Iterator,const value_compare &,const value_traits &) template sg_set_impl( Iterator b, Iterator e , const value_compare &cmp = value_compare() , const value_traits &v_traits = value_traits()) - : tree_(true, b, e, cmp, v_traits) + : tree_type(true, b, e, cmp, v_traits) {} - //! Effects: to-do - //! + //! @copydoc ::boost::intrusive::sgtree::sgtree(sgtree &&) sg_set_impl(BOOST_RV_REF(sg_set_impl) x) - : tree_(::boost::move(x.tree_)) + : tree_type(::boost::move(static_cast(x))) {} - //! Effects: to-do - //! + //! @copydoc ::boost::intrusive::sgtree::operator=(sgtree &&) sg_set_impl& operator=(BOOST_RV_REF(sg_set_impl) x) - { tree_ = ::boost::move(x.tree_); return *this; } + { return static_cast(tree_type::operator=(::boost::move(static_cast(x)))); } - //! Effects: Detaches all elements from this. The objects in the sg_set - //! are not deleted (i.e. no destructors are called). - //! - //! Complexity: Linear to the number of elements on the container. - //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. - //! - //! Throws: Nothing. - ~sg_set_impl() - {} + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::sgtree::~sgtree() + ~sg_set_impl(); - //! Effects: Returns an iterator pointing to the beginning of the sg_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator begin() - { return tree_.begin(); } + //! @copydoc ::boost::intrusive::sgtree::begin() + iterator begin(); - //! Effects: Returns a const_iterator pointing to the beginning of the sg_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator begin() const - { return tree_.begin(); } + //! @copydoc ::boost::intrusive::sgtree::begin()const + const_iterator begin() const; - //! Effects: Returns a const_iterator pointing to the beginning of the sg_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator cbegin() const - { return tree_.cbegin(); } + //! @copydoc ::boost::intrusive::sgtree::cbegin()const + const_iterator cbegin() const; - //! Effects: Returns an iterator pointing to the end of the sg_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator end() - { return tree_.end(); } + //! @copydoc ::boost::intrusive::sgtree::end() + iterator end(); - //! Effects: Returns a const_iterator pointing to the end of the sg_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator end() const - { return tree_.end(); } + //! @copydoc ::boost::intrusive::sgtree::end()const + const_iterator end() const; - //! Effects: Returns a const_iterator pointing to the end of the sg_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator cend() const - { return tree_.cend(); } + //! @copydoc ::boost::intrusive::sgtree::cend()const + const_iterator cend() const; - //! Effects: Returns a reverse_iterator pointing to the beginning of the - //! reversed sg_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - reverse_iterator rbegin() - { return tree_.rbegin(); } + //! @copydoc ::boost::intrusive::sgtree::rbegin() + reverse_iterator rbegin(); - //! Effects: Returns a const_reverse_iterator pointing to the beginning - //! of the reversed sg_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator rbegin() const - { return tree_.rbegin(); } + //! @copydoc ::boost::intrusive::sgtree::rbegin()const + const_reverse_iterator rbegin() const; - //! Effects: Returns a const_reverse_iterator pointing to the beginning - //! of the reversed sg_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator crbegin() const - { return tree_.crbegin(); } + //! @copydoc ::boost::intrusive::sgtree::crbegin()const + const_reverse_iterator crbegin() const; - //! Effects: Returns a reverse_iterator pointing to the end - //! of the reversed sg_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - reverse_iterator rend() - { return tree_.rend(); } + //! @copydoc ::boost::intrusive::sgtree::rend() + reverse_iterator rend(); - //! Effects: Returns a const_reverse_iterator pointing to the end - //! of the reversed sg_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator rend() const - { return tree_.rend(); } + //! @copydoc ::boost::intrusive::sgtree::rend()const + const_reverse_iterator rend() const; - //! Effects: Returns a const_reverse_iterator pointing to the end - //! of the reversed sg_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator crend() const - { return tree_.crend(); } + //! @copydoc ::boost::intrusive::sgtree::crend()const + const_reverse_iterator crend() const; - //! Precondition: end_iterator must be a valid end iterator - //! of sg_set. - //! - //! Effects: Returns a const reference to the sg_set associated to the end iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - static sg_set_impl &container_from_end_iterator(iterator end_iterator) - { - return *detail::parent_from_member - ( &tree_type::container_from_end_iterator(end_iterator) - , &sg_set_impl::tree_); - } + //! @copydoc ::boost::intrusive::sgtree::container_from_end_iterator(iterator) + static sg_set_impl &container_from_end_iterator(iterator end_iterator); - //! Precondition: end_iterator must be a valid end const_iterator - //! of sg_set. - //! - //! Effects: Returns a const reference to the sg_set associated to the end iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - static const sg_set_impl &container_from_end_iterator(const_iterator end_iterator) - { - return *detail::parent_from_member - ( &tree_type::container_from_end_iterator(end_iterator) - , &sg_set_impl::tree_); - } + //! @copydoc ::boost::intrusive::sgtree::container_from_end_iterator(const_iterator) + static const sg_set_impl &container_from_end_iterator(const_iterator end_iterator); - //! Precondition: it must be a valid iterator of set. - //! - //! Effects: Returns a reference to the set associated to the iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Logarithmic. - static sg_set_impl &container_from_iterator(iterator it) - { - return *detail::parent_from_member - ( &tree_type::container_from_iterator(it) - , &sg_set_impl::tree_); - } + //! @copydoc ::boost::intrusive::sgtree::container_from_iterator(iterator) + static sg_set_impl &container_from_iterator(iterator it); - //! Precondition: it must be a valid const_iterator of set. - //! - //! Effects: Returns a const reference to the set associated to the iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Logarithmic. - static const sg_set_impl &container_from_iterator(const_iterator it) - { - return *detail::parent_from_member - ( &tree_type::container_from_iterator(it) - , &sg_set_impl::tree_); - } + //! @copydoc ::boost::intrusive::sgtree::container_from_iterator(const_iterator) + static const sg_set_impl &container_from_iterator(const_iterator it); - //! Effects: Returns the key_compare object used by the sg_set. - //! - //! Complexity: Constant. - //! - //! Throws: If key_compare copy-constructor throws. - key_compare key_comp() const - { return tree_.value_comp(); } + //! @copydoc ::boost::intrusive::sgtree::key_comp()const + key_compare key_comp() const; - //! Effects: Returns the value_compare object used by the sg_set. - //! - //! Complexity: Constant. - //! - //! Throws: If value_compare copy-constructor throws. - value_compare value_comp() const - { return tree_.value_comp(); } + //! @copydoc ::boost::intrusive::sgtree::value_comp()const + value_compare value_comp() const; - //! Effects: Returns true if the container is empty. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - bool empty() const - { return tree_.empty(); } + //! @copydoc ::boost::intrusive::sgtree::empty()const + bool empty() const; - //! Effects: Returns the number of elements stored in the sg_set. - //! - //! Complexity: Linear to elements contained in *this if, - //! constant-time size option is enabled. Constant-time otherwise. - //! - //! Throws: Nothing. - size_type size() const - { return tree_.size(); } + //! @copydoc ::boost::intrusive::sgtree::size()const + size_type size() const; - //! Effects: Swaps the contents of two sets. - //! - //! Complexity: Constant. - //! - //! Throws: If the swap() call for the comparison functor - //! found using ADL throws. Strong guarantee. - void swap(sg_set_impl& other) - { tree_.swap(other.tree_); } + //! @copydoc ::boost::intrusive::sgtree::swap + void swap(sg_set_impl& other); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! Cloner should yield to nodes equivalent to the original nodes. - //! - //! Effects: Erases all the elements from *this - //! calling Disposer::operator()(pointer), clones all the - //! elements from src calling Cloner::operator()(const_reference ) - //! and inserts them on *this. Copies the predicate from the source container. - //! - //! If cloner throws, all cloned elements are unlinked and disposed - //! calling Disposer::operator()(pointer). - //! - //! Complexity: Linear to erased plus inserted elements. - //! - //! Throws: If cloner throws or predicate copy assignment throws. Basic guarantee. + //! @copydoc ::boost::intrusive::sgtree::clone_from template - void clone_from(const sg_set_impl &src, Cloner cloner, Disposer disposer) - { tree_.clone_from(src.tree_, cloner, disposer); } + void clone_from(const sg_set_impl &src, Cloner cloner, Disposer disposer); + + #endif //#ifdef BOOST_iNTRUSIVE_DOXYGEN_INVOKED - //! Requires: value must be an lvalue - //! - //! Effects: Tries to inserts value into the sg_set. - //! - //! Returns: If the value - //! is not already present inserts it and returns a pair containing the - //! iterator to the new value and true. If there is an equivalent value - //! returns a pair containing an iterator to the already present value - //! and false. - //! - //! Complexity: Average complexity for insert element is at - //! most logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. Strong guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + //! @copydoc ::boost::intrusive::sgtree::insert_unique(reference) std::pair insert(reference value) - { return tree_.insert_unique(value); } + { return tree_type::insert_unique(value); } - //! Requires: value must be an lvalue - //! - //! Effects: Tries to to insert x into the sg_set, using "hint" - //! as a hint to where it will be inserted. - //! - //! Returns: An iterator that points to the position where the - //! new element was inserted into the sg_set. - //! - //! Complexity: Logarithmic in general, but it's amortized - //! constant time if t is inserted immediately before hint. - //! - //! Throws: If the internal value_compare ordering function throws. Strong guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + //! @copydoc ::boost::intrusive::sgtree::insert_unique(const_iterator,reference) iterator insert(const_iterator hint, reference value) - { return tree_.insert_unique(hint, value); } + { return tree_type::insert_unique(hint, value); } - //! Requires: key_value_comp must be a comparison function that induces - //! the same strict weak ordering as value_compare. The difference is that - //! key_value_comp compares an arbitrary key with the contained values. - //! - //! Effects: Checks if a value can be inserted in the sg_set, using - //! a user provided key instead of the value itself. - //! - //! Returns: If there is an equivalent value - //! returns a pair containing an iterator to the already present value - //! and false. If the value can be inserted returns true in the returned - //! pair boolean and fills "commit_data" that is meant to be used with - //! the "insert_commit" function. - //! - //! Complexity: Average complexity is at most logarithmic. - //! - //! Throws: If the key_value_comp ordering function throws. Strong guarantee. - //! - //! Notes: This function is used to improve performance when constructing - //! a value_type is expensive: if there is an equivalent value - //! the constructed object must be discarded. Many times, the part of the - //! node that is used to impose the order is much cheaper to construct - //! than the value_type and this function offers the possibility to use that - //! part to check if the insertion will be successful. - //! - //! If the check is successful, the user can construct the value_type and use - //! "insert_commit" to insert the object in constant-time. This gives a total - //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)). - //! - //! "commit_data" remains valid for a subsequent "insert_commit" only if no more - //! objects are inserted or erased from the sg_set. + //! @copydoc ::boost::intrusive::sgtree::insert_unique_check(const KeyType&,KeyValueCompare,insert_commit_data&) template std::pair insert_check (const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data) - { return tree_.insert_unique_check(key, key_value_comp, commit_data); } + { return tree_type::insert_unique_check(key, key_value_comp, commit_data); } - //! Requires: key_value_comp must be a comparison function that induces - //! the same strict weak ordering as value_compare. The difference is that - //! key_value_comp compares an arbitrary key with the contained values. - //! - //! Effects: Checks if a value can be inserted in the sg_set, using - //! a user provided key instead of the value itself, using "hint" - //! as a hint to where it will be inserted. - //! - //! Returns: If there is an equivalent value - //! returns a pair containing an iterator to the already present value - //! and false. If the value can be inserted returns true in the returned - //! pair boolean and fills "commit_data" that is meant to be used with - //! the "insert_commit" function. - //! - //! Complexity: Logarithmic in general, but it's amortized - //! constant time if t is inserted immediately before hint. - //! - //! Throws: If the key_value_comp ordering function throws. Strong guarantee. - //! - //! Notes: This function is used to improve performance when constructing - //! a value_type is expensive: if there is an equivalent value - //! the constructed object must be discarded. Many times, the part of the - //! constructing that is used to impose the order is much cheaper to construct - //! than the value_type and this function offers the possibility to use that key - //! to check if the insertion will be successful. - //! - //! If the check is successful, the user can construct the value_type and use - //! "insert_commit" to insert the object in constant-time. This can give a total - //! constant-time complexity to the insertion: check(O(1)) + commit(O(1)). - //! - //! "commit_data" remains valid for a subsequent "insert_commit" only if no more - //! objects are inserted or erased from the sg_set. + //! @copydoc ::boost::intrusive::sgtree::insert_unique_check(const_iterator,const KeyType&,KeyValueCompare,insert_commit_data&) template std::pair insert_check (const_iterator hint, const KeyType &key ,KeyValueCompare key_value_comp, insert_commit_data &commit_data) - { return tree_.insert_unique_check(hint, key, key_value_comp, commit_data); } + { return tree_type::insert_unique_check(hint, key, key_value_comp, commit_data); } - //! Requires: value must be an lvalue of type value_type. commit_data - //! must have been obtained from a previous call to "insert_check". - //! No objects should have been inserted or erased from the sg_set between - //! the "insert_check" that filled "commit_data" and the call to "insert_commit". - //! - //! Effects: Inserts the value in the sg_set using the information obtained - //! from the "commit_data" that a previous "insert_check" filled. - //! - //! Returns: An iterator to the newly inserted object. - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Notes: This function has only sense if a "insert_check" has been - //! previously executed to fill "commit_data". No value should be inserted or - //! erased between the "insert_check" and "insert_commit" calls. - iterator insert_commit(reference value, const insert_commit_data &commit_data) - { return tree_.insert_unique_commit(value, commit_data); } - - //! Requires: Dereferencing iterator must yield an lvalue - //! of type value_type. - //! - //! Effects: Inserts a range into the sg_set. - //! - //! Complexity: Insert range is in general O(N * log(N)), where N is the - //! size of the range. However, it is linear in N if the range is already sorted - //! by value_comp(). - //! - //! Throws: If the internal value_compare ordering function throws. Basic guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + //! @copydoc ::boost::intrusive::sgtree::insert_unique(Iterator,Iterator) template void insert(Iterator b, Iterator e) - { tree_.insert_unique(b, e); } + { tree_type::insert_unique(b, e); } - //! Requires: value must be an lvalue, "pos" must be - //! a valid iterator (or end) and must be the succesor of value - //! once inserted according to the predicate. "value" must not be equal to any - //! inserted key according to the predicate. - //! - //! Effects: Inserts x into the tree before "pos". - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Note: This function does not check preconditions so if "pos" is not - //! the successor of "value" or "value" is not unique tree ordering and uniqueness - //! invariants will be broken respectively. - //! This is a low-level function to be used only for performance reasons - //! by advanced users. - iterator insert_before(const_iterator pos, reference value) - { return tree_.insert_before(pos, value); } + //! @copydoc ::boost::intrusive::sgtree::insert_unique_commit + iterator insert_commit(reference value, const insert_commit_data &commit_data) + { return tree_type::insert_unique_commit(value, commit_data); } - //! Requires: value must be an lvalue, and it must be greater than - //! any inserted key according to the predicate. - //! - //! Effects: Inserts x into the tree in the last position. - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Note: This function does not check preconditions so if value is - //! less than or equal to the greatest inserted key tree ordering invariant will be broken. - //! This function is slightly more efficient than using "insert_before". - //! This is a low-level function to be used only for performance reasons - //! by advanced users. - void push_back(reference value) - { tree_.push_back(value); } + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::sgtree::insert_before + iterator insert_before(const_iterator pos, reference value); - //! Requires: value must be an lvalue, and it must be less - //! than any inserted key according to the predicate. - //! - //! Effects: Inserts x into the tree in the first position. - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Note: This function does not check preconditions so if value is - //! greater than or equal to the the mimum inserted key tree ordering or uniqueness - //! invariants will be broken. - //! This function is slightly more efficient than using "insert_before". - //! This is a low-level function to be used only for performance reasons - //! by advanced users. - void push_front(reference value) - { tree_.push_front(value); } + //! @copydoc ::boost::intrusive::sgtree::push_back + void push_back(reference value); - //! Effects: Erases the element pointed to by pos. - //! - //! Complexity: Average complexity is constant time. - //! - //! Returns: An iterator to the element after the erased element. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - iterator erase(const_iterator i) - { return tree_.erase(i); } + //! @copydoc ::boost::intrusive::sgtree::push_front + void push_front(reference value); - //! Effects: Erases the range pointed to by b end e. - //! - //! Complexity: Average complexity for erase range is at most - //! O(log(size() + N)), where N is the number of elements in the range. - //! - //! Returns: An iterator to the element after the erased elements. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - iterator erase(const_iterator b, const_iterator e) - { return tree_.erase(b, e); } + //! @copydoc ::boost::intrusive::sgtree::erase(const_iterator) + iterator erase(const_iterator i); - //! Effects: Erases all the elements with the given value. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: O(log(size()) + this->count(value)). - //! - //! Throws: If the internal value_compare ordering function throws. Basic guarantee. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - size_type erase(const_reference value) - { return tree_.erase(value); } + //! @copydoc ::boost::intrusive::sgtree::erase(const_iterator,const_iterator) + iterator erase(const_iterator b, const_iterator e); - //! Effects: Erases all the elements that compare equal with - //! the given key and the given comparison functor. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: O(log(size() + this->count(key, comp)). - //! - //! Throws: If the comp ordering function throws. Basic guarantee. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. + //! @copydoc ::boost::intrusive::sgtree::erase(const_reference) + size_type erase(const_reference value); + + //! @copydoc ::boost::intrusive::sgtree::erase(const KeyType&,KeyValueCompare) template - size_type erase(const KeyType& key, KeyValueCompare comp - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) - { return tree_.erase(key, comp); } + size_type erase(const KeyType& key, KeyValueCompare comp); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases the element pointed to by pos. - //! Disposer::operator()(pointer) is called for the removed element. - //! - //! Complexity: Average complexity for erase element is constant time. - //! - //! Returns: An iterator to the element after the erased element. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::sgtree::erase_and_dispose(const_iterator,Disposer) template - iterator erase_and_dispose(const_iterator i, Disposer disposer) - { return tree_.erase_and_dispose(i, disposer); } + iterator erase_and_dispose(const_iterator i, Disposer disposer); - #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + //! @copydoc ::boost::intrusive::sgtree::erase_and_dispose(const_iterator,const_iterator,Disposer) template - iterator erase_and_dispose(iterator i, Disposer disposer) - { return this->erase_and_dispose(const_iterator(i), disposer); } - #endif + iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases the range pointed to by b end e. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Complexity: Average complexity for erase range is at most - //! O(log(size() + N)), where N is the number of elements in the range. - //! - //! Returns: An iterator to the element after the erased elements. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::sgtree::erase_and_dispose(const_reference, Disposer) template - iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer) - { return tree_.erase_and_dispose(b, e, disposer); } + size_type erase_and_dispose(const_reference value, Disposer disposer); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements with the given value. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Throws: If the internal value_compare ordering function throws. - //! - //! Complexity: O(log(size() + this->count(value)). Basic guarantee. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - template - size_type erase_and_dispose(const_reference value, Disposer disposer) - { return tree_.erase_and_dispose(value, disposer); } - - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements with the given key. - //! according to the comparison functor "comp". - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: O(log(size() + this->count(key, comp)). - //! - //! Throws: If comp ordering function throws. Basic guarantee. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::sgtree::erase_and_dispose(const KeyType&,KeyValueCompare,Disposer) template - size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) - { return tree_.erase_and_dispose(key, comp, disposer); } + size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer); - //! Effects: Erases all the elements of the container. - //! - //! Complexity: Linear to the number of elements on the container. - //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - void clear() - { return tree_.clear(); } + //! @copydoc ::boost::intrusive::sgtree::clear + void clear(); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements of the container. - //! - //! Complexity: Linear to the number of elements on the container. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. + //! @copydoc ::boost::intrusive::sgtree::clear_and_dispose template - void clear_and_dispose(Disposer disposer) - { return tree_.clear_and_dispose(disposer); } + void clear_and_dispose(Disposer disposer); - //! Effects: Returns the number of contained elements with the given key - //! - //! Complexity: Logarithmic to the number of elements contained plus lineal - //! to number of objects with the given key. - //! - //! Throws: If the internal value_compare ordering function throws. - size_type count(const_reference value) const - { return tree_.find(value) != end(); } + //! @copydoc ::boost::intrusive::sgtree::count(const_reference)const + size_type count(const_reference value) const; - //! Effects: Returns the number of contained elements with the same key - //! compared with the given comparison functor. - //! - //! Complexity: Logarithmic to the number of elements contained plus lineal - //! to number of objects with the given key. - //! - //! Throws: If comp ordering function throws. + //! @copydoc ::boost::intrusive::sgtree::count(const KeyType&,KeyValueCompare)const template - size_type count(const KeyType& key, KeyValueCompare comp) const - { return tree_.find(key, comp) != end(); } - - //! Effects: Returns an iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - iterator lower_bound(const_reference value) - { return tree_.lower_bound(value); } - - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Returns an iterator to the first element whose - //! key according to the comparison functor is not less than k or - //! end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + size_type count(const KeyType& key, KeyValueCompare comp) const; + + //! @copydoc ::boost::intrusive::sgtree::lower_bound(const_reference) + iterator lower_bound(const_reference value); + + //! @copydoc ::boost::intrusive::sgtree::lower_bound(const KeyType&,KeyValueCompare) template - iterator lower_bound(const KeyType& key, KeyValueCompare comp) - { return tree_.lower_bound(key, comp); } + iterator lower_bound(const KeyType& key, KeyValueCompare comp); - //! Effects: Returns a const iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - const_iterator lower_bound(const_reference value) const - { return tree_.lower_bound(value); } + //! @copydoc ::boost::intrusive::sgtree::lower_bound(const_reference)const + const_iterator lower_bound(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Returns a const_iterator to the first element whose - //! key according to the comparison functor is not less than k or - //! end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::sgtree::lower_bound(const KeyType&,KeyValueCompare)const template - const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const - { return tree_.lower_bound(key, comp); } + const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Returns an iterator to the first element whose - //! key is greater than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - iterator upper_bound(const_reference value) - { return tree_.upper_bound(value); } + //! @copydoc ::boost::intrusive::sgtree::upper_bound(const_reference) + iterator upper_bound(const_reference value); - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Returns an iterator to the first element whose - //! key according to the comparison functor is greater than key or - //! end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::sgtree::upper_bound(const KeyType&,KeyValueCompare) template - iterator upper_bound(const KeyType& key, KeyValueCompare comp) - { return tree_.upper_bound(key, comp); } + iterator upper_bound(const KeyType& key, KeyValueCompare comp); - //! Effects: Returns an iterator to the first element whose - //! key is greater than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - const_iterator upper_bound(const_reference value) const - { return tree_.upper_bound(value); } + //! @copydoc ::boost::intrusive::sgtree::upper_bound(const_reference)const + const_iterator upper_bound(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Returns a const_iterator to the first element whose - //! key according to the comparison functor is greater than key or - //! end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::sgtree::upper_bound(const KeyType&,KeyValueCompare)const template - const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const - { return tree_.upper_bound(key, comp); } + const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Finds an iterator to the first element whose value is - //! "value" or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - iterator find(const_reference value) - { return tree_.find(value); } + //! @copydoc ::boost::intrusive::sgtree::find(const_reference) + iterator find(const_reference value); - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Finds an iterator to the first element whose key is - //! "key" according to the comparison functor or end() if that element - //! does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::sgtree::find(const KeyType&,KeyValueCompare) template - iterator find(const KeyType& key, KeyValueCompare comp) - { return tree_.find(key, comp); } + iterator find(const KeyType& key, KeyValueCompare comp); - //! Effects: Finds a const_iterator to the first element whose value is - //! "value" or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - const_iterator find(const_reference value) const - { return tree_.find(value); } + //! @copydoc ::boost::intrusive::sgtree::find(const_reference)const + const_iterator find(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Finds a const_iterator to the first element whose key is - //! "key" according to the comparison functor or end() if that element - //! does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::sgtree::find(const KeyType&,KeyValueCompare)const template - const_iterator find(const KeyType& key, KeyValueCompare comp) const - { return tree_.find(key, comp); } + const_iterator find(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - std::pair equal_range(const_reference value) - { return tree_.equal_range(value); } + //! @copydoc ::boost::intrusive::sgtree::equal_range(const_reference) + std::pair equal_range(const_reference value); - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Finds a range containing all elements whose key is k - //! according to the comparison functor or an empty range - //! that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::sgtree::equal_range(const KeyType&,KeyValueCompare) template - std::pair equal_range(const KeyType& key, KeyValueCompare comp) - { return tree_.equal_range(key, comp); } + std::pair equal_range(const KeyType& key, KeyValueCompare comp); - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. + //! @copydoc ::boost::intrusive::sgtree::equal_range(const_reference)const std::pair - equal_range(const_reference value) const - { return tree_.equal_range(value); } + equal_range(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Finds a range containing all elements whose key is k - //! according to the comparison functor or an empty range - //! that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::sgtree::equal_range(const KeyType&,KeyValueCompare)const template std::pair - equal_range(const KeyType& key, KeyValueCompare comp) const - { return tree_.equal_range(key, comp); } + equal_range(const KeyType& key, KeyValueCompare comp) const; - //! Requires: 'lower_value' must not be greater than 'upper_value'. If - //! 'lower_value' == 'upper_value', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise - //! - //! second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the predicate throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_value and upper_value. + //! @copydoc ::boost::intrusive::sgtree::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) - { return tree_.bounded_range(lower_value, upper_value, left_closed, right_closed); } + (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); - //! Requires: KeyValueCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. - //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If - //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key, comp) if left_closed, upper_bound(lower_key, comp) otherwise - //! - //! second = upper_bound(upper_key, comp) if right_closed, lower_bound(upper_key, comp) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_key and upper_key. + //! @copydoc ::boost::intrusive::sgtree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool) template std::pair bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) - { return tree_.bounded_range(lower_key, upper_key, comp, left_closed, right_closed); } + (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed); - //! Requires: 'lower_value' must not be greater than 'upper_value'. If - //! 'lower_value' == 'upper_value', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise - //! - //! second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the predicate throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_value and upper_value. + //! @copydoc ::boost::intrusive::sgtree::bounded_range(const_reference,const_reference,bool,bool)const std::pair - bounded_range(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const - { return tree_.bounded_range(lower_value, upper_value, left_closed, right_closed); } + bounded_range(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; - //! Requires: KeyValueCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. - //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If - //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key, comp) if left_closed, upper_bound(lower_key, comp) otherwise - //! - //! second = upper_bound(upper_key, comp) if right_closed, lower_bound(upper_key, comp) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_key and upper_key. + //! @copydoc ::boost::intrusive::sgtree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const template - std::pair - bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const - { return tree_.bounded_range(lower_key, upper_key, comp, left_closed, right_closed); } + std::pair bounded_range + (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; - //! Requires: value must be an lvalue and shall be in a sg_set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid iterator i belonging to the sg_set - //! that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This static function is available only if the value traits - //! is stateless. - static iterator s_iterator_to(reference value) - { return tree_type::s_iterator_to(value); } + //! @copydoc ::boost::intrusive::sgtree::s_iterator_to(reference) + static iterator s_iterator_to(reference value); - //! Requires: value must be an lvalue and shall be in a sg_set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid const_iterator i belonging to the - //! sg_set that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This static function is available only if the value traits - //! is stateless. - static const_iterator s_iterator_to(const_reference value) - { return tree_type::s_iterator_to(value); } + //! @copydoc ::boost::intrusive::sgtree::s_iterator_to(const_reference) + static const_iterator s_iterator_to(const_reference value); - //! Requires: value must be an lvalue and shall be in a sg_set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid iterator i belonging to the sg_set - //! that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator iterator_to(reference value) - { return tree_.iterator_to(value); } + //! @copydoc ::boost::intrusive::sgtree::iterator_to(reference) + iterator iterator_to(reference value); - //! Requires: value must be an lvalue and shall be in a sg_set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid const_iterator i belonging to the - //! sg_set that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator iterator_to(const_reference value) const - { return tree_.iterator_to(value); } + //! @copydoc ::boost::intrusive::sgtree::iterator_to(const_reference)const + const_iterator iterator_to(const_reference value) const; - //! Requires: value shall not be in a sg_set/sg_multiset. - //! - //! Effects: init_node puts the hook of a value in a well-known default - //! state. - //! - //! Throws: Nothing. - //! - //! Complexity: Constant time. - //! - //! Note: This function puts the hook in the well-known default state - //! used by auto_unlink and safe hooks. - static void init_node(reference value) - { tree_type::init_node(value); } + //! @copydoc ::boost::intrusive::sgtree::init_node(reference) + static void init_node(reference value); - //! Effects: Unlinks the leftmost node from the tree. - //! - //! Complexity: Average complexity is constant time. - //! - //! Throws: Nothing. - //! - //! Notes: This function breaks the tree and the tree can - //! only be used for more unlink_leftmost_without_rebalance calls. - //! This function is normally used to achieve a step by step - //! controlled destruction of the tree. - pointer unlink_leftmost_without_rebalance() - { return tree_.unlink_leftmost_without_rebalance(); } + //! @copydoc ::boost::intrusive::sgtree::unlink_leftmost_without_rebalance + pointer unlink_leftmost_without_rebalance(); - //! Requires: replace_this must be a valid iterator of *this - //! and with_this must not be inserted in any tree. - //! - //! Effects: Replaces replace_this in its position in the - //! tree with with_this. The tree does not need to be rebalanced. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This function will break container ordering invariants if - //! with_this is not equivalent to *replace_this according to the - //! ordering rules. This function is faster than erasing and inserting - //! the node, since no rebalancing or comparison is needed. - void replace_node(iterator replace_this, reference with_this) - { tree_.replace_node(replace_this, with_this); } + //! @copydoc ::boost::intrusive::sgtree::replace_node + void replace_node(iterator replace_this, reference with_this); - //! Effects: Rebalances the tree. - //! - //! Throws: Nothing. - //! - //! Complexity: Linear. - void rebalance() - { tree_.rebalance(); } + //! @copydoc ::boost::intrusive::sgtree::remove_node + void remove_node(reference value); - //! Requires: old_root is a node of a tree. - //! - //! Effects: Rebalances the subtree rooted at old_root. - //! - //! Returns: The new root of the subtree. - //! - //! Throws: Nothing. - //! - //! Complexity: Linear to the elements in the subtree. - iterator rebalance_subtree(iterator root) - { return tree_.rebalance_subtree(root); } + //! @copydoc ::boost::intrusive::sgtree::rebalance + void rebalance(); - //! Returns: The balance factor (alpha) used in this tree - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - float balance_factor() const - { return tree_.balance_factor(); } + //! @copydoc ::boost::intrusive::sgtree::rebalance_subtree + iterator rebalance_subtree(iterator root); - //! Requires: new_alpha must be a value between 0.5 and 1.0 - //! - //! Effects: Establishes a new balance factor (alpha) and rebalances - //! the tree if the new balance factor is stricter (less) than the old factor. - //! - //! Throws: Nothing. - //! - //! Complexity: Linear to the elements in the subtree. - void balance_factor(float new_alpha) - { tree_.balance_factor(new_alpha); } + //! @copydoc ::boost::intrusive::sgtree::balance_factor() + float balance_factor() const; - /// @cond - friend bool operator==(const sg_set_impl &x, const sg_set_impl &y) - { return x.tree_ == y.tree_; } + //! @copydoc ::boost::intrusive::sgtree::balance_factor(float) + void balance_factor(float new_alpha); - friend bool operator<(const sg_set_impl &x, const sg_set_impl &y) - { return x.tree_ < y.tree_; } - /// @endcond + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED }; #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator!= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const sg_set_impl &x, const sg_set_impl &y) -#else -(const sg_set_impl &x, const sg_set_impl &y) -#endif -{ return !(x == y); } -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator> -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const sg_set_impl &x, const sg_set_impl &y) -#else -(const sg_set_impl &x, const sg_set_impl &y) -#endif -{ return y < x; } +bool operator!= (const sg_set_impl &x, const sg_set_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator<= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const sg_set_impl &x, const sg_set_impl &y) -#else -(const sg_set_impl &x, const sg_set_impl &y) -#endif -{ return !(y < x); } +bool operator>(const sg_set_impl &x, const sg_set_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator>= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const sg_set_impl &x, const sg_set_impl &y) -#else -(const sg_set_impl &x, const sg_set_impl &y) -#endif -{ return !(x < y); } +bool operator<=(const sg_set_impl &x, const sg_set_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline void swap -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(sg_set_impl &x, sg_set_impl &y) -#else -(sg_set_impl &x, sg_set_impl &y) -#endif -{ x.swap(y); } +bool operator>=(const sg_set_impl &x, const sg_set_impl &y); + +template +void swap(sg_set_impl &x, sg_set_impl &y); + +#endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Helper metafunction to define a \c sg_set that yields to the same type when the //! same options (either explicitly or implicitly) are used. #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else -template +template #endif struct make_sg_set { /// @cond - typedef sg_set_impl - < typename make_sgtree_opt::type - > implementation_defined; + >::type packed_options; + + typedef typename detail::get_value_traits + ::type value_traits; + + typedef sg_set_impl + < value_traits + , typename packed_options::compare + , typename packed_options::size_type + , packed_options::floating_point + > implementation_defined; /// @endcond typedef implementation_defined type; }; #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED - #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else @@ -1296,12 +429,12 @@ template #endif class sg_set : public make_sg_set::type + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3, O4 + #else + Options... + #endif + >::type { typedef typename make_sg_set ::type Base; - BOOST_MOVABLE_BUT_NOT_COPYABLE(sg_set) + BOOST_MOVABLE_BUT_NOT_COPYABLE(sg_set) public: typedef typename Base::value_compare value_compare; typedef typename Base::value_traits value_traits; @@ -1339,7 +472,7 @@ class sg_set {} sg_set& operator=(BOOST_RV_REF(sg_set) x) - { this->Base::operator=(::boost::move(static_cast(x))); return *this; } + { return static_cast(this->Base::operator=(::boost::move(static_cast(x)))); } static sg_set &container_from_end_iterator(iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } @@ -1365,19 +498,21 @@ class sg_set //! //! The container supports the following options: //! \c base_hook<>/member_hook<>/value_traits<>, -//! \c constant_time_size<>, \c size_type<> and +//! \c floating_point<>, \c size_type<> and //! \c compare<>. #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class sg_multiset_impl +#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + : public sgtree_impl +#endif { /// @cond - typedef sgtree_impl tree_type; + typedef sgtree_impl tree_type; - //Non-copyable and non-assignable BOOST_MOVABLE_BUT_NOT_COPYABLE(sg_multiset_impl) typedef tree_type implementation_defined; /// @endcond @@ -1404,1122 +539,334 @@ class sg_multiset_impl typedef typename implementation_defined::const_node_ptr const_node_ptr; typedef typename implementation_defined::node_algorithms node_algorithms; - /// @cond - private: - tree_type tree_; - /// @endcond + static const bool constant_time_size = tree_type::constant_time_size; public: - //! Effects: Constructs an empty sg_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: If value_traits::node_traits::node - //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) - //! or the copy constructor/operator() of the value_compare object throws. + //! @copydoc ::boost::intrusive::sgtree::sgtree(const value_compare &,const value_traits &) explicit sg_multiset_impl( const value_compare &cmp = value_compare() - , const value_traits &v_traits = value_traits()) - : tree_(cmp, v_traits) + , const value_traits &v_traits = value_traits()) + : tree_type(cmp, v_traits) {} - //! Requires: Dereferencing iterator must yield an lvalue of type value_type. - //! cmp must be a comparison function that induces a strict weak ordering. - //! - //! Effects: Constructs an empty sg_multiset and inserts elements from - //! [b, e). - //! - //! Complexity: Linear in N if [b, e) is already sorted using - //! comp and otherwise N * log N, where N is the distance between first and last - //! - //! Throws: If value_traits::node_traits::node - //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) - //! or the copy constructor/operator() of the value_compare object throws. + //! @copydoc ::boost::intrusive::sgtree::sgtree(bool,Iterator,Iterator,const value_compare &,const value_traits &) template sg_multiset_impl( Iterator b, Iterator e , const value_compare &cmp = value_compare() , const value_traits &v_traits = value_traits()) - : tree_(false, b, e, cmp, v_traits) + : tree_type(false, b, e, cmp, v_traits) {} - //! Effects: to-do - //! + //! @copydoc ::boost::intrusive::sgtree::sgtree(sgtree &&) sg_multiset_impl(BOOST_RV_REF(sg_multiset_impl) x) - : tree_(::boost::move(x.tree_)) + : tree_type(::boost::move(static_cast(x))) {} - //! Effects: to-do - //! + //! @copydoc ::boost::intrusive::sgtree::operator=(sgtree &&) sg_multiset_impl& operator=(BOOST_RV_REF(sg_multiset_impl) x) - { tree_ = ::boost::move(x.tree_); return *this; } + { return static_cast(tree_type::operator=(::boost::move(static_cast(x)))); } - //! Effects: Detaches all elements from this. The objects in the sg_multiset - //! are not deleted (i.e. no destructors are called). - //! - //! Complexity: Linear to the number of elements on the container. - //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. - //! - //! Throws: Nothing. - ~sg_multiset_impl() - {} + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::sgtree::~sgtree() + ~sg_multiset_impl(); - //! Effects: Returns an iterator pointing to the beginning of the sg_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator begin() - { return tree_.begin(); } + //! @copydoc ::boost::intrusive::sgtree::begin() + iterator begin(); - //! Effects: Returns a const_iterator pointing to the beginning of the sg_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator begin() const - { return tree_.begin(); } + //! @copydoc ::boost::intrusive::sgtree::begin()const + const_iterator begin() const; - //! Effects: Returns a const_iterator pointing to the beginning of the sg_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator cbegin() const - { return tree_.cbegin(); } + //! @copydoc ::boost::intrusive::sgtree::cbegin()const + const_iterator cbegin() const; - //! Effects: Returns an iterator pointing to the end of the sg_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator end() - { return tree_.end(); } + //! @copydoc ::boost::intrusive::sgtree::end() + iterator end(); - //! Effects: Returns a const_iterator pointing to the end of the sg_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator end() const - { return tree_.end(); } + //! @copydoc ::boost::intrusive::sgtree::end()const + const_iterator end() const; - //! Effects: Returns a const_iterator pointing to the end of the sg_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator cend() const - { return tree_.cend(); } + //! @copydoc ::boost::intrusive::sgtree::cend()const + const_iterator cend() const; - //! Effects: Returns a reverse_iterator pointing to the beginning of the - //! reversed sg_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - reverse_iterator rbegin() - { return tree_.rbegin(); } + //! @copydoc ::boost::intrusive::sgtree::rbegin() + reverse_iterator rbegin(); - //! Effects: Returns a const_reverse_iterator pointing to the beginning - //! of the reversed sg_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator rbegin() const - { return tree_.rbegin(); } + //! @copydoc ::boost::intrusive::sgtree::rbegin()const + const_reverse_iterator rbegin() const; - //! Effects: Returns a const_reverse_iterator pointing to the beginning - //! of the reversed sg_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator crbegin() const - { return tree_.crbegin(); } + //! @copydoc ::boost::intrusive::sgtree::crbegin()const + const_reverse_iterator crbegin() const; - //! Effects: Returns a reverse_iterator pointing to the end - //! of the reversed sg_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - reverse_iterator rend() - { return tree_.rend(); } + //! @copydoc ::boost::intrusive::sgtree::rend() + reverse_iterator rend(); - //! Effects: Returns a const_reverse_iterator pointing to the end - //! of the reversed sg_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator rend() const - { return tree_.rend(); } + //! @copydoc ::boost::intrusive::sgtree::rend()const + const_reverse_iterator rend() const; - //! Effects: Returns a const_reverse_iterator pointing to the end - //! of the reversed sg_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator crend() const - { return tree_.crend(); } + //! @copydoc ::boost::intrusive::sgtree::crend()const + const_reverse_iterator crend() const; - //! Precondition: end_iterator must be a valid end iterator - //! of sg_multiset. - //! - //! Effects: Returns a const reference to the sg_multiset associated to the end iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - static sg_multiset_impl &container_from_end_iterator(iterator end_iterator) - { - return *detail::parent_from_member - ( &tree_type::container_from_end_iterator(end_iterator) - , &sg_multiset_impl::tree_); - } + //! @copydoc ::boost::intrusive::sgtree::container_from_end_iterator(iterator) + static sg_multiset_impl &container_from_end_iterator(iterator end_iterator); - //! Precondition: end_iterator must be a valid end const_iterator - //! of sg_multiset. - //! - //! Effects: Returns a const reference to the sg_multiset associated to the end iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - static const sg_multiset_impl &container_from_end_iterator(const_iterator end_iterator) - { - return *detail::parent_from_member - ( &tree_type::container_from_end_iterator(end_iterator) - , &sg_multiset_impl::tree_); - } + //! @copydoc ::boost::intrusive::sgtree::container_from_end_iterator(const_iterator) + static const sg_multiset_impl &container_from_end_iterator(const_iterator end_iterator); - //! Precondition: it must be a valid iterator of multiset. - //! - //! Effects: Returns a const reference to the multiset associated to the iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - static sg_multiset_impl &container_from_iterator(iterator it) - { - return *detail::parent_from_member - ( &tree_type::container_from_iterator(it) - , &sg_multiset_impl::tree_); - } + //! @copydoc ::boost::intrusive::sgtree::container_from_iterator(iterator) + static sg_multiset_impl &container_from_iterator(iterator it); - //! Precondition: it must be a valid const_iterator of multiset. - //! - //! Effects: Returns a const reference to the multiset associated to the iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - static const sg_multiset_impl &container_from_iterator(const_iterator it) - { - return *detail::parent_from_member - ( &tree_type::container_from_iterator(it) - , &sg_multiset_impl::tree_); - } + //! @copydoc ::boost::intrusive::sgtree::container_from_iterator(const_iterator) + static const sg_multiset_impl &container_from_iterator(const_iterator it); - //! Effects: Returns the key_compare object used by the sg_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: If key_compare copy-constructor throws. - key_compare key_comp() const - { return tree_.value_comp(); } + //! @copydoc ::boost::intrusive::sgtree::key_comp()const + key_compare key_comp() const; - //! Effects: Returns the value_compare object used by the sg_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: If value_compare copy-constructor throws. - value_compare value_comp() const - { return tree_.value_comp(); } + //! @copydoc ::boost::intrusive::sgtree::value_comp()const + value_compare value_comp() const; - //! Effects: Returns true if the container is empty. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - bool empty() const - { return tree_.empty(); } + //! @copydoc ::boost::intrusive::sgtree::empty()const + bool empty() const; - //! Effects: Returns the number of elements stored in the sg_multiset. - //! - //! Complexity: Linear to elements contained in *this if, - //! constant-time size option is enabled. Constant-time otherwise. - //! - //! Throws: Nothing. - size_type size() const - { return tree_.size(); } + //! @copydoc ::boost::intrusive::sgtree::size()const + size_type size() const; - //! Effects: Swaps the contents of two sg_multisets. - //! - //! Complexity: Constant. - //! - //! Throws: If the swap() call for the comparison functor - //! found using ADL throws. Strong guarantee. - void swap(sg_multiset_impl& other) - { tree_.swap(other.tree_); } + //! @copydoc ::boost::intrusive::sgtree::swap + void swap(sg_multiset_impl& other); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! Cloner should yield to nodes equivalent to the original nodes. - //! - //! Effects: Erases all the elements from *this - //! calling Disposer::operator()(pointer), clones all the - //! elements from src calling Cloner::operator()(const_reference ) - //! and inserts them on *this. Copies the predicate from the source container. - //! - //! If cloner throws, all cloned elements are unlinked and disposed - //! calling Disposer::operator()(pointer). - //! - //! Complexity: Linear to erased plus inserted elements. - //! - //! Throws: If cloner throws or predicate copy assignment throws. Basic guarantee. + //! @copydoc ::boost::intrusive::sgtree::clone_from template - void clone_from(const sg_multiset_impl &src, Cloner cloner, Disposer disposer) - { tree_.clone_from(src.tree_, cloner, disposer); } + void clone_from(const sg_multiset_impl &src, Cloner cloner, Disposer disposer); - //! Requires: value must be an lvalue - //! - //! Effects: Inserts value into the sg_multiset. - //! - //! Returns: An iterator that points to the position where the new - //! element was inserted. - //! - //! Complexity: Average complexity for insert element is at - //! most logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. Strong guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + #endif //#ifdef BOOST_iNTRUSIVE_DOXYGEN_INVOKED + + //! @copydoc ::boost::intrusive::sgtree::insert_equal(reference) iterator insert(reference value) - { return tree_.insert_equal(value); } + { return tree_type::insert_equal(value); } - //! Requires: value must be an lvalue - //! - //! Effects: Inserts x into the sg_multiset, using pos as a hint to - //! where it will be inserted. - //! - //! Returns: An iterator that points to the position where the new - //! element was inserted. - //! - //! Complexity: Logarithmic in general, but it is amortized - //! constant time if t is inserted immediately before hint. - //! - //! Throws: If the internal value_compare ordering function throws. Strong guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + //! @copydoc ::boost::intrusive::sgtree::insert_equal(const_iterator,reference) iterator insert(const_iterator hint, reference value) - { return tree_.insert_equal(hint, value); } + { return tree_type::insert_equal(hint, value); } - //! Requires: Dereferencing iterator must yield an lvalue - //! of type value_type. - //! - //! Effects: Inserts a range into the sg_multiset. - //! - //! Returns: An iterator that points to the position where the new - //! element was inserted. - //! - //! Complexity: Insert range is in general O(N * log(N)), where N is the - //! size of the range. However, it is linear in N if the range is already sorted - //! by value_comp(). - //! - //! Throws: If the internal value_compare ordering function throws. Basic guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + //! @copydoc ::boost::intrusive::sgtree::insert_equal(Iterator,Iterator) template void insert(Iterator b, Iterator e) - { tree_.insert_equal(b, e); } + { tree_type::insert_equal(b, e); } - //! Requires: value must be an lvalue, "pos" must be - //! a valid iterator (or end) and must be the succesor of value - //! once inserted according to the predicate - //! - //! Effects: Inserts x into the tree before "pos". - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Note: This function does not check preconditions so if "pos" is not - //! the successor of "value" tree ordering invariant will be broken. - //! This is a low-level function to be used only for performance reasons - //! by advanced users. - iterator insert_before(const_iterator pos, reference value) - { return tree_.insert_before(pos, value); } + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::sgtree::insert_before + iterator insert_before(const_iterator pos, reference value); - //! Requires: value must be an lvalue, and it must be no less - //! than the greatest inserted key - //! - //! Effects: Inserts x into the tree in the last position. - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Note: This function does not check preconditions so if value is - //! less than the greatest inserted key tree ordering invariant will be broken. - //! This function is slightly more efficient than using "insert_before". - //! This is a low-level function to be used only for performance reasons - //! by advanced users. - void push_back(reference value) - { tree_.push_back(value); } + //! @copydoc ::boost::intrusive::sgtree::push_back + void push_back(reference value); - //! Requires: value must be an lvalue, and it must be no greater - //! than the minimum inserted key - //! - //! Effects: Inserts x into the tree in the first position. - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Note: This function does not check preconditions so if value is - //! greater than the minimum inserted key tree ordering invariant will be broken. - //! This function is slightly more efficient than using "insert_before". - //! This is a low-level function to be used only for performance reasons - //! by advanced users. - void push_front(reference value) - { tree_.push_front(value); } + //! @copydoc ::boost::intrusive::sgtree::push_front + void push_front(reference value); - //! Effects: Erases the element pointed to by pos. - //! - //! Complexity: Average complexity is constant time. - //! - //! Returns: An iterator to the element after the erased element. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - iterator erase(const_iterator i) - { return tree_.erase(i); } + //! @copydoc ::boost::intrusive::sgtree::erase(const_iterator) + iterator erase(const_iterator i); - //! Effects: Erases the range pointed to by b end e. - //! - //! Returns: An iterator to the element after the erased elements. - //! - //! Complexity: Average complexity for erase range is at most - //! O(log(size() + N)), where N is the number of elements in the range. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - iterator erase(const_iterator b, const_iterator e) - { return tree_.erase(b, e); } + //! @copydoc ::boost::intrusive::sgtree::erase(const_iterator,const_iterator) + iterator erase(const_iterator b, const_iterator e); - //! Effects: Erases all the elements with the given value. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: O(log(size() + this->count(value)). - //! - //! Throws: If the internal value_compare ordering function throws. Basic guarantee. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - size_type erase(const_reference value) - { return tree_.erase(value); } + //! @copydoc ::boost::intrusive::sgtree::erase(const_reference) + size_type erase(const_reference value); - //! Effects: Erases all the elements that compare equal with - //! the given key and the given comparison functor. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: O(log(size() + this->count(key, comp)). - //! - //! Throws: If comp ordering function throws. Basic guarantee. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. + //! @copydoc ::boost::intrusive::sgtree::erase(const KeyType&,KeyValueCompare) template - size_type erase(const KeyType& key, KeyValueCompare comp - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) - { return tree_.erase(key, comp); } + size_type erase(const KeyType& key, KeyValueCompare comp); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Returns: An iterator to the element after the erased element. - //! - //! Effects: Erases the element pointed to by pos. - //! Disposer::operator()(pointer) is called for the removed element. - //! - //! Complexity: Average complexity for erase element is constant time. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::sgtree::erase_and_dispose(const_iterator,Disposer) template - iterator erase_and_dispose(const_iterator i, Disposer disposer) - { return tree_.erase_and_dispose(i, disposer); } + iterator erase_and_dispose(const_iterator i, Disposer disposer); - #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + //! @copydoc ::boost::intrusive::sgtree::erase_and_dispose(const_iterator,const_iterator,Disposer) template - iterator erase_and_dispose(iterator i, Disposer disposer) - { return this->erase_and_dispose(const_iterator(i), disposer); } - #endif + iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Returns: An iterator to the element after the erased elements. - //! - //! Effects: Erases the range pointed to by b end e. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Complexity: Average complexity for erase range is at most - //! O(log(size() + N)), where N is the number of elements in the range. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::sgtree::erase_and_dispose(const_reference, Disposer) template - iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer) - { return tree_.erase_and_dispose(b, e, disposer); } + size_type erase_and_dispose(const_reference value, Disposer disposer); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements with the given value. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: O(log(size() + this->count(value)). - //! - //! Throws: If the internal value_compare ordering function throws. Basic guarantee. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - template - size_type erase_and_dispose(const_reference value, Disposer disposer) - { return tree_.erase_and_dispose(value, disposer); } - - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements with the given key. - //! according to the comparison functor "comp". - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: O(log(size() + this->count(key, comp)). - //! - //! Throws: If comp ordering function throws. Basic guarantee. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::sgtree::erase_and_dispose(const KeyType&,KeyValueCompare,Disposer) template - size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) - { return tree_.erase_and_dispose(key, comp, disposer); } + size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer); - //! Effects: Erases all the elements of the container. - //! - //! Complexity: Linear to the number of elements on the container. - //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - void clear() - { return tree_.clear(); } + //! @copydoc ::boost::intrusive::sgtree::clear + void clear(); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements of the container. - //! - //! Complexity: Linear to the number of elements on the container. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. + //! @copydoc ::boost::intrusive::sgtree::clear_and_dispose template - void clear_and_dispose(Disposer disposer) - { return tree_.clear_and_dispose(disposer); } + void clear_and_dispose(Disposer disposer); - //! Effects: Returns the number of contained elements with the given key - //! - //! Complexity: Logarithmic to the number of elements contained plus lineal - //! to number of objects with the given key. - //! - //! Throws: If the internal value_compare ordering function throws. - size_type count(const_reference value) const - { return tree_.count(value); } + //! @copydoc ::boost::intrusive::sgtree::count(const_reference)const + size_type count(const_reference value) const; - //! Effects: Returns the number of contained elements with the same key - //! compared with the given comparison functor. - //! - //! Complexity: Logarithmic to the number of elements contained plus lineal - //! to number of objects with the given key. - //! - //! Throws: If comp ordering function throws. + //! @copydoc ::boost::intrusive::sgtree::count(const KeyType&,KeyValueCompare)const template - size_type count(const KeyType& key, KeyValueCompare comp) const - { return tree_.count(key, comp); } - - //! Effects: Returns an iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - iterator lower_bound(const_reference value) - { return tree_.lower_bound(value); } - - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Returns an iterator to the first element whose - //! key according to the comparison functor is not less than k or - //! end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + size_type count(const KeyType& key, KeyValueCompare comp) const; + + //! @copydoc ::boost::intrusive::sgtree::lower_bound(const_reference) + iterator lower_bound(const_reference value); + + //! @copydoc ::boost::intrusive::sgtree::lower_bound(const KeyType&,KeyValueCompare) template - iterator lower_bound(const KeyType& key, KeyValueCompare comp) - { return tree_.lower_bound(key, comp); } + iterator lower_bound(const KeyType& key, KeyValueCompare comp); - //! Effects: Returns a const iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - const_iterator lower_bound(const_reference value) const - { return tree_.lower_bound(value); } + //! @copydoc ::boost::intrusive::sgtree::lower_bound(const_reference)const + const_iterator lower_bound(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Returns a const_iterator to the first element whose - //! key according to the comparison functor is not less than k or - //! end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::sgtree::lower_bound(const KeyType&,KeyValueCompare)const template - const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const - { return tree_.lower_bound(key, comp); } + const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Returns an iterator to the first element whose - //! key is greater than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - iterator upper_bound(const_reference value) - { return tree_.upper_bound(value); } + //! @copydoc ::boost::intrusive::sgtree::upper_bound(const_reference) + iterator upper_bound(const_reference value); - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Returns an iterator to the first element whose - //! key according to the comparison functor is greater than key or - //! end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::sgtree::upper_bound(const KeyType&,KeyValueCompare) template - iterator upper_bound(const KeyType& key, KeyValueCompare comp) - { return tree_.upper_bound(key, comp); } + iterator upper_bound(const KeyType& key, KeyValueCompare comp); - //! Effects: Returns an iterator to the first element whose - //! key is greater than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - const_iterator upper_bound(const_reference value) const - { return tree_.upper_bound(value); } + //! @copydoc ::boost::intrusive::sgtree::upper_bound(const_reference)const + const_iterator upper_bound(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Returns a const_iterator to the first element whose - //! key according to the comparison functor is greater than key or - //! end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::sgtree::upper_bound(const KeyType&,KeyValueCompare)const template - const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const - { return tree_.upper_bound(key, comp); } + const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Finds an iterator to the first element whose value is - //! "value" or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - iterator find(const_reference value) - { return tree_.find(value); } + //! @copydoc ::boost::intrusive::sgtree::find(const_reference) + iterator find(const_reference value); - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Finds an iterator to the first element whose key is - //! "key" according to the comparison functor or end() if that element - //! does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::sgtree::find(const KeyType&,KeyValueCompare) template - iterator find(const KeyType& key, KeyValueCompare comp) - { return tree_.find(key, comp); } + iterator find(const KeyType& key, KeyValueCompare comp); - //! Effects: Finds a const_iterator to the first element whose value is - //! "value" or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - const_iterator find(const_reference value) const - { return tree_.find(value); } + //! @copydoc ::boost::intrusive::sgtree::find(const_reference)const + const_iterator find(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Finds a const_iterator to the first element whose key is - //! "key" according to the comparison functor or end() if that element - //! does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::sgtree::find(const KeyType&,KeyValueCompare)const template - const_iterator find(const KeyType& key, KeyValueCompare comp) const - { return tree_.find(key, comp); } + const_iterator find(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - std::pair equal_range(const_reference value) - { return tree_.equal_range(value); } + //! @copydoc ::boost::intrusive::sgtree::equal_range(const_reference) + std::pair equal_range(const_reference value); - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Finds a range containing all elements whose key is k - //! according to the comparison functor or an empty range - //! that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::sgtree::equal_range(const KeyType&,KeyValueCompare) template - std::pair equal_range(const KeyType& key, KeyValueCompare comp) - { return tree_.equal_range(key, comp); } + std::pair equal_range(const KeyType& key, KeyValueCompare comp); - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. + //! @copydoc ::boost::intrusive::sgtree::equal_range(const_reference)const std::pair - equal_range(const_reference value) const - { return tree_.equal_range(value); } + equal_range(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Finds a range containing all elements whose key is k - //! according to the comparison functor or an empty range - //! that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::sgtree::equal_range(const KeyType&,KeyValueCompare)const template std::pair - equal_range(const KeyType& key, KeyValueCompare comp) const - { return tree_.equal_range(key, comp); } + equal_range(const KeyType& key, KeyValueCompare comp) const; - //! Requires: 'lower_value' must not be greater than 'upper_value'. If - //! 'lower_value' == 'upper_value', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise - //! - //! second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the predicate throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_value and upper_value. + //! @copydoc ::boost::intrusive::sgtree::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) - { return tree_.bounded_range(lower_value, upper_value, left_closed, right_closed); } + (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); - //! Requires: KeyValueCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. - //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If - //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key, comp) if left_closed, upper_bound(lower_key, comp) otherwise - //! - //! second = upper_bound(upper_key, comp) if right_closed, lower_bound(upper_key, comp) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_key and upper_key. + //! @copydoc ::boost::intrusive::sgtree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool) template std::pair bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) - { return tree_.bounded_range(lower_key, upper_key, comp, left_closed, right_closed); } + (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed); - //! Requires: 'lower_value' must not be greater than 'upper_value'. If - //! 'lower_value' == 'upper_value', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise - //! - //! second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the predicate throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_value and upper_value. + //! @copydoc ::boost::intrusive::sgtree::bounded_range(const_reference,const_reference,bool,bool)const std::pair - bounded_range(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const - { return tree_.bounded_range(lower_value, upper_value, left_closed, right_closed); } + bounded_range(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; - //! Requires: KeyValueCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. - //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If - //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key, comp) if left_closed, upper_bound(lower_key, comp) otherwise - //! - //! second = upper_bound(upper_key, comp) if right_closed, lower_bound(upper_key, comp) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_key and upper_key. + //! @copydoc ::boost::intrusive::sgtree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const template - std::pair - bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const - { return tree_.bounded_range(lower_key, upper_key, comp, left_closed, right_closed); } + std::pair bounded_range + (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; - //! Requires: value must be an lvalue and shall be in a sg_multiset of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid iterator i belonging to the sg_multiset - //! that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This static function is available only if the value traits - //! is stateless. - static iterator s_iterator_to(reference value) - { return tree_type::s_iterator_to(value); } + //! @copydoc ::boost::intrusive::sgtree::s_iterator_to(reference) + static iterator s_iterator_to(reference value); - //! Requires: value must be an lvalue and shall be in a sg_multiset of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid const_iterator i belonging to the - //! sg_multiset that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This static function is available only if the value traits - //! is stateless. - static const_iterator s_iterator_to(const_reference value) - { return tree_type::s_iterator_to(value); } + //! @copydoc ::boost::intrusive::sgtree::s_iterator_to(const_reference) + static const_iterator s_iterator_to(const_reference value); - //! Requires: value must be an lvalue and shall be in a sg_multiset of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid iterator i belonging to the sg_multiset - //! that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator iterator_to(reference value) - { return tree_.iterator_to(value); } + //! @copydoc ::boost::intrusive::sgtree::iterator_to(reference) + iterator iterator_to(reference value); - //! Requires: value must be an lvalue and shall be in a sg_multiset of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid const_iterator i belonging to the - //! sg_multiset that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator iterator_to(const_reference value) const - { return tree_.iterator_to(value); } + //! @copydoc ::boost::intrusive::sgtree::iterator_to(const_reference)const + const_iterator iterator_to(const_reference value) const; - //! Requires: value shall not be in a sg_multiset/sg_multiset. - //! - //! Effects: init_node puts the hook of a value in a well-known default - //! state. - //! - //! Throws: Nothing. - //! - //! Complexity: Constant time. - //! - //! Note: This function puts the hook in the well-known default state - //! used by auto_unlink and safe hooks. - static void init_node(reference value) - { tree_type::init_node(value); } + //! @copydoc ::boost::intrusive::sgtree::init_node(reference) + static void init_node(reference value); - //! Effects: Unlinks the leftmost node from the tree. - //! - //! Complexity: Average complexity is constant time. - //! - //! Throws: Nothing. - //! - //! Notes: This function breaks the tree and the tree can - //! only be used for more unlink_leftmost_without_rebalance calls. - //! This function is normally used to achieve a step by step - //! controlled destruction of the tree. - pointer unlink_leftmost_without_rebalance() - { return tree_.unlink_leftmost_without_rebalance(); } + //! @copydoc ::boost::intrusive::sgtree::unlink_leftmost_without_rebalance + pointer unlink_leftmost_without_rebalance(); - //! Requires: replace_this must be a valid iterator of *this - //! and with_this must not be inserted in any tree. - //! - //! Effects: Replaces replace_this in its position in the - //! tree with with_this. The tree does not need to be rebalanced. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This function will break container ordering invariants if - //! with_this is not equivalent to *replace_this according to the - //! ordering rules. This function is faster than erasing and inserting - //! the node, since no rebalancing or comparison is needed. - void replace_node(iterator replace_this, reference with_this) - { tree_.replace_node(replace_this, with_this); } + //! @copydoc ::boost::intrusive::sgtree::replace_node + void replace_node(iterator replace_this, reference with_this); - //! Effects: Rebalances the tree. - //! - //! Throws: Nothing. - //! - //! Complexity: Linear. - void rebalance() - { tree_.rebalance(); } + //! @copydoc ::boost::intrusive::sgtree::remove_node + void remove_node(reference value); - //! Requires: old_root is a node of a tree. - //! - //! Effects: Rebalances the subtree rooted at old_root. - //! - //! Returns: The new root of the subtree. - //! - //! Throws: Nothing. - //! - //! Complexity: Linear to the elements in the subtree. - iterator rebalance_subtree(iterator root) - { return tree_.rebalance_subtree(root); } + //! @copydoc ::boost::intrusive::sgtree::rebalance + void rebalance(); - //! Returns: The balance factor (alpha) used in this tree - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - float balance_factor() const - { return tree_.balance_factor(); } + //! @copydoc ::boost::intrusive::sgtree::rebalance_subtree + iterator rebalance_subtree(iterator root); - //! Requires: new_alpha must be a value between 0.5 and 1.0 - //! - //! Effects: Establishes a new balance factor (alpha) and rebalances - //! the tree if the new balance factor is stricter (less) than the old factor. - //! - //! Throws: Nothing. - //! - //! Complexity: Linear to the elements in the subtree. - void balance_factor(float new_alpha) - { tree_.balance_factor(new_alpha); } + //! @copydoc ::boost::intrusive::sgtree::balance_factor() + float balance_factor() const; - /// @cond - friend bool operator==(const sg_multiset_impl &x, const sg_multiset_impl &y) - { return x.tree_ == y.tree_; } + //! @copydoc ::boost::intrusive::sgtree::balance_factor(float) + void balance_factor(float new_alpha); - friend bool operator<(const sg_multiset_impl &x, const sg_multiset_impl &y) - { return x.tree_ < y.tree_; } - /// @endcond + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED }; #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator!= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const sg_multiset_impl &x, const sg_multiset_impl &y) -#else -(const sg_multiset_impl &x, const sg_multiset_impl &y) -#endif -{ return !(x == y); } -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator> -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const sg_multiset_impl &x, const sg_multiset_impl &y) -#else -(const sg_multiset_impl &x, const sg_multiset_impl &y) -#endif -{ return y < x; } +bool operator!= (const sg_multiset_impl &x, const sg_multiset_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator<= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const sg_multiset_impl &x, const sg_multiset_impl &y) -#else -(const sg_multiset_impl &x, const sg_multiset_impl &y) -#endif -{ return !(y < x); } +bool operator>(const sg_multiset_impl &x, const sg_multiset_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator>= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const sg_multiset_impl &x, const sg_multiset_impl &y) -#else -(const sg_multiset_impl &x, const sg_multiset_impl &y) -#endif -{ return !(x < y); } +bool operator<=(const sg_multiset_impl &x, const sg_multiset_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline void swap -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(sg_multiset_impl &x, sg_multiset_impl &y) -#else -(sg_multiset_impl &x, sg_multiset_impl &y) -#endif -{ x.swap(y); } +bool operator>=(const sg_multiset_impl &x, const sg_multiset_impl &y); + +template +void swap(sg_multiset_impl &x, sg_multiset_impl &y); + +#endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Helper metafunction to define a \c sg_multiset that yields to the same type when the //! same options (either explicitly or implicitly) are used. #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else -template +template #endif struct make_sg_multiset { /// @cond + typedef typename pack_options + < sgtree_defaults, + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3, O4 + #else + Options... + #endif + >::type packed_options; + + typedef typename detail::get_value_traits + ::type value_traits; + typedef sg_multiset_impl - < typename make_sgtree_opt::type - > implementation_defined; + < value_traits + , typename packed_options::compare + , typename packed_options::size_type + , packed_options::floating_point + > implementation_defined; /// @endcond typedef implementation_defined type; }; @@ -2540,14 +887,14 @@ class sg_multiset #endif >::type { - typedef typename make_sg_multiset - ::type Base; + BOOST_MOVABLE_BUT_NOT_COPYABLE(sg_multiset) public: @@ -2576,7 +923,7 @@ class sg_multiset {} sg_multiset& operator=(BOOST_RV_REF(sg_multiset) x) - { this->Base::operator=(::boost::move(static_cast(x))); return *this; } + { return static_cast(this->Base::operator=(::boost::move(static_cast(x)))); } static sg_multiset &container_from_end_iterator(iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } diff --git a/include/boost/intrusive/sgtree.hpp b/include/boost/intrusive/sgtree.hpp index 91f276f..aa92da5 100644 --- a/include/boost/intrusive/sgtree.hpp +++ b/include/boost/intrusive/sgtree.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -68,6 +69,7 @@ struct h_alpha_sqrt2_t struct alpha_0_75_by_max_size_t { alpha_0_75_by_max_size_t(void){} + std::size_t operator()(std::size_t max_tree_size) const { const std::size_t max_tree_size_limit = ((~std::size_t(0))/std::size_t(3)); @@ -77,7 +79,7 @@ struct alpha_0_75_by_max_size_t struct h_alpha_t { - h_alpha_t(float inv_minus_logalpha) + explicit h_alpha_t(float inv_minus_logalpha) : inv_minus_logalpha_(inv_minus_logalpha) {} @@ -94,13 +96,13 @@ struct h_alpha_t //Since the function will be repeatedly called //precalculate constant data to avoid repeated //calls to log and division. - //This will store 1/(-std::log(alpha_)) + //This will store 1/(-std::log2(alpha_)) float inv_minus_logalpha_; }; struct alpha_by_max_size_t { - alpha_by_max_size_t(float alpha) + explicit alpha_by_max_size_t(float alpha) : alpha_(alpha) {} @@ -109,16 +111,15 @@ struct alpha_by_max_size_t private: float alpha_; - float inv_minus_logalpha_; }; -template +template struct alpha_holder { typedef boost::intrusive::detail::h_alpha_t h_alpha_t; typedef boost::intrusive::detail::alpha_by_max_size_t multiply_by_alpha_t; - alpha_holder() + alpha_holder() : max_tree_size_(0) { set_alpha(0.7f); } float get_alpha() const @@ -131,18 +132,19 @@ struct alpha_holder } h_alpha_t get_h_alpha_t() const - { return h_alpha_t(inv_minus_logalpha_); } + { return h_alpha_t(/*alpha_, */inv_minus_logalpha_); } multiply_by_alpha_t get_multiply_by_alpha_t() const { return multiply_by_alpha_t(alpha_); } - private: + protected: float alpha_; float inv_minus_logalpha_; + SizeType max_tree_size_; }; -template<> -struct alpha_holder +template +struct alpha_holder { //This specialization uses alpha = 1/sqrt(2) //without using floating point operations @@ -163,30 +165,21 @@ struct alpha_holder multiply_by_alpha_t get_multiply_by_alpha_t() const { return multiply_by_alpha_t(); } + + SizeType max_tree_size_; }; } //namespace detail{ -template -struct sg_setopt +struct sgtree_defaults { - typedef ValueTraits value_traits; - typedef Compare compare; - typedef SizeType size_type; - static const bool floating_point = FloatingPoint; + typedef detail::default_bstree_hook proto_value_traits; + static const bool constant_time_size = true; + typedef std::size_t size_type; + typedef void compare; + static const bool floating_point = true; }; -template -struct sg_set_defaults - : pack_options - < none - , base_hook - , floating_point - , size_type - , compare > - >::type -{}; - /// @endcond //! The class template sgtree is an intrusive scapegoat tree container, that @@ -205,499 +198,238 @@ struct sg_set_defaults #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class sgtree_impl - : private detail::clear_on_destructor_base > -{ - template friend class detail::clear_on_destructor_base; - public: - typedef typename Config::value_traits value_traits; /// @cond - static const bool external_value_traits = - detail::external_value_traits_bool_is_true::value; - typedef typename detail::eval_if_c - < external_value_traits - , detail::eval_value_traits - , detail::identity - >::type real_value_traits; + : public bstree_impl + , public detail::alpha_holder /// @endcond - typedef typename real_value_traits::pointer pointer; - typedef typename real_value_traits::const_pointer const_pointer; - typedef typename pointer_traits::element_type value_type; - typedef value_type key_type; - typedef typename pointer_traits::reference reference; - typedef typename pointer_traits::reference const_reference; - typedef typename pointer_traits::difference_type difference_type; - typedef typename Config::size_type size_type; - typedef typename Config::compare value_compare; - typedef value_compare key_compare; - typedef tree_iterator iterator; - typedef tree_iterator const_iterator; - typedef boost::intrusive::detail::reverse_iterator reverse_iterator; - typedef boost::intrusive::detail::reverse_iteratorconst_reverse_iterator; - typedef typename real_value_traits::node_traits node_traits; - typedef typename node_traits::node node; - typedef typename pointer_traits - ::template rebind_pointer - ::type node_ptr; - typedef typename pointer_traits - ::template rebind_pointer - ::type const_node_ptr; - typedef sgtree_algorithms node_algorithms; +{ + public: + typedef ValueTraits value_traits; + /// @cond + 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; - static const bool floating_point = Config::floating_point; - static const bool constant_time_size = true; - static const bool stateful_value_traits = detail::is_stateful_value_traits::value; + /// @endcond + + typedef typename implementation_defined::pointer pointer; + typedef typename implementation_defined::const_pointer const_pointer; + typedef typename implementation_defined::value_type value_type; + typedef typename implementation_defined::key_type key_type; + typedef typename implementation_defined::reference reference; + typedef typename implementation_defined::const_reference const_reference; + typedef typename implementation_defined::difference_type difference_type; + typedef typename implementation_defined::size_type size_type; + typedef typename implementation_defined::value_compare value_compare; + typedef typename implementation_defined::key_compare key_compare; + typedef typename implementation_defined::iterator iterator; + typedef typename implementation_defined::const_iterator const_iterator; + typedef typename implementation_defined::reverse_iterator reverse_iterator; + typedef typename implementation_defined::const_reverse_iterator const_reverse_iterator; + typedef typename implementation_defined::node_traits node_traits; + typedef typename implementation_defined::node node; + typedef typename implementation_defined::node_ptr node_ptr; + typedef typename implementation_defined::const_node_ptr const_node_ptr; + typedef BOOST_INTRUSIVE_IMPDEF(sgtree_algorithms) node_algorithms; + + static const bool constant_time_size = implementation_defined::constant_time_size; + static const bool floating_point = FloatingPoint; + static const bool stateful_value_traits = implementation_defined::stateful_value_traits; /// @cond private: - typedef detail::size_holder size_traits; - typedef detail::alpha_holder alpha_traits; - typedef typename alpha_traits::h_alpha_t h_alpha_t; - typedef typename alpha_traits::multiply_by_alpha_t multiply_by_alpha_t; //noncopyable + typedef detail::alpha_holder alpha_traits; + typedef typename alpha_traits::h_alpha_t h_alpha_t; + 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)); enum { safemode_or_autounlink = (int)real_value_traits::link_mode == (int)auto_unlink || (int)real_value_traits::link_mode == (int)safe_link }; - BOOST_STATIC_ASSERT(((int)real_value_traits::link_mode != (int)auto_unlink)); - - //BOOST_STATIC_ASSERT(( - // (int)real_value_traits::link_mode != (int)auto_unlink || - // !floating_point - // )); - - struct header_plus_alpha : public alpha_traits - { node header_; }; - - struct node_plus_pred_t : public detail::ebo_functor_holder - { - node_plus_pred_t(const value_compare &comp) - : detail::ebo_functor_holder(comp) - {} - header_plus_alpha header_plus_alpha_; - size_traits size_traits_; - }; - - struct data_t : public sgtree_impl::value_traits - { - typedef typename sgtree_impl::value_traits value_traits; - data_t(const value_compare & comp, const value_traits &val_traits) - : value_traits(val_traits), node_plus_pred_(comp) - , max_tree_size_(0) - {} - node_plus_pred_t node_plus_pred_; - size_type max_tree_size_; - } data_; - - float priv_alpha() const - { return this->priv_alpha_traits().get_alpha(); } - - void priv_alpha(float alpha) - { return this->priv_alpha_traits().set_alpha(alpha); } - - const value_compare &priv_comp() const - { return data_.node_plus_pred_.get(); } - - value_compare &priv_comp() - { return data_.node_plus_pred_.get(); } - - const value_traits &priv_value_traits() const - { return data_; } - - value_traits &priv_value_traits() - { return data_; } - - node_ptr priv_header_ptr() - { return pointer_traits::pointer_to(data_.node_plus_pred_.header_plus_alpha_.header_); } - - const_node_ptr priv_header_ptr() const - { return pointer_traits::pointer_to(data_.node_plus_pred_.header_plus_alpha_.header_); } - - static node_ptr uncast(const const_node_ptr & ptr) - { return pointer_traits::const_cast_from(ptr); } - - size_traits &priv_size_traits() - { return data_.node_plus_pred_.size_traits_; } - - const size_traits &priv_size_traits() const - { return data_.node_plus_pred_.size_traits_; } - - alpha_traits &priv_alpha_traits() - { return data_.node_plus_pred_.header_plus_alpha_; } - - const alpha_traits &priv_alpha_traits() const - { return data_.node_plus_pred_.header_plus_alpha_; } - - const real_value_traits &get_real_value_traits(detail::bool_) const - { return data_; } - - const real_value_traits &get_real_value_traits(detail::bool_) const - { return data_.get_value_traits(*this); } - - real_value_traits &get_real_value_traits(detail::bool_) - { return data_; } - - real_value_traits &get_real_value_traits(detail::bool_) - { return data_.get_value_traits(*this); } - - h_alpha_t get_h_alpha_func() const - { return priv_alpha_traits().get_h_alpha_t(); } - - multiply_by_alpha_t get_alpha_by_max_size_func() const - { return priv_alpha_traits().get_multiply_by_alpha_t(); } - /// @endcond public: - const real_value_traits &get_real_value_traits() const - { return this->get_real_value_traits(detail::bool_()); } + typedef BOOST_INTRUSIVE_IMPDEF(typename node_algorithms::insert_commit_data) insert_commit_data; - real_value_traits &get_real_value_traits() - { return this->get_real_value_traits(detail::bool_()); } - - typedef typename node_algorithms::insert_commit_data insert_commit_data; - - //! Effects: Constructs an empty tree. - //! - //! Complexity: Constant. - //! - //! Throws: If value_traits::node_traits::node - //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) - //! or the copy constructorof the value_compare object throws. Basic guarantee. - explicit sgtree_impl( const value_compare &cmp = value_compare() + //! @copydoc ::boost::intrusive::bstree::bstree(const value_compare &,const value_traits &) + explicit sgtree_impl( const value_compare &cmp = value_compare() , const value_traits &v_traits = value_traits()) - : data_(cmp, v_traits) - { - node_algorithms::init_header(this->priv_header_ptr()); - this->priv_size_traits().set_size(size_type(0)); - } + : tree_type(cmp, v_traits) + {} - //! Requires: Dereferencing iterator must yield an lvalue of type value_type. - //! cmp must be a comparison function that induces a strict weak ordering. - //! - //! Effects: Constructs an empty tree and inserts elements from - //! [b, e). - //! - //! Complexity: Linear in N if [b, e) is already sorted using - //! comp and otherwise N * log N, where N is the distance between first and last. - //! - //! Throws: If value_traits::node_traits::node - //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) - //! or the copy constructor/operator() of the value_compare object throws. Basic guarantee. + //! @copydoc ::boost::intrusive::bstree::bstree(bool,Iterator,Iterator,const value_compare &,const value_traits &) template sgtree_impl( bool unique, Iterator b, Iterator e , const value_compare &cmp = value_compare() , const value_traits &v_traits = value_traits()) - : data_(cmp, v_traits) + : tree_type(cmp, v_traits) { - node_algorithms::init_header(this->priv_header_ptr()); - this->priv_size_traits().set_size(size_type(0)); if(unique) this->insert_unique(b, e); else this->insert_equal(b, e); } - //! Effects: to-do - //! + //! @copydoc ::boost::intrusive::bstree::bstree(bstree &&) sgtree_impl(BOOST_RV_REF(sgtree_impl) x) - : data_(::boost::move(x.priv_comp()), ::boost::move(x.priv_value_traits())) - { - node_algorithms::init_header(this->priv_header_ptr()); - this->priv_size_traits().set_size(size_type(0)); - this->swap(x); - } + : tree_type(::boost::move(static_cast(x))), alpha_traits(x.get_alpha_traits()) + { std::swap(this->get_alpha_traits(), x.get_alpha_traits()); } - //! Effects: to-do - //! + //! @copydoc ::boost::intrusive::bstree::operator=(bstree &&) sgtree_impl& operator=(BOOST_RV_REF(sgtree_impl) x) - { this->swap(x); return *this; } - - //! Effects: Detaches all elements from this. The objects in the set - //! are not deleted (i.e. no destructors are called), but the nodes according to - //! the value_traits template parameter are reinitialized and thus can be reused. - //! - //! Complexity: Linear to elements contained in *this. - //! - //! Throws: Nothing. - ~sgtree_impl() - {} - - //! Effects: Returns an iterator pointing to the beginning of the tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator begin() - { return iterator (node_traits::get_left(this->priv_header_ptr()), this); } - - //! Effects: Returns a const_iterator pointing to the beginning of the tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator begin() const - { return cbegin(); } - - //! Effects: Returns a const_iterator pointing to the beginning of the tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator cbegin() const - { return const_iterator (node_traits::get_left(this->priv_header_ptr()), this); } - - //! Effects: Returns an iterator pointing to the end of the tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator end() - { return iterator (this->priv_header_ptr(), this); } - - //! Effects: Returns a const_iterator pointing to the end of the tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator end() const - { return cend(); } - - //! Effects: Returns a const_iterator pointing to the end of the tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator cend() const - { return const_iterator (uncast(this->priv_header_ptr()), this); } - - //! Effects: Returns a reverse_iterator pointing to the beginning of the - //! reversed tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - reverse_iterator rbegin() - { return reverse_iterator(end()); } - - //! Effects: Returns a const_reverse_iterator pointing to the beginning - //! of the reversed tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator rbegin() const - { return const_reverse_iterator(end()); } - - //! Effects: Returns a const_reverse_iterator pointing to the beginning - //! of the reversed tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator crbegin() const - { return const_reverse_iterator(end()); } - - //! Effects: Returns a reverse_iterator pointing to the end - //! of the reversed tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - reverse_iterator rend() - { return reverse_iterator(begin()); } - - //! Effects: Returns a const_reverse_iterator pointing to the end - //! of the reversed tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator rend() const - { return const_reverse_iterator(begin()); } - - //! Effects: Returns a const_reverse_iterator pointing to the end - //! of the reversed tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator crend() const - { return const_reverse_iterator(begin()); } - - //! Precondition: end_iterator must be a valid end iterator - //! of sgtree. - //! - //! Effects: Returns a const reference to the sgtree associated to the end iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - static sgtree_impl &container_from_end_iterator(iterator end_iterator) - { return priv_container_from_end_iterator(end_iterator); } - - //! Precondition: end_iterator must be a valid end const_iterator - //! of sgtree. - //! - //! Effects: Returns a const reference to the sgtree associated to the end iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - static const sgtree_impl &container_from_end_iterator(const_iterator end_iterator) - { return priv_container_from_end_iterator(end_iterator); } - - //! Precondition: it must be a valid iterator - //! of rbtree. - //! - //! Effects: Returns a const reference to the tree associated to the iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Logarithmic. - static sgtree_impl &container_from_iterator(iterator it) - { return priv_container_from_iterator(it); } - - //! Precondition: it must be a valid end const_iterator - //! of rbtree. - //! - //! Effects: Returns a const reference to the tree associated to the iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Logarithmic. - static const sgtree_impl &container_from_iterator(const_iterator it) - { return priv_container_from_iterator(it); } - - //! Effects: Returns the value_compare object used by the tree. - //! - //! Complexity: Constant. - //! - //! Throws: If value_compare copy-constructor throws. - value_compare value_comp() const - { return priv_comp(); } - - //! Effects: Returns true if the container is empty. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - bool empty() const - { return node_algorithms::unique(this->priv_header_ptr()); } - - //! Effects: Returns the number of elements stored in the tree. - //! - //! Complexity: Linear to elements contained in *this - //! if constant-time size option is disabled. Constant time otherwise. - //! - //! Throws: Nothing. - size_type size() const { - if(constant_time_size) - return this->priv_size_traits().get_size(); - else{ - return (size_type)node_algorithms::size(this->priv_header_ptr()); - } + this->get_alpha_traits() = x.get_alpha_traits(); + return static_cast(tree_type::operator=(::boost::move(static_cast(x)))); } - //! Effects: Swaps the contents of two sgtrees. - //! - //! Complexity: Constant. - //! - //! Throws: If the comparison functor's swap call throws. + /// @cond + private: + + const alpha_traits &get_alpha_traits() const + { return *this; } + + alpha_traits &get_alpha_traits() + { return *this; } + + h_alpha_t get_h_alpha_func() const + { return this->get_alpha_traits().get_h_alpha_t(); } + + multiply_by_alpha_t get_alpha_by_max_size_func() const + { return this->get_alpha_traits().get_multiply_by_alpha_t(); } + + /// @endcond + + public: + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::bstree::~bstree() + ~sgtree_impl(); + + //! @copydoc ::boost::intrusive::bstree::begin() + iterator begin(); + + //! @copydoc ::boost::intrusive::bstree::begin()const + const_iterator begin() const; + + //! @copydoc ::boost::intrusive::bstree::cbegin()const + const_iterator cbegin() const; + + //! @copydoc ::boost::intrusive::bstree::end() + iterator end(); + + //! @copydoc ::boost::intrusive::bstree::end()const + const_iterator end() const; + + //! @copydoc ::boost::intrusive::bstree::cend()const + const_iterator cend() const; + + //! @copydoc ::boost::intrusive::bstree::rbegin() + reverse_iterator rbegin(); + + //! @copydoc ::boost::intrusive::bstree::rbegin()const + const_reverse_iterator rbegin() const; + + //! @copydoc ::boost::intrusive::bstree::crbegin()const + const_reverse_iterator crbegin() const; + + //! @copydoc ::boost::intrusive::bstree::rend() + reverse_iterator rend(); + + //! @copydoc ::boost::intrusive::bstree::rend()const + const_reverse_iterator rend() const; + + //! @copydoc ::boost::intrusive::bstree::crend()const + const_reverse_iterator crend() const; + + //! @copydoc ::boost::intrusive::bstree::container_from_end_iterator(iterator) + static sgtree_impl &container_from_end_iterator(iterator end_iterator); + + //! @copydoc ::boost::intrusive::bstree::container_from_end_iterator(const_iterator) + static const sgtree_impl &container_from_end_iterator(const_iterator end_iterator); + + //! @copydoc ::boost::intrusive::bstree::container_from_iterator(iterator) + static sgtree_impl &container_from_iterator(iterator it); + + //! @copydoc ::boost::intrusive::bstree::container_from_iterator(const_iterator) + static const sgtree_impl &container_from_iterator(const_iterator it); + + //! @copydoc ::boost::intrusive::bstree::key_comp()const + key_compare key_comp() const; + + //! @copydoc ::boost::intrusive::bstree::value_comp()const + value_compare value_comp() const; + + //! @copydoc ::boost::intrusive::bstree::empty()const + bool empty() const; + + //! @copydoc ::boost::intrusive::bstree::size()const + size_type size() const; + + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + + //! @copydoc ::boost::intrusive::bstree::swap void swap(sgtree_impl& other) { //This can throw using std::swap; - swap(priv_comp(), priv_comp()); - swap(priv_alpha_traits(), priv_alpha_traits()); - swap(data_.max_tree_size_, other.data_.max_tree_size_); - //These can't throw - node_algorithms::swap_tree(this->priv_header_ptr(), other.priv_header_ptr()); - if(constant_time_size){ - size_type backup = this->priv_size_traits().get_size(); - this->priv_size_traits().set_size(other.priv_size_traits().get_size()); - other.priv_size_traits().set_size(backup); - } + this->tree_type::swap(static_cast(other)); + swap(this->get_alpha_traits(), other.get_alpha_traits()); } - //! Requires: value must be an lvalue - //! - //! Effects: Inserts value into the tree before the upper bound. - //! - //! Complexity: Average complexity for insert element is at - //! most logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. Strong guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + //! @copydoc ::boost::intrusive::bstree::clone_from + //! Additional notes: it also copies the alpha factor from the source container. + template + void clone_from(const sgtree_impl &src, Cloner cloner, Disposer disposer) + { + this->tree_type::clone_from(src, cloner, disposer); + this->get_alpha_traits() = src.get_alpha_traits(); + } + + //! @copydoc ::boost::intrusive::bstree::insert_equal(reference) iterator insert_equal(reference value) { - detail::key_nodeptr_comp - key_node_comp(priv_comp(), this); - node_ptr to_insert(get_real_value_traits().to_node_ptr(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)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); - std::size_t max_tree_size = (std::size_t)data_.max_tree_size_; + std::size_t max_tree_size = (std::size_t)this->max_tree_size_; node_ptr p = node_algorithms::insert_equal_upper_bound - (this->priv_header_ptr(), to_insert, key_node_comp + (this->tree_type::header_ptr(), to_insert, key_node_comp , (size_type)this->size(), this->get_h_alpha_func(), max_tree_size); - this->priv_size_traits().increment(); - data_.max_tree_size_ = (size_type)max_tree_size; - return iterator(p, this); + this->tree_type::sz_traits().increment(); + this->max_tree_size_ = (size_type)max_tree_size; + return iterator(p, this->real_value_traits_ptr()); } - //! Requires: value must be an lvalue, and "hint" must be - //! a valid iterator. - //! - //! Effects: Inserts x into the tree, using "hint" as a hint to - //! where it will be inserted. If "hint" is the upper_bound - //! the insertion takes constant time (two comparisons in the worst case) - //! - //! Complexity: Logarithmic in general, but it is amortized - //! constant time if t is inserted immediately before hint. - //! - //! Throws: Nothing. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + //! @copydoc ::boost::intrusive::bstree::insert_equal(const_iterator,reference) iterator insert_equal(const_iterator hint, reference value) { - detail::key_nodeptr_comp - key_node_comp(priv_comp(), this); - node_ptr to_insert(get_real_value_traits().to_node_ptr(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)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); - std::size_t max_tree_size = (std::size_t)data_.max_tree_size_; + std::size_t max_tree_size = (std::size_t)this->max_tree_size_; node_ptr p = node_algorithms::insert_equal - (this->priv_header_ptr(), hint.pointed_node(), to_insert, key_node_comp + (this->tree_type::header_ptr(), hint.pointed_node(), to_insert, key_node_comp , (std::size_t)this->size(), this->get_h_alpha_func(), max_tree_size); - this->priv_size_traits().increment(); - data_.max_tree_size_ = (size_type)max_tree_size; - return iterator(p, this); + this->tree_type::sz_traits().increment(); + this->max_tree_size_ = (size_type)max_tree_size; + return iterator(p, this->real_value_traits_ptr()); } - //! Requires: Dereferencing iterator must yield an lvalue - //! of type value_type. - //! - //! Effects: Inserts a each element of a range into the tree - //! before the upper bound of the key of each element. - //! - //! Complexity: Insert range is in general O(N * log(N)), where N is the - //! size of the range. However, it is linear in N if the range is already sorted - //! by value_comp(). - //! - //! Throws: Nothing. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + //! @copydoc ::boost::intrusive::bstree::insert_equal(Iterator,Iterator) template void insert_equal(Iterator b, Iterator e) { @@ -706,63 +438,69 @@ class sgtree_impl this->insert_equal(iend, *b); } - //! Requires: value must be an lvalue - //! - //! Effects: Inserts value into the tree if the value - //! is not already present. - //! - //! Complexity: Average complexity for insert element is at - //! most logarithmic. - //! - //! Throws: Nothing. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + //! @copydoc ::boost::intrusive::bstree::insert_unique(reference) std::pair insert_unique(reference value) { insert_commit_data commit_data; - std::pair ret = insert_unique_check(value, priv_comp(), commit_data); + std::pair ret = insert_unique_check(value, this->value_comp(), commit_data); if(!ret.second) return ret; return std::pair (insert_unique_commit(value, commit_data), true); } - //! Requires: value must be an lvalue, and "hint" must be - //! a valid iterator - //! - //! Effects: Tries to insert x into the tree, using "hint" as a hint - //! to where it will be inserted. - //! - //! Complexity: Logarithmic in general, but it is amortized - //! constant time (two comparisons in the worst case) - //! if t is inserted immediately before hint. - //! - //! Throws: Nothing. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + //! @copydoc ::boost::intrusive::bstree::insert_unique(const_iterator,reference) iterator insert_unique(const_iterator hint, reference value) { insert_commit_data commit_data; - std::pair ret = insert_unique_check(hint, value, priv_comp(), commit_data); + std::pair ret = insert_unique_check(hint, value, this->value_comp(), commit_data); if(!ret.second) return ret.first; return insert_unique_commit(value, commit_data); } - //! Requires: Dereferencing iterator must yield an lvalue - //! of type value_type. - //! - //! Effects: Tries to insert each element of a range into the tree. - //! - //! Complexity: Insert range is in general O(N * log(N)), where N is the - //! size of the range. However, it is linear in N if the range is already sorted - //! by value_comp(). - //! - //! Throws: Nothing. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const KeyType&,KeyValueCompare,insert_commit_data&) + template + 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()); + 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); + } + + //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const_iterator,const KeyType&,KeyValueCompare,insert_commit_data&) + template + std::pair insert_unique_check + (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()); + 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); + } + + //! @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)); + 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_; + node_algorithms::insert_unique_commit + ( this->tree_type::header_ptr(), to_insert, commit_data + , (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()); + } + + //! @copydoc ::boost::intrusive::bstree::insert_unique(Iterator,Iterator) template void insert_unique(Iterator b, Iterator e) { @@ -777,214 +515,51 @@ class sgtree_impl } } - //! Requires: key_value_comp must be a comparison function that induces - //! the same strict weak ordering as value_compare. The difference is that - //! key_value_comp compares an arbitrary key with the contained values. - //! - //! Effects: Checks if a value can be inserted in the container, using - //! a user provided key instead of the value itself. - //! - //! Returns: If there is an equivalent value - //! returns a pair containing an iterator to the already present value - //! and false. If the value can be inserted returns true in the returned - //! pair boolean and fills "commit_data" that is meant to be used with - //! the "insert_commit" function. - //! - //! Complexity: Average complexity is at most logarithmic. - //! - //! Throws: If the key_value_comp ordering function throws. Strong guarantee. - //! - //! Notes: This function is used to improve performance when constructing - //! a value_type is expensive: if there is an equivalent value - //! the constructed object must be discarded. Many times, the part of the - //! node that is used to impose the order is much cheaper to construct - //! than the value_type and this function offers the possibility to use that - //! part to check if the insertion will be successful. - //! - //! If the check is successful, the user can construct the value_type and use - //! "insert_commit" to insert the object in constant-time. This gives a total - //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)). - //! - //! "commit_data" remains valid for a subsequent "insert_commit" only if no more - //! objects are inserted or erased from the container. - template - 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); - std::pair ret = - (node_algorithms::insert_unique_check - (this->priv_header_ptr(), key, comp, commit_data)); - return std::pair(iterator(ret.first, this), ret.second); - } - - //! Requires: key_value_comp must be a comparison function that induces - //! the same strict weak ordering as value_compare. The difference is that - //! key_value_comp compares an arbitrary key with the contained values. - //! - //! Effects: Checks if a value can be inserted in the container, using - //! a user provided key instead of the value itself, using "hint" - //! as a hint to where it will be inserted. - //! - //! Returns: If there is an equivalent value - //! returns a pair containing an iterator to the already present value - //! and false. If the value can be inserted returns true in the returned - //! pair boolean and fills "commit_data" that is meant to be used with - //! the "insert_commit" function. - //! - //! Complexity: Logarithmic in general, but it's amortized - //! constant time if t is inserted immediately before hint. - //! - //! Throws: If the key_value_comp ordering function throws. Strong guarantee. - //! - //! Notes: This function is used to improve performance when constructing - //! a value_type is expensive: if there is an equivalent value - //! the constructed object must be discarded. Many times, the part of the - //! constructing that is used to impose the order is much cheaper to construct - //! than the value_type and this function offers the possibility to use that key - //! to check if the insertion will be successful. - //! - //! If the check is successful, the user can construct the value_type and use - //! "insert_commit" to insert the object in constant-time. This can give a total - //! constant-time complexity to the insertion: check(O(1)) + commit(O(1)). - //! - //! "commit_data" remains valid for a subsequent "insert_commit" only if no more - //! objects are inserted or erased from the container. - template - std::pair insert_unique_check - (const_iterator hint, const KeyType &key - ,KeyValueCompare key_value_comp, insert_commit_data &commit_data) - { - detail::key_nodeptr_comp - comp(key_value_comp, this); - std::pair ret = - (node_algorithms::insert_unique_check - (this->priv_header_ptr(), hint.pointed_node(), key, comp, commit_data)); - return std::pair(iterator(ret.first, this), ret.second); - } - - //! Requires: value must be an lvalue of type value_type. commit_data - //! must have been obtained from a previous call to "insert_check". - //! No objects should have been inserted or erased from the container between - //! the "insert_check" that filled "commit_data" and the call to "insert_commit". - //! - //! Effects: Inserts the value in the avl_set using the information obtained - //! from the "commit_data" that a previous "insert_check" filled. - //! - //! Returns: An iterator to the newly inserted object. - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Notes: This function has only sense if a "insert_check" has been - //! previously executed to fill "commit_data". No value should be inserted or - //! 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(get_real_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)data_.max_tree_size_; - node_algorithms::insert_unique_commit - ( this->priv_header_ptr(), to_insert, commit_data - , (std::size_t)this->size(), this->get_h_alpha_func(), max_tree_size); - this->priv_size_traits().increment(); - data_.max_tree_size_ = (size_type)max_tree_size; - return iterator(to_insert, this); - } - - //! Requires: value must be an lvalue, "pos" must be - //! a valid iterator (or end) and must be the succesor of value - //! once inserted according to the predicate - //! - //! Effects: Inserts x into the tree before "pos". - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Note: This function does not check preconditions so if "pos" is not - //! the successor of "value" tree ordering invariant will be broken. - //! This is a low-level function to be used only for performance reasons - //! by advanced users. + //! @copydoc ::boost::intrusive::bstree::insert_before iterator insert_before(const_iterator pos, reference value) { - node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + node_ptr to_insert(this->get_real_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)data_.max_tree_size_; + std::size_t max_tree_size = (std::size_t)this->max_tree_size_; node_ptr p = node_algorithms::insert_before - ( this->priv_header_ptr(), pos.pointed_node(), to_insert + ( this->tree_type::header_ptr(), pos.pointed_node(), to_insert , (size_type)this->size(), this->get_h_alpha_func(), max_tree_size); - this->priv_size_traits().increment(); - data_.max_tree_size_ = (size_type)max_tree_size; - return iterator(p, this); + this->tree_type::sz_traits().increment(); + this->max_tree_size_ = (size_type)max_tree_size; + return iterator(p, this->real_value_traits_ptr()); } - //! Requires: value must be an lvalue, and it must be no less - //! than the greatest inserted key - //! - //! Effects: Inserts x into the tree in the last position. - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Note: This function does not check preconditions so if value is - //! less than the greatest inserted key tree ordering invariant will be broken. - //! This function is slightly more efficient than using "insert_before". - //! This is a low-level function to be used only for performance reasons - //! by advanced users. + //! @copydoc ::boost::intrusive::bstree::push_back void push_back(reference value) { - node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + node_ptr to_insert(this->get_real_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)data_.max_tree_size_; + std::size_t max_tree_size = (std::size_t)this->max_tree_size_; node_algorithms::push_back - ( this->priv_header_ptr(), to_insert + ( this->tree_type::header_ptr(), to_insert , (size_type)this->size(), this->get_h_alpha_func(), max_tree_size); - this->priv_size_traits().increment(); - data_.max_tree_size_ = (size_type)max_tree_size; + this->tree_type::sz_traits().increment(); + this->max_tree_size_ = (size_type)max_tree_size; } - //! Requires: value must be an lvalue, and it must be no greater - //! than the minimum inserted key - //! - //! Effects: Inserts x into the tree in the first position. - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Note: This function does not check preconditions so if value is - //! greater than the minimum inserted key tree ordering invariant will be broken. - //! This function is slightly more efficient than using "insert_before". - //! This is a low-level function to be used only for performance reasons - //! by advanced users. + //! @copydoc ::boost::intrusive::bstree::push_front void push_front(reference value) { - node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + node_ptr to_insert(this->get_real_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)data_.max_tree_size_; + std::size_t max_tree_size = (std::size_t)this->max_tree_size_; node_algorithms::push_front - ( this->priv_header_ptr(), to_insert + ( this->tree_type::header_ptr(), to_insert , (size_type)this->size(), this->get_h_alpha_func(), max_tree_size); - this->priv_size_traits().increment(); - data_.max_tree_size_ = (size_type)max_tree_size; + this->tree_type::sz_traits().increment(); + this->max_tree_size_ = (size_type)max_tree_size; } - //! Effects: Erases the element pointed to by pos. - //! - //! Complexity: Average complexity for erase element is constant time. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. + + //! @copydoc ::boost::intrusive::bstree::erase(const_iterator) iterator erase(const_iterator i) { const_iterator ret(i); @@ -992,53 +567,26 @@ class sgtree_impl node_ptr to_erase(i.pointed_node()); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!node_algorithms::unique(to_erase)); - std::size_t max_tree_size = data_.max_tree_size_; + std::size_t max_tree_size = this->max_tree_size_; node_algorithms::erase - ( this->priv_header_ptr(), to_erase, (std::size_t)this->size() + ( this->tree_type::header_ptr(), to_erase, (std::size_t)this->size() , max_tree_size, this->get_alpha_by_max_size_func()); - data_.max_tree_size_ = (size_type)max_tree_size; - this->priv_size_traits().decrement(); + this->max_tree_size_ = (size_type)max_tree_size; + this->tree_type::sz_traits().decrement(); if(safemode_or_autounlink) node_algorithms::init(to_erase); return ret.unconst(); } - //! Effects: Erases the range pointed to by b end e. - //! - //! Complexity: Average complexity for erase range is at most - //! O(log(size() + N)), where N is the number of elements in the range. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. + //! @copydoc ::boost::intrusive::bstree::erase(const_iterator,const_iterator) iterator erase(const_iterator b, const_iterator e) { size_type n; return private_erase(b, e, n); } - //! Effects: Erases all the elements with the given value. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: O(log(size() + N). - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. + //! @copydoc ::boost::intrusive::bstree::erase(const_reference) size_type erase(const_reference value) - { return this->erase(value, priv_comp()); } + { return this->erase(value, this->value_comp()); } - //! Effects: Erases all the elements with the given key. - //! according to the comparison functor "comp". - //! - //! Returns: The number of erased elements. - //! - //! Complexity: O(log(size() + N). - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. + //! @copydoc ::boost::intrusive::bstree::erase(const KeyType&,KeyValueCompare) template size_type erase(const KeyType& key, KeyValueCompare comp /// @cond @@ -1052,23 +600,13 @@ class sgtree_impl return n; } - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases the element pointed to by pos. - //! Disposer::operator()(pointer) is called for the removed element. - //! - //! Complexity: Average complexity for erase element is constant time. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_iterator,Disposer) template iterator erase_and_dispose(const_iterator i, Disposer disposer) { node_ptr to_erase(i.pointed_node()); iterator ret(this->erase(i)); - disposer(get_real_value_traits().to_value_ptr(to_erase)); + disposer(this->get_real_value_traits().to_value_ptr(to_erase)); return ret; } @@ -1078,35 +616,12 @@ class sgtree_impl { return this->erase_and_dispose(const_iterator(i), disposer); } #endif - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases the range pointed to by b end e. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Complexity: Average complexity for erase range is at most - //! O(log(size() + N)), where N is the number of elements in the range. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_iterator,const_iterator,Disposer) template iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer) { size_type n; return private_erase(b, e, n, disposer); } - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements with the given value. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: O(log(size() + N). - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. + //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_reference, Disposer) template size_type erase_and_dispose(const_reference value, Disposer disposer) { @@ -1116,20 +631,7 @@ class sgtree_impl return n; } - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements with the given key. - //! according to the comparison functor "comp". - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: O(log(size() + N). - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const KeyType&,KeyValueCompare,Disposer) template size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer /// @cond @@ -1143,535 +645,136 @@ class sgtree_impl return n; } - //! Effects: Erases all of the elements. - //! - //! Complexity: Linear to the number of elements on the container. - //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. + //! @copydoc ::boost::intrusive::bstree::clear void clear() { - if(safemode_or_autounlink){ - this->clear_and_dispose(detail::null_disposer()); - } - else{ - node_algorithms::init_header(this->priv_header_ptr()); - this->priv_size_traits().set_size(0); - } + tree_type::clear(); + this->max_tree_size_ = 0; } - //! Effects: Erases all of the elements calling disposer(p) for - //! each node to be erased. - //! Complexity: Average complexity for is at most O(log(size() + N)), - //! where N is the number of elements in the container. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. Calls N times to disposer functor. + //! @copydoc ::boost::intrusive::bstree::clear_and_dispose template void clear_and_dispose(Disposer disposer) { - node_algorithms::clear_and_dispose(this->priv_header_ptr() - , detail::node_disposer(disposer, this)); - this->priv_size_traits().set_size(0); + tree_type::clear_and_dispose(disposer); + this->max_tree_size_ = 0; } - //! Effects: Returns the number of contained elements with the given value - //! - //! Complexity: Logarithmic to the number of elements contained plus lineal - //! to number of objects with the given value. - //! - //! Throws: Nothing. - size_type count(const_reference value) const - { return this->count(value, priv_comp()); } + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::bstree::count(const_reference)const + size_type count(const_reference value) const; - //! Effects: Returns the number of contained elements with the given key - //! - //! Complexity: Logarithmic to the number of elements contained plus lineal - //! to number of objects with the given key. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const template - size_type count(const KeyType &key, KeyValueCompare comp) const - { - std::pair ret = this->equal_range(key, comp); - return std::distance(ret.first, ret.second); - } - - //! Effects: Returns an iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - iterator lower_bound(const_reference value) - { return this->lower_bound(value, priv_comp()); } - - //! Effects: Returns an iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - const_iterator lower_bound(const_reference value) const - { return this->lower_bound(value, priv_comp()); } - - //! Effects: Returns an iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + size_type count(const KeyType& key, KeyValueCompare comp) const; + + //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference) + iterator lower_bound(const_reference value); + + //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare) template - iterator lower_bound(const KeyType &key, KeyValueCompare comp) - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - return iterator(node_algorithms::lower_bound - (this->priv_header_ptr(), key, key_node_comp), this); - } + iterator lower_bound(const KeyType& key, KeyValueCompare comp); - //! Effects: Returns a const iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference)const + const_iterator lower_bound(const_reference value) const; + + //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare)const template - const_iterator lower_bound(const KeyType &key, KeyValueCompare comp) const - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - return const_iterator(node_algorithms::lower_bound - (this->priv_header_ptr(), key, key_node_comp), this); - } + const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Returns an iterator to the first element whose - //! key is greater than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - iterator upper_bound(const_reference value) - { return this->upper_bound(value, priv_comp()); } + //! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference) + iterator upper_bound(const_reference value); - //! Effects: Returns an iterator to the first element whose - //! key is greater than k according to comp or end() if that element - //! does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare) template - iterator upper_bound(const KeyType &key, KeyValueCompare comp) - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - return iterator(node_algorithms::upper_bound - (this->priv_header_ptr(), key, key_node_comp), this); - } + iterator upper_bound(const KeyType& key, KeyValueCompare comp); - //! Effects: Returns an iterator to the first element whose - //! key is greater than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - const_iterator upper_bound(const_reference value) const - { return this->upper_bound(value, priv_comp()); } + //! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference)const + const_iterator upper_bound(const_reference value) const; - //! Effects: Returns an iterator to the first element whose - //! key is greater than k according to comp or end() if that element - //! does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare)const template - const_iterator upper_bound(const KeyType &key, KeyValueCompare comp) const - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - return const_iterator(node_algorithms::upper_bound - (this->priv_header_ptr(), key, key_node_comp), this); - } + const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Finds an iterator to the first element whose key is - //! k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - iterator find(const_reference value) - { return this->find(value, priv_comp()); } + //! @copydoc ::boost::intrusive::bstree::find(const_reference) + iterator find(const_reference value); - //! Effects: Finds an iterator to the first element whose key is - //! k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare) template - iterator find(const KeyType &key, KeyValueCompare comp) - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - return iterator - (node_algorithms::find(this->priv_header_ptr(), key, key_node_comp), this); - } + iterator find(const KeyType& key, KeyValueCompare comp); - //! Effects: Finds a const_iterator to the first element whose key is - //! k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - const_iterator find(const_reference value) const - { return this->find(value, priv_comp()); } + //! @copydoc ::boost::intrusive::bstree::find(const_reference)const + const_iterator find(const_reference value) const; - //! Effects: Finds a const_iterator to the first element whose key is - //! k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare)const template - const_iterator find(const KeyType &key, KeyValueCompare comp) const - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - return const_iterator - (node_algorithms::find(this->priv_header_ptr(), key, key_node_comp), this); - } + const_iterator find(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - std::pair equal_range(const_reference value) - { return this->equal_range(value, priv_comp()); } + //! @copydoc ::boost::intrusive::bstree::equal_range(const_reference) + std::pair equal_range(const_reference value); - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare) template - std::pair equal_range(const KeyType &key, KeyValueCompare comp) - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - std::pair ret - (node_algorithms::equal_range(this->priv_header_ptr(), key, key_node_comp)); - return std::pair(iterator(ret.first, this), iterator(ret.second, this)); - } + std::pair equal_range(const KeyType& key, KeyValueCompare comp); - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::equal_range(const_reference)const std::pair - equal_range(const_reference value) const - { return this->equal_range(value, priv_comp()); } + equal_range(const_reference value) const; - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare)const template std::pair - equal_range(const KeyType &key, KeyValueCompare comp) const - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - std::pair ret - (node_algorithms::equal_range(this->priv_header_ptr(), key, key_node_comp)); - return std::pair(const_iterator(ret.first, this), const_iterator(ret.second, this)); - } + equal_range(const KeyType& key, KeyValueCompare comp) const; - //! Requires: 'lower_value' must not be greater than 'upper_value'. If - //! 'lower_value' == 'upper_value', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise - //! - //! second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the predicate throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_value and upper_value. + //! @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) - { return this->bounded_range(lower_value, upper_value, priv_comp(), left_closed, right_closed); } + (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); - //! Requires: KeyValueCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. - //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If - //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key, comp) if left_closed, upper_bound(lower_key, comp) otherwise - //! - //! second = upper_bound(upper_key, comp) if right_closed, lower_bound(upper_key, comp) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_key and upper_key. + //! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool) template std::pair bounded_range - (const KeyType &lower_key, const KeyType &upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - std::pair ret - (node_algorithms::bounded_range - (this->priv_header_ptr(), lower_key, upper_key, key_node_comp, left_closed, right_closed)); - return std::pair(iterator(ret.first, this), iterator(ret.second, this)); - } + (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed); - //! Requires: 'lower_value' must not be greater than 'upper_value'. If - //! 'lower_value' == 'upper_value', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise - //! - //! second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the predicate throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_value and upper_value. - std::pair bounded_range - (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const - { return this->bounded_range(lower_value, upper_value, priv_comp(), left_closed, right_closed); } + //! @copydoc ::boost::intrusive::bstree::bounded_range(const_reference,const_reference,bool,bool)const + std::pair + bounded_range(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; - //! Requires: KeyValueCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. - //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If - //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key, comp) if left_closed, upper_bound(lower_key, comp) otherwise - //! - //! second = upper_bound(upper_key, comp) if right_closed, lower_bound(upper_key, comp) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_key and upper_key. + //! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const template - std::pair bounded_range - (const KeyType &lower_key, const KeyType &upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - std::pair ret - (node_algorithms::bounded_range - (this->priv_header_ptr(), lower_key, upper_key, key_node_comp, left_closed, right_closed)); - return std::pair(const_iterator(ret.first, this), const_iterator(ret.second, this)); - } + std::pair bounded_range + (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! Cloner should yield to nodes equivalent to the original nodes. - //! - //! Effects: Erases all the elements from *this - //! calling Disposer::operator()(pointer), clones all the - //! elements from src calling Cloner::operator()(const_reference ) - //! and inserts them on *this. Copies the predicate from the source container. - //! - //! If cloner throws, all cloned elements are unlinked and disposed - //! calling Disposer::operator()(pointer). - //! - //! Complexity: Linear to erased plus inserted elements. - //! - //! Throws: If cloner throws or predicate copy assignment throws. Basic guarantee. - template - void clone_from(const sgtree_impl &src, Cloner cloner, Disposer disposer) - { - this->clear_and_dispose(disposer); - if(!src.empty()){ - detail::exception_disposer - rollback(*this, disposer); - node_algorithms::clone - (src.priv_header_ptr() - ,this->priv_header_ptr() - ,detail::node_cloner(cloner, this) - ,detail::node_disposer(disposer, this)); - this->priv_size_traits().set_size(src.priv_size_traits().get_size()); - this->priv_comp() = src.priv_comp(); - rollback.release(); - } - } + //! @copydoc ::boost::intrusive::bstree::s_iterator_to(reference) + static iterator s_iterator_to(reference value); - //! Effects: Unlinks the leftmost node from the tree. - //! - //! Complexity: Average complexity is constant time. - //! - //! Throws: Nothing. - //! - //! Notes: This function breaks the tree and the tree can - //! only be used for more unlink_leftmost_without_rebalance calls. - //! This function is normally used to achieve a step by step - //! controlled destruction of the tree. - pointer unlink_leftmost_without_rebalance() - { - node_ptr to_be_disposed(node_algorithms::unlink_leftmost_without_rebalance - (this->priv_header_ptr())); - if(!to_be_disposed) - return 0; - this->priv_size_traits().decrement(); - if(safemode_or_autounlink)//If this is commented does not work with normal_link - node_algorithms::init(to_be_disposed); - return get_real_value_traits().to_value_ptr(to_be_disposed); - } + //! @copydoc ::boost::intrusive::bstree::s_iterator_to(const_reference) + static const_iterator s_iterator_to(const_reference value); - //! Requires: replace_this must be a valid iterator of *this - //! and with_this must not be inserted in any tree. - //! - //! Effects: Replaces replace_this in its position in the - //! tree with with_this. The tree does not need to be rebalanced. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This function will break container ordering invariants if - //! with_this is not equivalent to *replace_this according to the - //! ordering rules. This function is faster than erasing and inserting - //! the node, since no rebalancing or comparison is needed. - void replace_node(iterator replace_this, reference with_this) - { - node_algorithms::replace_node( get_real_value_traits().to_node_ptr(*replace_this) - , this->priv_header_ptr() - , get_real_value_traits().to_node_ptr(with_this)); - if(safemode_or_autounlink) - node_algorithms::init(replace_this.pointed_node()); - } + //! @copydoc ::boost::intrusive::bstree::iterator_to(reference) + iterator iterator_to(reference value); - //! Requires: value must be an lvalue and shall be in a set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid iterator i belonging to the set - //! that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This static function is available only if the value traits - //! is stateless. - static iterator s_iterator_to(reference value) - { - BOOST_STATIC_ASSERT((!stateful_value_traits)); - return iterator (value_traits::to_node_ptr(value), 0); - } + //! @copydoc ::boost::intrusive::bstree::iterator_to(const_reference)const + const_iterator iterator_to(const_reference value) const; - //! Requires: value must be an lvalue and shall be in a set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid const_iterator i belonging to the - //! set that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This static function is available only if the value traits - //! is stateless. - static const_iterator s_iterator_to(const_reference value) - { - BOOST_STATIC_ASSERT((!stateful_value_traits)); - return const_iterator (value_traits::to_node_ptr(const_cast (value)), 0); - } + //! @copydoc ::boost::intrusive::bstree::init_node(reference) + static void init_node(reference value); - //! Requires: value must be an lvalue and shall be in a set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid iterator i belonging to the set - //! that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator iterator_to(reference value) - { return iterator (value_traits::to_node_ptr(value), this); } + //! @copydoc ::boost::intrusive::bstree::unlink_leftmost_without_rebalance + pointer unlink_leftmost_without_rebalance(); - //! Requires: value must be an lvalue and shall be in a set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid const_iterator i belonging to the - //! set that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator iterator_to(const_reference value) const - { return const_iterator (value_traits::to_node_ptr(const_cast (value)), this); } + //! @copydoc ::boost::intrusive::bstree::replace_node + void replace_node(iterator replace_this, reference with_this); - //! Requires: value shall not be in a tree. - //! - //! Effects: init_node puts the hook of a value in a well-known default - //! state. - //! - //! Throws: Nothing. - //! - //! Complexity: Constant time. - //! - //! Note: This function puts the hook in the well-known default state - //! used by auto_unlink and safe hooks. - static void init_node(reference value) - { node_algorithms::init(value_traits::to_node_ptr(value)); } + //! @copydoc ::boost::intrusive::bstree::remove_node + void remove_node(reference value); - //! Effects: Rebalances the tree. - //! - //! Throws: Nothing. - //! - //! Complexity: Linear. - void rebalance() - { node_algorithms::rebalance(this->priv_header_ptr()); } + //! @copydoc ::boost::intrusive::bstree::rebalance + void rebalance(); - //! Requires: old_root is a node of a tree. - //! - //! Effects: Rebalances the subtree rooted at old_root. - //! - //! Returns: The new root of the subtree. - //! - //! Throws: Nothing. - //! - //! Complexity: Linear to the elements in the subtree. - iterator rebalance_subtree(iterator root) - { return iterator(node_algorithms::rebalance_subtree(root.pointed_node()), this); } + //! @copydoc ::boost::intrusive::bstree::rebalance_subtree + iterator rebalance_subtree(iterator root); + + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! Returns: The balance factor (alpha) used in this tree //! @@ -1679,7 +782,7 @@ class sgtree_impl //! //! Complexity: Constant. float balance_factor() const - { return this->priv_alpha(); } + { return this->get_alpha_traits().get_alpha(); } //! Requires: new_alpha must be a value between 0.5 and 1.0 //! @@ -1697,41 +800,14 @@ class sgtree_impl //The alpha factor CAN't be changed if the fixed, floating operation-less //1/sqrt(2) alpha factor option is activated BOOST_STATIC_ASSERT((floating_point)); - float old_alpha = this->priv_alpha(); - this->priv_alpha(new_alpha); + float old_alpha = this->get_alpha_traits().get_alpha(); + this->get_alpha_traits().set_alpha(new_alpha); if(new_alpha < old_alpha){ - data_.max_tree_size_ = this->size(); + this->max_tree_size_ = this->size(); this->rebalance(); } } -/* - //! Effects: removes x from a tree of the appropriate type. It has no effect, - //! if x is not in such a tree. - //! - //! Throws: Nothing. - //! - //! Complexity: Constant time. - //! - //! Note: This static function is only usable with the "safe mode" - //! hook and non-constant time size lists. Otherwise, the user must use - //! the non-static "erase(reference )" member. If the user calls - //! this function with a non "safe mode" or constant time size list - //! a compilation error will be issued. - template - static void remove_node(T& value) - { - //This function is only usable for safe mode hooks and non-constant - //time lists. - //BOOST_STATIC_ASSERT((!(safemode_or_autounlink && constant_time_size))); - BOOST_STATIC_ASSERT((!constant_time_size)); - BOOST_STATIC_ASSERT((boost::is_convertible::value)); - node_ptr to_remove(value_traits::to_node_ptr(value)); - node_algorithms::unlink_and_rebalance(to_remove); - if(safemode_or_autounlink) - node_algorithms::init(to_remove); - } -*/ /// @cond private: @@ -1750,193 +826,69 @@ class sgtree_impl return b.unconst(); } /// @endcond - - private: - static sgtree_impl &priv_container_from_end_iterator(const const_iterator &end_iterator) - { - header_plus_alpha *r = detail::parent_from_member - ( boost::intrusive::detail::to_raw_pointer(end_iterator.pointed_node()), &header_plus_alpha::header_); - node_plus_pred_t *n = detail::parent_from_member - (r, &node_plus_pred_t::header_plus_alpha_); - data_t *d = detail::parent_from_member(n, &data_t::node_plus_pred_); - sgtree_impl *scapegoat = detail::parent_from_member(d, &sgtree_impl::data_); - return *scapegoat; - } - - static sgtree_impl &priv_container_from_iterator(const const_iterator &it) - { return priv_container_from_end_iterator(it.end_iterator_from_it()); } }; #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + template -#else -template -#endif -inline bool operator< -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const sgtree_impl &x, const sgtree_impl &y) -#else -(const sgtree_impl &x, const sgtree_impl &y) -#endif -{ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } +bool operator< (const sgtree_impl &x, const sgtree_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -bool operator== -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const sgtree_impl &x, const sgtree_impl &y) -#else -(const sgtree_impl &x, const sgtree_impl &y) -#endif -{ - typedef sgtree_impl tree_type; - typedef typename tree_type::const_iterator const_iterator; +bool operator==(const sgtree_impl &x, const sgtree_impl &y); - if(tree_type::constant_time_size && x.size() != y.size()){ - return false; - } - const_iterator end1 = x.end(); - const_iterator i1 = x.begin(); - const_iterator i2 = y.begin(); - if(tree_type::constant_time_size){ - while (i1 != end1 && *i1 == *i2) { - ++i1; - ++i2; - } - return i1 == end1; - } - else{ - const_iterator end2 = y.end(); - while (i1 != end1 && i2 != end2 && *i1 == *i2) { - ++i1; - ++i2; - } - return i1 == end1 && i2 == end2; - } -} - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator!= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const sgtree_impl &x, const sgtree_impl &y) -#else -(const sgtree_impl &x, const sgtree_impl &y) -#endif -{ return !(x == y); } +bool operator!= (const sgtree_impl &x, const sgtree_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator> -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const sgtree_impl &x, const sgtree_impl &y) -#else -(const sgtree_impl &x, const sgtree_impl &y) -#endif -{ return y < x; } +bool operator>(const sgtree_impl &x, const sgtree_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator<= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const sgtree_impl &x, const sgtree_impl &y) -#else -(const sgtree_impl &x, const sgtree_impl &y) -#endif -{ return !(y < x); } +bool operator<=(const sgtree_impl &x, const sgtree_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator>= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const sgtree_impl &x, const sgtree_impl &y) -#else -(const sgtree_impl &x, const sgtree_impl &y) -#endif -{ return !(x < y); } +bool operator>=(const sgtree_impl &x, const sgtree_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline void swap -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(sgtree_impl &x, sgtree_impl &y) -#else -(sgtree_impl &x, sgtree_impl &y) -#endif -{ x.swap(y); } +void swap(sgtree_impl &x, sgtree_impl &y); -/// @cond -#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) -template -#else -template -#endif -struct make_sgtree_opt -{ - typedef typename pack_options - < sg_set_defaults, - #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - O1, O2, O3, O4 - #else - Options... - #endif - >::type packed_options; - typedef typename detail::get_value_traits - ::type value_traits; - - typedef sg_setopt - < value_traits - , typename packed_options::compare - , typename packed_options::size_type - , packed_options::floating_point - > type; -}; -/// @endcond +#endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Helper metafunction to define a \c sgtree that yields to the same type when the //! same options (either explicitly or implicitly) are used. #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else -template +template #endif struct make_sgtree { /// @cond + typedef typename pack_options + < sgtree_defaults, + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3, O4 + #else + Options... + #endif + >::type packed_options; + + typedef typename detail::get_value_traits + ::type value_traits; + typedef sgtree_impl - < typename make_sgtree_opt::type - > implementation_defined; + < value_traits + , typename packed_options::compare + , typename packed_options::size_type + , packed_options::floating_point + > implementation_defined; /// @endcond typedef implementation_defined type; }; + #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else @@ -1944,22 +896,21 @@ template #endif class sgtree : public make_sgtree::type { typedef typename make_sgtree ::type Base; - BOOST_MOVABLE_BUT_NOT_COPYABLE(sgtree) public: @@ -1968,6 +919,8 @@ class sgtree 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)); @@ -1989,18 +942,23 @@ class sgtree {} sgtree& operator=(BOOST_RV_REF(sgtree) x) - { this->Base::operator=(::boost::move(static_cast(x))); return *this; } + { return static_cast(this->Base::operator=(::boost::move(static_cast(x)))); } static sgtree &container_from_end_iterator(iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } static const sgtree &container_from_end_iterator(const_iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } + + static sgtree &container_from_iterator(iterator it) + { return static_cast(Base::container_from_iterator(it)); } + + static const sgtree &container_from_iterator(const_iterator it) + { return static_cast(Base::container_from_iterator(it)); } }; #endif - } //namespace intrusive } //namespace boost diff --git a/include/boost/intrusive/sgtree_algorithms.hpp b/include/boost/intrusive/sgtree_algorithms.hpp index bad1c32..a52bbbb 100644 --- a/include/boost/intrusive/sgtree_algorithms.hpp +++ b/include/boost/intrusive/sgtree_algorithms.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include @@ -36,7 +36,7 @@ namespace intrusive { //! //! Typedefs: //! -//! node: The type of the node that forms the circular list +//! node: The type of the node that forms the binary search tree //! //! node_ptr: A pointer to a node //! @@ -57,6 +57,9 @@ namespace intrusive { //! static void set_right(node_ptr n, node_ptr right); template class sgtree_algorithms + #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + : public bstree_algorithms + #endif { public: typedef typename NodeTraits::node node; @@ -67,490 +70,194 @@ class sgtree_algorithms /// @cond private: - typedef detail::tree_algorithms tree_algorithms; + typedef bstree_algorithms bstree_algorithms; - static node_ptr uncast(const const_node_ptr & ptr) - { return pointer_traits::const_cast_from(ptr); } /// @endcond public: - static node_ptr begin_node(const const_node_ptr & header) - { return tree_algorithms::begin_node(header); } - - static node_ptr end_node(const const_node_ptr & header) - { return tree_algorithms::end_node(header); } - //! This type is the information that will be //! filled by insert_unique_check struct insert_commit_data - : tree_algorithms::insert_commit_data + : bstree_algorithms::insert_commit_data { std::size_t depth; }; - //! Requires: header1 and header2 must be the header nodes - //! of two trees. - //! - //! Effects: Swaps two trees. After the function header1 will contain - //! links to the second tree and header2 will have links to the first tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - static void swap_tree(const node_ptr & header1, const node_ptr & header2) - { return tree_algorithms::swap_tree(header1, header2); } + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::bstree_algorithms::get_header(const const_node_ptr&) + static node_ptr get_header(const const_node_ptr & n); - //! Requires: node1 and node2 can't be header nodes - //! of two trees. - //! - //! Effects: Swaps two nodes. After the function node1 will be inserted - //! in the position node2 before the function. node2 will be inserted in the - //! position node1 had before the function. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - //! - //! Note: This function will break container ordering invariants if - //! node1 and node2 are not equivalent according to the ordering rules. - //! - //!Experimental function - static void swap_nodes(const node_ptr & node1, const node_ptr & node2) - { - if(node1 == node2) - return; + //! @copydoc ::boost::intrusive::bstree_algorithms::begin_node + static node_ptr begin_node(const const_node_ptr & header); - node_ptr header1(tree_algorithms::get_header(node1)), header2(tree_algorithms::get_header(node2)); - swap_nodes(node1, header1, node2, header2); - } + //! @copydoc ::boost::intrusive::bstree_algorithms::end_node + static node_ptr end_node(const const_node_ptr & header); - //! Requires: node1 and node2 can't be header nodes - //! of two trees with header header1 and header2. - //! - //! Effects: Swaps two nodes. After the function node1 will be inserted - //! in the position node2 before the function. node2 will be inserted in the - //! position node1 had before the function. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This function will break container ordering invariants if - //! node1 and node2 are not equivalent according to the ordering rules. - //! - //!Experimental function - static void swap_nodes(const node_ptr & node1, const node_ptr & header1, const node_ptr & node2, const node_ptr & header2) - { tree_algorithms::swap_nodes(node1, header1, node2, header2); } + //! @copydoc ::boost::intrusive::bstree_algorithms::swap_tree + static void swap_tree(const node_ptr & header1, const node_ptr & header2); - //! Requires: node_to_be_replaced must be inserted in a tree - //! and new_node must not be inserted in a tree. - //! - //! Effects: Replaces node_to_be_replaced in its position in the - //! tree with new_node. The tree does not need to be rebalanced - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - //! - //! Note: This function will break container ordering invariants if - //! new_node is not equivalent to node_to_be_replaced according to the - //! ordering rules. This function is faster than erasing and inserting - //! the node, since no rebalancing and comparison is needed. - //! - //!Experimental function - static void replace_node(const node_ptr & node_to_be_replaced, const node_ptr & new_node) - { - if(node_to_be_replaced == new_node) - return; - replace_node(node_to_be_replaced, tree_algorithms::get_header(node_to_be_replaced), new_node); - } + //! @copydoc ::boost::intrusive::bstree_algorithms::swap_nodes(const node_ptr&,const node_ptr&) + static void swap_nodes(const node_ptr & node1, const node_ptr & node2); - //! Requires: node_to_be_replaced must be inserted in a tree - //! with header "header" and new_node must not be inserted in a tree. - //! - //! Effects: Replaces node_to_be_replaced in its position in the - //! tree with new_node. The tree does not need to be rebalanced - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This function will break container ordering invariants if - //! new_node is not equivalent to node_to_be_replaced according to the - //! ordering rules. This function is faster than erasing and inserting - //! the node, since no rebalancing or comparison is needed. - //! - //!Experimental function - static void replace_node(const node_ptr & node_to_be_replaced, const node_ptr & header, const node_ptr & new_node) - { tree_algorithms::replace_node(node_to_be_replaced, header, new_node); } + //! @copydoc ::boost::intrusive::bstree_algorithms::swap_nodes(const node_ptr&,const node_ptr&,const node_ptr&,const node_ptr&) + static void swap_nodes(const node_ptr & node1, const node_ptr & header1, const node_ptr & node2, const node_ptr & header2); - //! Requires: node is a tree node but not the header. - //! - //! Effects: Unlinks the node and rebalances the tree. - //! - //! Complexity: Average complexity is constant time. - //! - //! Throws: Nothing. - static void unlink(const node_ptr & node) - { - node_ptr x = NodeTraits::get_parent(node); - if(x){ - while(!is_header(x)) - x = NodeTraits::get_parent(x); - tree_algorithms::erase(x, node); - } - } + //! @copydoc ::boost::intrusive::bstree_algorithms::replace_node(const node_ptr&,const node_ptr&) + static void replace_node(const node_ptr & node_to_be_replaced, const node_ptr & new_node); - //! Requires: header is the header of a tree. - //! - //! Effects: Unlinks the leftmost node from the tree, and - //! updates the header link to the new leftmost node. - //! - //! Complexity: Average complexity is constant time. - //! - //! Throws: Nothing. - //! - //! Notes: This function breaks the tree and the tree can - //! only be used for more unlink_leftmost_without_rebalance calls. - //! This function is normally used to achieve a step by step - //! controlled destruction of the tree. - static node_ptr unlink_leftmost_without_rebalance(const node_ptr & header) - { return tree_algorithms::unlink_leftmost_without_rebalance(header); } + //! @copydoc ::boost::intrusive::bstree_algorithms::replace_node(const node_ptr&,const node_ptr&,const node_ptr&) + static void replace_node(const node_ptr & node_to_be_replaced, const node_ptr & header, const node_ptr & new_node); - //! Requires: node is a node of the tree or an node initialized - //! by init(...). - //! - //! Effects: Returns true if the node is initialized by init(). - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - static bool unique(const const_node_ptr & node) - { return tree_algorithms::unique(node); } + //Unlink is not possible since tree metadata is needed to update the tree + //!static void unlink(const node_ptr & node); - //! Requires: node is a node of the tree but it's not the header. - //! - //! Effects: Returns the number of nodes of the subtree. - //! - //! Complexity: Linear time. - //! - //! Throws: Nothing. - static std::size_t count(const const_node_ptr & node) - { return tree_algorithms::count(node); } + //! @copydoc ::boost::intrusive::bstree_algorithms::unlink_leftmost_without_rebalance + static node_ptr unlink_leftmost_without_rebalance(const node_ptr & header); - //! Requires: header is the header node of the tree. - //! - //! Effects: Returns the number of nodes above the header. - //! - //! Complexity: Linear time. - //! - //! Throws: Nothing. - static std::size_t size(const const_node_ptr & header) - { return tree_algorithms::size(header); } + //! @copydoc ::boost::intrusive::bstree_algorithms::unique(const const_node_ptr&) + static bool unique(const const_node_ptr & node); - //! Requires: p is a node from the tree except the header. - //! - //! Effects: Returns the next node of the tree. - //! - //! Complexity: Average constant time. - //! - //! Throws: Nothing. - static node_ptr next_node(const node_ptr & p) - { return tree_algorithms::next_node(p); } + //! @copydoc ::boost::intrusive::bstree_algorithms::size(const const_node_ptr&) + static std::size_t size(const const_node_ptr & header); - //! Requires: p is a node from the tree except the leftmost node. - //! - //! Effects: Returns the previous node of the tree. - //! - //! Complexity: Average constant time. - //! - //! Throws: Nothing. - static node_ptr prev_node(const node_ptr & p) - { return tree_algorithms::prev_node(p); } + //! @copydoc ::boost::intrusive::bstree_algorithms::next_node(const node_ptr&) + static node_ptr next_node(const node_ptr & node); - //! Requires: node must not be part of any tree. - //! - //! Effects: After the function unique(node) == true. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Nodes: If node is inserted in a tree, this function corrupts the tree. - static void init(const node_ptr & node) - { tree_algorithms::init(node); } + //! @copydoc ::boost::intrusive::bstree_algorithms::prev_node(const node_ptr&) + static node_ptr prev_node(const node_ptr & node); - //! Requires: node must not be part of any tree. - //! - //! Effects: Initializes the header to represent an empty tree. - //! unique(header) == true. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Nodes: If node is inserted in a tree, this function corrupts the tree. - static void init_header(const node_ptr & header) - { tree_algorithms::init_header(header); } + //! @copydoc ::boost::intrusive::bstree_algorithms::init(const node_ptr&) + static void init(const node_ptr & node); - //! Requires: header must be the header of a tree, z a node - //! of that tree and z != header. - //! - //! Effects: Erases node "z" from the tree with header "header". - //! - //! Complexity: Amortized constant time. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree_algorithms::init_header(const node_ptr&) + static void init_header(const node_ptr & header); + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + + //! @copydoc ::boost::intrusive::bstree_algorithms::erase(const node_ptr&,const node_ptr&) template static node_ptr erase(const node_ptr & header, const node_ptr & z, std::size_t tree_size, std::size_t &max_tree_size, AlphaByMaxSize alpha_by_maxsize) { - //typename tree_algorithms::data_for_rebalance info; - tree_algorithms::erase(header, z); + //typename bstree_algorithms::data_for_rebalance info; + bstree_algorithms::erase(header, z); --tree_size; if (tree_size > 0 && tree_size < alpha_by_maxsize(max_tree_size)){ - tree_algorithms::rebalance(header); + bstree_algorithms::rebalance(header); max_tree_size = tree_size; } return z; } - //! Requires: "cloner" must be a function - //! object taking a node_ptr and returning a new cloned node of it. "disposer" must - //! take a node_ptr and shouldn't throw. - //! - //! Effects: First empties target tree calling - //! void disposer::operator()(const node_ptr &) for every node of the tree - //! except the header. - //! - //! Then, duplicates the entire tree pointed by "source_header" cloning each - //! source node with node_ptr Cloner::operator()(const node_ptr &) to obtain - //! the nodes of the target tree. If "cloner" throws, the cloned target nodes - //! are disposed using void disposer(const node_ptr &). - //! - //! Complexity: Linear to the number of element of the source tree plus the. - //! number of elements of tree target tree when calling this function. - //! - //! Throws: If cloner functor throws. If this happens target nodes are disposed. + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::bstree_algorithms::clone(const const_node_ptr&,const node_ptr&,Cloner,Disposer) template static void clone - (const const_node_ptr & source_header, const node_ptr & target_header, Cloner cloner, Disposer disposer) - { - tree_algorithms::clone(source_header, target_header, cloner, disposer); - } + (const const_node_ptr & source_header, const node_ptr & target_header, Cloner cloner, Disposer disposer); - //! Requires: "disposer" must be an object function - //! taking a node_ptr parameter and shouldn't throw. - //! - //! Effects: Empties the target tree calling - //! void disposer::operator()(const node_ptr &) for every node of the tree - //! except the header. - //! - //! Complexity: Linear to the number of element of the source tree plus the. - //! number of elements of tree target tree when calling this function. - //! - //! Throws: If cloner functor throws. If this happens target nodes are disposed. + //! @copydoc ::boost::intrusive::bstree_algorithms::clear_and_dispose(const node_ptr&,Disposer) template - static void clear_and_dispose(const node_ptr & header, Disposer disposer) - { tree_algorithms::clear_and_dispose(header, disposer); } + static void clear_and_dispose(const node_ptr & header, Disposer disposer); - //! 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 an node_ptr to the first element that is - //! not less than "key" according to "comp" or "header" if that element does - //! not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. + //! @copydoc ::boost::intrusive::bstree_algorithms::lower_bound(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) template static node_ptr lower_bound - (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) - { return tree_algorithms::lower_bound(header, key, comp); } + (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp); - //! 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 an node_ptr to the first element that is greater - //! than "key" according to "comp" or "header" if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. + //! @copydoc ::boost::intrusive::bstree_algorithms::upper_bound(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) template static node_ptr upper_bound - (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) - { return tree_algorithms::upper_bound(header, key, comp); } + (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp); - //! 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 an node_ptr to the element that is equivalent to - //! "key" according to "comp" or "header" if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. + //! @copydoc ::boost::intrusive::bstree_algorithms::find(const const_node_ptr&, const KeyType&,KeyNodePtrCompare) template static node_ptr find - (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) - { return tree_algorithms::find(header, key, comp); } + (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp); - //! 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 an a pair of node_ptr delimiting a range containing - //! all elements that are equivalent to "key" according to "comp" or an - //! empty range that indicates the position where those elements would be - //! if they there are no equivalent elements. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. + //! @copydoc ::boost::intrusive::bstree_algorithms::equal_range(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) template static std::pair equal_range - (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) - { return tree_algorithms::equal_range(header, key, comp); } + (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp); - //! 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. - //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If - //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise - //! - //! second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_key and upper_key. + //! @copydoc ::boost::intrusive::bstree_algorithms::bounded_range(const const_node_ptr&,const KeyType&,const KeyType&,KeyNodePtrCompare,bool,bool) template static std::pair bounded_range (const const_node_ptr & header, const KeyType &lower_key, const KeyType &upper_key, KeyNodePtrCompare comp - , bool left_closed, bool right_closed) - { return tree_algorithms::bounded_range(header, lower_key, upper_key, comp, left_closed, right_closed); } + , bool left_closed, bool right_closed); - //! Requires: "h" must be the header node of a tree. - //! NodePtrCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. NodePtrCompare compares two node_ptrs. - //! - //! Effects: Inserts new_node into the tree before the upper bound - //! according to "comp". - //! - //! Complexity: Average complexity for insert element is at - //! most logarithmic. - //! - //! Throws: If "comp" throws. + //! @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) template static node_ptr insert_equal_upper_bound (const node_ptr & h, const node_ptr & new_node, NodePtrCompare comp ,std::size_t tree_size, H_Alpha h_alpha, std::size_t &max_tree_size) { std::size_t depth; - tree_algorithms::insert_equal_upper_bound(h, new_node, comp, &depth); + bstree_algorithms::insert_equal_upper_bound(h, new_node, comp, &depth); rebalance_after_insertion(new_node, depth, tree_size+1, h_alpha, max_tree_size); return new_node; } - //! Requires: "h" must be the header node of a tree. - //! NodePtrCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. NodePtrCompare compares two node_ptrs. - //! - //! Effects: Inserts new_node into the tree before the lower bound - //! according to "comp". - //! - //! Complexity: Average complexity for insert element is at - //! most logarithmic. - //! - //! Throws: If "comp" throws. + //! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal_lower_bound(const node_ptr&,const node_ptr&,NodePtrCompare) template static node_ptr insert_equal_lower_bound (const node_ptr & h, const node_ptr & new_node, NodePtrCompare comp ,std::size_t tree_size, H_Alpha h_alpha, std::size_t &max_tree_size) { std::size_t depth; - tree_algorithms::insert_equal_lower_bound(h, new_node, comp, &depth); + bstree_algorithms::insert_equal_lower_bound(h, new_node, comp, &depth); rebalance_after_insertion(new_node, depth, tree_size+1, h_alpha, max_tree_size); return new_node; } - //! Requires: "header" must be the header node of a tree. - //! NodePtrCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. NodePtrCompare compares two node_ptrs. "hint" is node from - //! the "header"'s tree. - //! - //! Effects: Inserts new_node into the tree, using "hint" as a hint to - //! where it will be inserted. If "hint" is the upper_bound - //! the insertion takes constant time (two comparisons in the worst case). - //! - //! Complexity: Logarithmic in general, but it is amortized - //! constant time if new_node is inserted immediately before "hint". - //! - //! Throws: If "comp" throws. + //! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal(const node_ptr&,const node_ptr&,const node_ptr&,NodePtrCompare) template static node_ptr insert_equal (const node_ptr & header, const node_ptr & hint, const node_ptr & new_node, NodePtrCompare comp ,std::size_t tree_size, H_Alpha h_alpha, std::size_t &max_tree_size) { std::size_t depth; - tree_algorithms::insert_equal(header, hint, new_node, comp, &depth); + bstree_algorithms::insert_equal(header, hint, new_node, comp, &depth); rebalance_after_insertion(new_node, depth, tree_size+1, h_alpha, max_tree_size); return new_node; } - //! 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. NodePtrCompare compares KeyType with a node_ptr. - //! - //! Effects: Checks if there is an equivalent node to "key" in the - //! tree according to "comp" and obtains the needed information to realize - //! a constant-time node insertion if there is no equivalent node. - //! - //! Returns: If there is an equivalent value - //! returns a pair containing a node_ptr to the already present node - //! and false. If there is not equivalent key can be inserted returns true - //! in the returned pair's boolean and fills "commit_data" that is meant to - //! be used with the "insert_commit" function to achieve a constant-time - //! insertion function. - //! - //! Complexity: Average complexity is at most logarithmic. - //! - //! Throws: If "comp" throws. - //! - //! Notes: This function is used to improve performance when constructing - //! a node is expensive and the user does not want to have two equivalent nodes - //! in the tree: if there is an equivalent value - //! the constructed object must be discarded. Many times, the part of the - //! node that is used to impose the order is much cheaper to construct - //! than the node and this function offers the possibility to use that part - //! to check if the insertion will be successful. - //! - //! If the check is successful, the user can construct the node and use - //! "insert_commit" to insert the node in constant-time. This gives a total - //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)). - //! - //! "commit_data" remains valid for a subsequent "insert_unique_commit" only - //! if no more objects are inserted or erased from the set. + //! @copydoc ::boost::intrusive::bstree_algorithms::insert_before(const node_ptr&,const node_ptr&,const node_ptr&) + template + static node_ptr insert_before + (const node_ptr & header, const node_ptr & pos, const node_ptr & new_node + ,std::size_t tree_size, H_Alpha h_alpha, std::size_t &max_tree_size) + { + std::size_t depth; + bstree_algorithms::insert_before(header, pos, new_node, &depth); + rebalance_after_insertion(new_node, depth, tree_size+1, h_alpha, max_tree_size); + return new_node; + } + + //! @copydoc ::boost::intrusive::bstree_algorithms::push_back(const node_ptr&,const node_ptr&) + template + static void push_back(const node_ptr & header, const node_ptr & new_node + ,std::size_t tree_size, H_Alpha h_alpha, std::size_t &max_tree_size) + { + std::size_t depth; + bstree_algorithms::push_back(header, new_node, &depth); + rebalance_after_insertion(new_node, depth, tree_size+1, h_alpha, max_tree_size); + } + + //! @copydoc ::boost::intrusive::bstree_algorithms::push_front(const node_ptr&,const node_ptr&) + template + static void push_front(const node_ptr & header, const node_ptr & new_node + ,std::size_t tree_size, H_Alpha h_alpha, std::size_t &max_tree_size) + { + std::size_t depth; + bstree_algorithms::push_front(header, new_node, &depth); + rebalance_after_insertion(new_node, depth, tree_size+1, h_alpha, max_tree_size); + } + + //! @copydoc ::boost::intrusive::bstree_algorithms::insert_unique_check(const const_node_ptr&,const KeyType&,KeyNodePtrCompare,insert_commit_data&) template static std::pair insert_unique_check (const const_node_ptr & header, const KeyType &key @@ -558,120 +265,12 @@ class sgtree_algorithms { std::size_t depth; std::pair ret = - tree_algorithms::insert_unique_check(header, key, comp, commit_data, &depth); + bstree_algorithms::insert_unique_check(header, key, comp, commit_data, &depth); commit_data.depth = depth; return ret; } - - //! Requires: "header" must be the header node of a tree. - //! "pos" must be a valid iterator or header (end) node. - //! "pos" must be an iterator pointing to the successor to "new_node" - //! once inserted according to the order of already inserted nodes. This function does not - //! check "pos" and this precondition must be guaranteed by the caller. - //! - //! Effects: Inserts new_node into the tree before "pos". - //! - //! Complexity: Constant-time. - //! - //! Throws: Nothing. - //! - //! Note: If "pos" is not the successor of the newly inserted "new_node" - //! tree invariants might be broken. - template - static node_ptr insert_before - (const node_ptr & header, const node_ptr & pos, const node_ptr & new_node - ,std::size_t tree_size, H_Alpha h_alpha, std::size_t &max_tree_size) - { - std::size_t depth; - tree_algorithms::insert_before(header, pos, new_node, &depth); - rebalance_after_insertion(new_node, depth, tree_size+1, h_alpha, max_tree_size); - return new_node; - } - - //! Requires: "header" must be the header node of a tree. - //! "new_node" must be, according to the used ordering no less than the - //! greatest inserted key. - //! - //! Effects: Inserts new_node into the tree before "pos". - //! - //! Complexity: Constant-time. - //! - //! Throws: Nothing. - //! - //! Note: If "new_node" is less than the greatest inserted key - //! tree invariants are broken. This function is slightly faster than - //! using "insert_before". - template - static void push_back(const node_ptr & header, const node_ptr & new_node - ,std::size_t tree_size, H_Alpha h_alpha, std::size_t &max_tree_size) - { - std::size_t depth; - tree_algorithms::push_back(header, new_node, &depth); - rebalance_after_insertion(new_node, depth, tree_size+1, h_alpha, max_tree_size); - } - - //! Requires: "header" must be the header node of a tree. - //! "new_node" must be, according to the used ordering, no greater than the - //! lowest inserted key. - //! - //! Effects: Inserts new_node into the tree before "pos". - //! - //! Complexity: Constant-time. - //! - //! Throws: Nothing. - //! - //! Note: If "new_node" is greater than the lowest inserted key - //! tree invariants are broken. This function is slightly faster than - //! using "insert_before". - template - static void push_front(const node_ptr & header, const node_ptr & new_node - ,std::size_t tree_size, H_Alpha h_alpha, std::size_t &max_tree_size) - { - std::size_t depth; - tree_algorithms::push_front(header, new_node, &depth); - rebalance_after_insertion(new_node, depth, tree_size+1, h_alpha, max_tree_size); - } - - //! 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. NodePtrCompare compares KeyType with a node_ptr. - //! "hint" is node from the "header"'s tree. - //! - //! Effects: Checks if there is an equivalent node to "key" in the - //! tree according to "comp" using "hint" as a hint to where it should be - //! inserted and obtains the needed information to realize - //! a constant-time node insertion if there is no equivalent node. - //! If "hint" is the upper_bound the function has constant time - //! complexity (two comparisons in the worst case). - //! - //! Returns: If there is an equivalent value - //! returns a pair containing a node_ptr to the already present node - //! and false. If there is not equivalent key can be inserted returns true - //! in the returned pair's boolean and fills "commit_data" that is meant to - //! be used with the "insert_commit" function to achieve a constant-time - //! insertion function. - //! - //! Complexity: Average complexity is at most logarithmic, but it is - //! amortized constant time if new_node should be inserted immediately before "hint". - //! - //! Throws: If "comp" throws. - //! - //! Notes: This function is used to improve performance when constructing - //! a node is expensive and the user does not want to have two equivalent nodes - //! in the tree: if there is an equivalent value - //! the constructed object must be discarded. Many times, the part of the - //! node that is used to impose the order is much cheaper to construct - //! than the node and this function offers the possibility to use that part - //! to check if the insertion will be successful. - //! - //! If the check is successful, the user can construct the node and use - //! "insert_commit" to insert the node in constant-time. This gives a total - //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)). - //! - //! "commit_data" remains valid for a subsequent "insert_unique_commit" only - //! if no more objects are inserted or erased from the set. + //! @copydoc ::boost::intrusive::bstree_algorithms::insert_unique_check(const const_node_ptr&,const node_ptr&,const KeyType&,KeyNodePtrCompare,insert_commit_data&) template static std::pair insert_unique_check (const const_node_ptr & header, const node_ptr &hint, const KeyType &key @@ -679,83 +278,36 @@ class sgtree_algorithms { std::size_t depth; std::pair ret = - tree_algorithms::insert_unique_check + bstree_algorithms::insert_unique_check (header, hint, key, comp, commit_data, &depth); commit_data.depth = depth; return ret; } - //! Requires: "header" must be the header node of a tree. - //! "commit_data" must have been obtained from a previous call to - //! "insert_unique_check". No objects should have been inserted or erased - //! from the set between the "insert_unique_check" that filled "commit_data" - //! and the call to "insert_commit". - //! - //! - //! Effects: Inserts new_node in the set using the information obtained - //! from the "commit_data" that a previous "insert_check" filled. - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Notes: This function has only sense if a "insert_unique_check" has been - //! previously executed to fill "commit_data". No value should be inserted or - //! erased between the "insert_check" and "insert_commit" calls. + //! @copydoc ::boost::intrusive::bstree_algorithms::insert_unique_commit(const node_ptr&,const node_ptr&,const insert_commit_data&) template static void insert_unique_commit (const node_ptr & header, const node_ptr & new_value, const insert_commit_data &commit_data ,std::size_t tree_size, H_Alpha h_alpha, std::size_t &max_tree_size) { - tree_algorithms::insert_unique_commit(header, new_value, commit_data); + bstree_algorithms::insert_unique_commit(header, new_value, commit_data); rebalance_after_insertion(new_value, commit_data.depth, tree_size+1, h_alpha, max_tree_size); } - //! Requires: header must be the header of a tree. - //! - //! Effects: Rebalances the tree. - //! - //! Throws: Nothing. - //! - //! Complexity: Linear. - static void rebalance(const node_ptr & header) - { tree_algorithms::rebalance(header); } + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::bstree_algorithms::is_header + static bool is_header(const const_node_ptr & p); - //! Requires: old_root is a node of a tree. - //! - //! Effects: Rebalances the subtree rooted at old_root. - //! - //! Returns: The new root of the subtree. - //! - //! Throws: Nothing. - //! - //! Complexity: Linear. + //! @copydoc ::boost::intrusive::bstree_algorithms::is_header + static void rebalance(const node_ptr & header); + + //! @copydoc ::boost::intrusive::bstree_algorithms::rebalance_subtree static node_ptr rebalance_subtree(const node_ptr & old_root) - { return tree_algorithms::rebalance_subtree(old_root); } - - //! Requires: "n" must be a node inserted in a tree. - //! - //! Effects: Returns a pointer to the header node of the tree. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - static node_ptr get_header(const node_ptr & n) - { return tree_algorithms::get_header(n); } + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED /// @cond private: - //! Requires: p is a node of a tree. - //! - //! Effects: Returns true if p is the header of the tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - static bool is_header(const const_node_ptr & p) - { return tree_algorithms::is_header(p); } - template static void rebalance_after_insertion (const node_ptr &x, std::size_t depth @@ -764,7 +316,12 @@ class sgtree_algorithms if(tree_size > max_tree_size) max_tree_size = tree_size; - if(tree_size != 1 && depth > h_alpha(tree_size)){ + if(tree_size > 2 && //Nothing to do with only the root + //Check if the root node is unbalanced + //Scapegoat paper depth counts root depth as zero and "depth" counts root as 1, + //but since "depth" is the depth of the ancestor of x, i == depth + depth > h_alpha(tree_size)){ + //Find the first non height-balanced node //as described in the section 4.2 of the paper. //This method is the alternative method described @@ -773,32 +330,40 @@ class sgtree_algorithms //than the weight balanced method. node_ptr s = x; std::size_t size = 1; - - for(std::size_t i = 1; true; ++i){ - bool rebalance = false; - if(i == depth){ - BOOST_INTRUSIVE_INVARIANT_ASSERT(tree_size == count(s)); - rebalance = true; - } - else if(i > h_alpha(size)){ - node_ptr s_parent = NodeTraits::get_parent(s); - node_ptr s_parent_left = NodeTraits::get_left(s_parent); - size += 1 + tree_algorithms::count - ( s_parent_left == s ? NodeTraits::get_right(s_parent) : s_parent_left ); - s = s_parent; - rebalance = true; - } - if(rebalance){ - rebalance_subtree(s); + for(std::size_t ancestor = 1; true; ++ancestor){ + if(ancestor == depth){ //Check if whole tree must be rebuilt + max_tree_size = tree_size; + bstree_algorithms::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_algorithms::subtree_size(s_sibling); + s = s_parent; + if(ancestor > h_alpha(size)){ //is 's' scapegoat? + bstree_algorithms::rebalance_subtree(s); + break; + } + } } } } - /// @endcond }; +/// @cond + +template +struct get_algo +{ + typedef sgtree_algorithms type; +}; + +/// @endcond + } //namespace intrusive } //namespace boost diff --git a/include/boost/intrusive/slist.hpp b/include/boost/intrusive/slist.hpp index bee6ac7..ac7301a 100644 --- a/include/boost/intrusive/slist.hpp +++ b/include/boost/intrusive/slist.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 @@ -38,16 +38,6 @@ namespace intrusive { /// @cond -template -struct slistopt -{ - typedef ValueTraits value_traits; - typedef SizeType size_type; - static const bool constant_time_size = ConstantTimeSize; - static const bool linear = Linear; - static const bool cache_last = CacheLast; -}; - template struct root_plus_last { @@ -61,17 +51,22 @@ struct root_plus_last Node root_; }; -template struct slist_defaults - : pack_options - < none - , base_hook - , constant_time_size - , linear - , size_type - , cache_last - >::type -{}; +{ + typedef detail::default_slist_hook proto_value_traits; + static const bool constant_time_size = true; + static const bool linear = false; + typedef std::size_t size_type; + static const bool cache_last = false; +}; + +struct slist_bool_flags +{ + static const std::size_t linear_pos = 1u; + static const std::size_t constant_time_size_pos = 2u; + static const std::size_t cache_last_pos = 4u; +}; + /// @endcond @@ -101,23 +96,19 @@ struct slist_defaults #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class slist_impl - : private detail::clear_on_destructor_base > + : private detail::clear_on_destructor_base > { template friend class detail::clear_on_destructor_base; //Public typedefs public: - typedef typename Config::value_traits value_traits; + typedef ValueTraits value_traits; /// @cond static const bool external_value_traits = detail::external_value_traits_bool_is_true::value; - typedef typename detail::eval_if_c - < external_value_traits - , detail::eval_value_traits - , detail::identity - >::type real_value_traits; + typedef typename detail::get_real_value_traits::type real_value_traits; /// @endcond typedef typename real_value_traits::pointer pointer; typedef typename real_value_traits::const_pointer const_pointer; @@ -125,25 +116,25 @@ class slist_impl typedef typename pointer_traits::reference reference; typedef typename pointer_traits::reference const_reference; typedef typename pointer_traits::difference_type difference_type; - typedef typename Config::size_type size_type; - typedef slist_iterator iterator; - typedef slist_iterator const_iterator; + typedef SizeType size_type; + typedef slist_iterator iterator; + typedef slist_iterator const_iterator; typedef typename real_value_traits::node_traits node_traits; typedef typename node_traits::node node; typedef typename node_traits::node_ptr node_ptr; typedef typename node_traits::const_node_ptr const_node_ptr; + static const bool constant_time_size = 0 != (BoolFlags & slist_bool_flags::constant_time_size_pos); + static const bool stateful_value_traits = detail::is_stateful_value_traits::value; + static const bool linear = 0 != (BoolFlags & slist_bool_flags::linear_pos); + static const bool cache_last = 0 != (BoolFlags & slist_bool_flags::cache_last_pos); + typedef typename detail::if_c - < Config::linear + < linear , linear_slist_algorithms , circular_slist_algorithms >::type node_algorithms; - static const bool constant_time_size = Config::constant_time_size; - static const bool stateful_value_traits = detail::is_stateful_value_traits::value; - static const bool linear = Config::linear; - static const bool cache_last = Config::cache_last; - /// @cond private: typedef detail::size_holder size_traits; @@ -151,9 +142,7 @@ class slist_impl //noncopyable BOOST_MOVABLE_BUT_NOT_COPYABLE(slist_impl) - enum { safemode_or_autounlink = - (int)real_value_traits::link_mode == (int)auto_unlink || - (int)real_value_traits::link_mode == (int)safe_link }; + 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))); @@ -207,9 +196,6 @@ class slist_impl void set_last_node(const node_ptr & n, detail::bool_) { data_.root_plus_size_.last_ = n; } - static node_ptr uncast(const const_node_ptr & ptr) - { return pointer_traits::const_cast_from(ptr); } - void set_default_constructed_state() { node_algorithms::init_header(this->get_root_node()); @@ -279,6 +265,11 @@ class slist_impl real_value_traits &get_real_value_traits() { return this->get_real_value_traits(detail::bool_()); } + typedef typename pointer_traits::template rebind_pointer::type const_real_value_traits_ptr; + + const_real_value_traits_ptr real_value_traits_ptr() const + { return pointer_traits::pointer_to(this->get_real_value_traits()); } + public: ///@cond @@ -511,7 +502,7 @@ class slist_impl //! //! Complexity: Constant. const_reference front() const - { return *this->get_real_value_traits().to_value_ptr(uncast(node_traits::get_next(this->get_root_node()))); } + { return *this->get_real_value_traits().to_value_ptr(detail::uncast(node_traits::get_next(this->get_root_node()))); } //! Effects: Returns a reference to the last element of the list. //! @@ -547,7 +538,7 @@ class slist_impl //! //! Complexity: Constant. iterator begin() - { return iterator (node_traits::get_next(this->get_root_node()), this); } + { return iterator (node_traits::get_next(this->get_root_node()), this->real_value_traits_ptr()); } //! Effects: Returns a const_iterator to the first element contained in the list. //! @@ -555,7 +546,7 @@ class slist_impl //! //! Complexity: Constant. const_iterator begin() const - { return const_iterator (node_traits::get_next(this->get_root_node()), this); } + { return const_iterator (node_traits::get_next(this->get_root_node()), this->real_value_traits_ptr()); } //! Effects: Returns a const_iterator to the first element contained in the list. //! @@ -563,7 +554,7 @@ class slist_impl //! //! Complexity: Constant. const_iterator cbegin() const - { return const_iterator(node_traits::get_next(this->get_root_node()), this); } + { return const_iterator(node_traits::get_next(this->get_root_node()), this->real_value_traits_ptr()); } //! Effects: Returns an iterator to the end of the list. //! @@ -571,7 +562,7 @@ class slist_impl //! //! Complexity: Constant. iterator end() - { return iterator(this->get_end_node(), this); } + { return iterator(this->get_end_node(), this->real_value_traits_ptr()); } //! Effects: Returns a const_iterator to the end of the list. //! @@ -579,7 +570,7 @@ class slist_impl //! //! Complexity: Constant. const_iterator end() const - { return const_iterator(uncast(this->get_end_node()), this); } + { return const_iterator(detail::uncast(this->get_end_node()), this->real_value_traits_ptr()); } //! Effects: Returns a const_iterator to the end of the list. //! @@ -596,7 +587,7 @@ class slist_impl //! //! Complexity: Constant. iterator before_begin() - { return iterator(this->get_root_node(), this); } + { return iterator(this->get_root_node(), this->real_value_traits_ptr()); } //! Effects: Returns an iterator that points to a position //! before the first element. Equivalent to "end()" @@ -605,7 +596,7 @@ class slist_impl //! //! Complexity: Constant. const_iterator before_begin() const - { return const_iterator(uncast(this->get_root_node()), this); } + { return const_iterator(detail::uncast(this->get_root_node()), this->real_value_traits_ptr()); } //! Effects: Returns an iterator that points to a position //! before the first element. Equivalent to "end()" @@ -627,7 +618,7 @@ class slist_impl { //This function shall not be used if cache_last is not true BOOST_INTRUSIVE_INVARIANT_ASSERT(cache_last); - return iterator (this->get_last_node(), this); + return iterator (this->get_last_node(), this->real_value_traits_ptr()); } //! Effects: Returns a const_iterator to the last element contained in the list. @@ -641,7 +632,7 @@ class slist_impl { //This function shall not be used if cache_last is not true BOOST_INTRUSIVE_INVARIANT_ASSERT(cache_last); - return const_iterator (this->get_last_node(), this); + return const_iterator (this->get_last_node(), this->real_value_traits_ptr()); } //! Effects: Returns a const_iterator to the last element contained in the list. @@ -652,7 +643,7 @@ class slist_impl //! //! Note: This function is present only if cached_last<> option is true. const_iterator clast() const - { return const_iterator(this->get_last_node(), this); } + { return const_iterator(this->get_last_node(), this->real_value_traits_ptr()); } //! Precondition: end_iterator must be a valid end iterator //! of slist. @@ -801,7 +792,7 @@ class slist_impl this->set_last_node(n); } this->priv_size_traits().increment(); - return iterator (n, this); + return iterator (n, this->real_value_traits_ptr()); } //! Requires: Dereferencing iterator must yield @@ -1696,7 +1687,7 @@ class slist_impl { BOOST_STATIC_ASSERT((!stateful_value_traits)); //BOOST_INTRUSIVE_INVARIANT_ASSERT (!node_algorithms::inited(value_traits::to_node_ptr(value))); - return iterator (value_traits::to_node_ptr(value), 0); + return iterator (value_traits::to_node_ptr(value), const_real_value_traits_ptr()); } //! Requires: value must be a const reference to a value inserted in a list. @@ -1714,7 +1705,7 @@ class slist_impl { BOOST_STATIC_ASSERT((!stateful_value_traits)); //BOOST_INTRUSIVE_INVARIANT_ASSERT (!node_algorithms::inited(value_traits::to_node_ptr(const_cast (value)))); - return const_iterator (value_traits::to_node_ptr(const_cast (value)), 0); + return const_iterator (value_traits::to_node_ptr(const_cast (value)), const_real_value_traits_ptr()); } //! Requires: value must be a reference to a value inserted in a list. @@ -1729,7 +1720,7 @@ class slist_impl iterator iterator_to(reference value) { //BOOST_INTRUSIVE_INVARIANT_ASSERT (!node_algorithms::inited(value_traits::to_node_ptr(value))); - return iterator (value_traits::to_node_ptr(value), this); + return iterator (value_traits::to_node_ptr(value), this->real_value_traits_ptr()); } //! Requires: value must be a const reference to a value inserted in a list. @@ -1744,7 +1735,7 @@ class slist_impl const_iterator iterator_to(const_reference value) const { //BOOST_INTRUSIVE_INVARIANT_ASSERT (!node_algorithms::inited(value_traits::to_node_ptr(const_cast (value)))); - return const_iterator (value_traits::to_node_ptr(const_cast (value)), this); + return const_iterator (value_traits::to_node_ptr(const_cast (value)), this->real_value_traits_ptr()); } //! Returns: The iterator to the element before i in the list. @@ -1793,11 +1784,11 @@ class slist_impl const_iterator previous(const_iterator prev_from, const_iterator i) const { if(cache_last && (i.pointed_node() == this->get_end_node())){ - return const_iterator(uncast(this->get_last_node()), this); + return const_iterator(detail::uncast(this->get_last_node()), this->real_value_traits_ptr()); } return const_iterator (node_algorithms::get_previous_node - (prev_from.pointed_node(), i.pointed_node()), this); + (prev_from.pointed_node(), i.pointed_node()), this->real_value_traits_ptr()); } ///@cond @@ -1846,7 +1837,11 @@ class slist_impl { if(n){ BOOST_INTRUSIVE_INVARIANT_ASSERT(n > 0); - BOOST_INTRUSIVE_INVARIANT_ASSERT(size_type(std::distance(iterator(f, this), iterator(before_l, this)))+1 == n); + BOOST_INTRUSIVE_INVARIANT_ASSERT + (size_type(std::distance + ( iterator(f, this->real_value_traits_ptr()) + , iterator(before_l, this->real_value_traits_ptr()))) + +1 == n); this->priv_incorporate_after(prev_pos.pointed_node(), f, before_l); if(constant_time_size){ this->priv_size_traits().increase(n); @@ -1994,29 +1989,31 @@ class slist_impl #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif inline bool operator< #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const slist_impl &x, const slist_impl &y) #else -(const slist_impl &x, const slist_impl &y) +( const slist_impl &x +, const slist_impl &y) #endif { return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif bool operator== #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const slist_impl &x, const slist_impl &y) #else -(const slist_impl &x, const slist_impl &y) +( const slist_impl &x +, const slist_impl &y) #endif { - typedef slist_impl slist_type; + typedef slist_impl slist_type; typedef typename slist_type::const_iterator const_iterator; const bool C = slist_type::constant_time_size; if(C && x.size() != y.size()){ @@ -2046,65 +2043,70 @@ bool operator== #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif inline bool operator!= #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const slist_impl &x, const slist_impl &y) #else -(const slist_impl &x, const slist_impl &y) +( const slist_impl &x +, const slist_impl &y) #endif { return !(x == y); } #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif inline bool operator> #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const slist_impl &x, const slist_impl &y) #else -(const slist_impl &x, const slist_impl &y) +( const slist_impl &x +, const slist_impl &y) #endif { return y < x; } #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif inline bool operator<= #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const slist_impl &x, const slist_impl &y) #else -(const slist_impl &x, const slist_impl &y) +( const slist_impl &x +, const slist_impl &y) #endif { return !(y < x); } #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif inline bool operator>= #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (const slist_impl &x, const slist_impl &y) #else -(const slist_impl &x, const slist_impl &y) +( const slist_impl &x +, const slist_impl &y) #endif { return !(x < y); } #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif inline void swap #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) (slist_impl &x, slist_impl &y) #else -(slist_impl &x, slist_impl &y) +( slist_impl &x +, slist_impl &y) #endif { x.swap(y); } @@ -2113,13 +2115,13 @@ inline void swap #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else -template +template #endif struct make_slist { /// @cond typedef typename pack_options - < slist_defaults, + < slist_defaults, #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) O1, O2, O3, O4, O5 #else @@ -2127,16 +2129,13 @@ struct make_slist #endif >::type packed_options; typedef typename detail::get_value_traits - ::type value_traits; + ::type value_traits; typedef slist_impl - < - slistopt - < value_traits - , typename packed_options::size_type - , packed_options::constant_time_size - , packed_options::linear - , packed_options::cache_last - > + < value_traits + , typename packed_options::size_type + , (std::size_t(packed_options::linear)*slist_bool_flags::linear_pos) + |(std::size_t(packed_options::constant_time_size)*slist_bool_flags::constant_time_size_pos) + |(std::size_t(packed_options::cache_last)*slist_bool_flags::cache_last_pos) > implementation_defined; /// @endcond typedef implementation_defined type; @@ -2200,7 +2199,7 @@ class slist {} slist& operator=(BOOST_RV_REF(slist) x) - { this->Base::operator=(::boost::move(static_cast(x))); return *this; } + { return static_cast(this->Base::operator=(::boost::move(static_cast(x)))); } static slist &container_from_end_iterator(iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } diff --git a/include/boost/intrusive/slist_hook.hpp b/include/boost/intrusive/slist_hook.hpp index cd94a7e..fc160d9 100644 --- a/include/boost/intrusive/slist_hook.hpp +++ b/include/boost/intrusive/slist_hook.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 @@ -40,7 +40,7 @@ struct get_slist_node_algo #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else -template +template #endif struct make_slist_base_hook { @@ -54,11 +54,11 @@ struct make_slist_base_hook #endif >::type packed_options; - typedef detail::generic_hook + typedef generic_hook < get_slist_node_algo , typename packed_options::tag , packed_options::link_mode - , detail::SlistBaseHook + , SlistBaseHookId > implementation_defined; /// @endcond typedef implementation_defined type; @@ -168,7 +168,7 @@ class slist_base_hook #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else -template +template #endif struct make_slist_member_hook { @@ -182,11 +182,11 @@ struct make_slist_member_hook #endif >::type packed_options; - typedef detail::generic_hook + typedef generic_hook < get_slist_node_algo , member_tag , packed_options::link_mode - , detail::NoBaseHook + , NoBaseHookId > implementation_defined; /// @endcond typedef implementation_defined type; diff --git a/include/boost/intrusive/splay_set.hpp b/include/boost/intrusive/splay_set.hpp index 7cb4978..67aa56b 100644 --- a/include/boost/intrusive/splay_set.hpp +++ b/include/boost/intrusive/splay_set.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 @@ -36,14 +36,15 @@ namespace intrusive { #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class splay_set_impl +#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + : public splaytree_impl +#endif { /// @cond - typedef splaytree_impl tree_type; - //! This class is - //! movable + typedef splaytree_impl tree_type; BOOST_MOVABLE_BUT_NOT_COPYABLE(splay_set_impl) typedef tree_type implementation_defined; @@ -71,1204 +72,407 @@ class splay_set_impl typedef typename implementation_defined::const_node_ptr const_node_ptr; typedef typename implementation_defined::node_algorithms node_algorithms; - static const bool constant_time_size = Config::constant_time_size; - - /// @cond - private: - tree_type tree_; - /// @endcond + static const bool constant_time_size = tree_type::constant_time_size; public: - //! Effects: Constructs an empty splay_set. - //! - //! Complexity: Constant. - //! - //! Throws: If value_traits::node_traits::node - //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) - //! or the copy constructor of the value_compare object throws. + //! @copydoc ::boost::intrusive::splaytree::splaytree(const value_compare &,const value_traits &) explicit splay_set_impl( const value_compare &cmp = value_compare() - , const value_traits &v_traits = value_traits()) - : tree_(cmp, v_traits) + , const value_traits &v_traits = value_traits()) + : tree_type(cmp, v_traits) {} - //! Requires: Dereferencing iterator must yield an lvalue of type value_type. - //! cmp must be a comparison function that induces a strict weak ordering. - //! - //! Effects: Constructs an empty splay_set and inserts elements from - //! [b, e). - //! - //! Complexity: Linear in N if [b, e) is already sorted using - //! comp and otherwise amortized N * log N, where N is std::distance(last, first). - //! - //! Throws: If value_traits::node_traits::node - //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) - //! or the copy constructor/operator() of the value_compare object throws. + //! @copydoc ::boost::intrusive::splaytree::splaytree(bool,Iterator,Iterator,const value_compare &,const value_traits &) template splay_set_impl( Iterator b, Iterator e , const value_compare &cmp = value_compare() , const value_traits &v_traits = value_traits()) - : tree_(true, b, e, cmp, v_traits) + : tree_type(true, b, e, cmp, v_traits) {} - //! Effects: to-do - //! + //! @copydoc ::boost::intrusive::splaytree::splaytree(splaytree &&) splay_set_impl(BOOST_RV_REF(splay_set_impl) x) - : tree_(::boost::move(x.tree_)) + : tree_type(::boost::move(static_cast(x))) {} - //! Effects: to-do - //! + //! @copydoc ::boost::intrusive::splaytree::operator=(splaytree &&) splay_set_impl& operator=(BOOST_RV_REF(splay_set_impl) x) - { tree_ = ::boost::move(x.tree_); return *this; } + { return static_cast(tree_type::operator=(::boost::move(static_cast(x)))); } - //! Effects: Detaches all elements from this. The objects in the splay_set - //! are not deleted (i.e. no destructors are called). - //! - //! Complexity: Linear to the number of elements on the container. - //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. - //! - //! Throws: Nothing. - ~splay_set_impl() - {} + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::splaytree::~splaytree() + ~splay_set_impl(); - //! Effects: Returns an iterator pointing to the beginning of the splay_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator begin() - { return tree_.begin(); } + //! @copydoc ::boost::intrusive::splaytree::begin() + iterator begin(); - //! Effects: Returns a const_iterator pointing to the beginning of the splay_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator begin() const - { return tree_.begin(); } + //! @copydoc ::boost::intrusive::splaytree::begin()const + const_iterator begin() const; - //! Effects: Returns a const_iterator pointing to the beginning of the splay_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator cbegin() const - { return tree_.cbegin(); } + //! @copydoc ::boost::intrusive::splaytree::cbegin()const + const_iterator cbegin() const; - //! Effects: Returns an iterator pointing to the end of the splay_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator end() - { return tree_.end(); } + //! @copydoc ::boost::intrusive::splaytree::end() + iterator end(); - //! Effects: Returns a const_iterator pointing to the end of the splay_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator end() const - { return tree_.end(); } + //! @copydoc ::boost::intrusive::splaytree::end()const + const_iterator end() const; - //! Effects: Returns a const_iterator pointing to the end of the splay_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator cend() const - { return tree_.cend(); } + //! @copydoc ::boost::intrusive::splaytree::cend()const + const_iterator cend() const; - //! Effects: Returns a reverse_iterator pointing to the beginning of the - //! reversed splay_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - reverse_iterator rbegin() - { return tree_.rbegin(); } + //! @copydoc ::boost::intrusive::splaytree::rbegin() + reverse_iterator rbegin(); - //! Effects: Returns a const_reverse_iterator pointing to the beginning - //! of the reversed splay_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator rbegin() const - { return tree_.rbegin(); } + //! @copydoc ::boost::intrusive::splaytree::rbegin()const + const_reverse_iterator rbegin() const; - //! Effects: Returns a const_reverse_iterator pointing to the beginning - //! of the reversed splay_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator crbegin() const - { return tree_.crbegin(); } + //! @copydoc ::boost::intrusive::splaytree::crbegin()const + const_reverse_iterator crbegin() const; - //! Effects: Returns a reverse_iterator pointing to the end - //! of the reversed splay_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - reverse_iterator rend() - { return tree_.rend(); } + //! @copydoc ::boost::intrusive::splaytree::rend() + reverse_iterator rend(); - //! Effects: Returns a const_reverse_iterator pointing to the end - //! of the reversed splay_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator rend() const - { return tree_.rend(); } + //! @copydoc ::boost::intrusive::splaytree::rend()const + const_reverse_iterator rend() const; - //! Effects: Returns a const_reverse_iterator pointing to the end - //! of the reversed splay_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator crend() const - { return tree_.crend(); } + //! @copydoc ::boost::intrusive::splaytree::crend()const + const_reverse_iterator crend() const; - //! Precondition: end_iterator must be a valid end iterator - //! of splay_set. - //! - //! Effects: Returns a const reference to the splay_set associated to the end iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - static splay_set_impl &container_from_end_iterator(iterator end_iterator) - { - return *detail::parent_from_member - ( &tree_type::container_from_end_iterator(end_iterator) - , &splay_set_impl::tree_); - } + //! @copydoc ::boost::intrusive::splaytree::container_from_end_iterator(iterator) + static splay_set_impl &container_from_end_iterator(iterator end_iterator); - //! Precondition: end_iterator must be a valid end const_iterator - //! of splay_set. - //! - //! Effects: Returns a const reference to the splay_set associated to the end iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - static const splay_set_impl &container_from_end_iterator(const_iterator end_iterator) - { - return *detail::parent_from_member - ( &tree_type::container_from_end_iterator(end_iterator) - , &splay_set_impl::tree_); - } + //! @copydoc ::boost::intrusive::splaytree::container_from_end_iterator(const_iterator) + static const splay_set_impl &container_from_end_iterator(const_iterator end_iterator); - //! Precondition: it must be a valid iterator of set. - //! - //! Effects: Returns a reference to the set associated to the iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - static splay_set_impl &container_from_iterator(iterator it) - { - return *detail::parent_from_member - ( &tree_type::container_from_iterator(it) - , &splay_set_impl::tree_); - } + //! @copydoc ::boost::intrusive::splaytree::container_from_iterator(iterator) + static splay_set_impl &container_from_iterator(iterator it); - //! Precondition: it must be a valid const_iterator of set. - //! - //! Effects: Returns a const reference to the set associated to the iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Logarithmic. - static const splay_set_impl &container_from_iterator(const_iterator it) - { - return *detail::parent_from_member - ( &tree_type::container_from_iterator(it) - , &splay_set_impl::tree_); - } + //! @copydoc ::boost::intrusive::splaytree::container_from_iterator(const_iterator) + static const splay_set_impl &container_from_iterator(const_iterator it); - //! Effects: Returns the key_compare object used by the splay_set. - //! - //! Complexity: Constant. - //! - //! Throws: If key_compare copy-constructor throws. - key_compare key_comp() const - { return tree_.value_comp(); } + //! @copydoc ::boost::intrusive::splaytree::key_comp()const + key_compare key_comp() const; - //! Effects: Returns the value_compare object used by the splay_set. - //! - //! Complexity: Constant. - //! - //! Throws: If value_compare copy-constructor throws. - value_compare value_comp() const - { return tree_.value_comp(); } + //! @copydoc ::boost::intrusive::splaytree::value_comp()const + value_compare value_comp() const; - //! Effects: Returns true if the container is empty. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - bool empty() const - { return tree_.empty(); } + //! @copydoc ::boost::intrusive::splaytree::empty()const + bool empty() const; - //! Effects: Returns the number of elements stored in the splay_set. - //! - //! Complexity: Linear to elements contained in *this if, - //! constant-time size option is enabled. Constant-time otherwise. - //! - //! Throws: Nothing. - size_type size() const - { return tree_.size(); } + //! @copydoc ::boost::intrusive::splaytree::size()const + size_type size() const; - //! Effects: Swaps the contents of two splay_sets. - //! - //! Complexity: Constant. - //! - //! Throws: If the swap() call for the comparison functor - //! found using ADL throws. Strong guarantee. - void swap(splay_set_impl& other) - { tree_.swap(other.tree_); } + //! @copydoc ::boost::intrusive::splaytree::swap + void swap(splay_set_impl& other); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! Cloner should yield to nodes equivalent to the original nodes. - //! - //! Effects: Erases all the elements from *this - //! calling Disposer::operator()(pointer), clones all the - //! elements from src calling Cloner::operator()(const_reference ) - //! and inserts them on *this. Copies the predicate from the source container. - //! - //! If cloner throws, all cloned elements are unlinked and disposed - //! calling Disposer::operator()(pointer). - //! - //! Complexity: Linear to erased plus inserted elements. - //! - //! Throws: If cloner throws or predicate copy assignment throws. Basic guarantee. + //! @copydoc ::boost::intrusive::splaytree::clone_from template - void clone_from(const splay_set_impl &src, Cloner cloner, Disposer disposer) - { tree_.clone_from(src.tree_, cloner, disposer); } + void clone_from(const splay_set_impl &src, Cloner cloner, Disposer disposer); + + #endif //#ifdef BOOST_iNTRUSIVE_DOXYGEN_INVOKED - //! Requires: value must be an lvalue - //! - //! Effects: Tries to inserts value into the splay_set. - //! - //! Returns: If the value - //! is not already present inserts it and returns a pair containing the - //! iterator to the new value and true. If there is an equivalent value - //! returns a pair containing an iterator to the already present value - //! and false. - //! - //! Complexity: Amortized logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. Strong guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + //! @copydoc ::boost::intrusive::splaytree::insert_unique(reference) std::pair insert(reference value) - { return tree_.insert_unique(value); } + { return tree_type::insert_unique(value); } - //! Requires: value must be an lvalue - //! - //! Effects: Tries to to insert x into the splay_set, using "hint" - //! as a hint to where it will be inserted. - //! - //! Returns: An iterator that points to the position where the - //! new element was inserted into the splay_set. - //! - //! Complexity: Amortized logarithmic in general, but it's amortized - //! constant time if t is inserted immediately before hint. - //! - //! Throws: If the internal value_compare ordering function throws. Strong guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + //! @copydoc ::boost::intrusive::splaytree::insert_unique(const_iterator,reference) iterator insert(const_iterator hint, reference value) - { return tree_.insert_unique(hint, value); } + { return tree_type::insert_unique(hint, value); } - //! Requires: key_value_comp must be a comparison function that induces - //! the same strict weak ordering as value_compare. The difference is that - //! key_value_comp compares an arbitrary key with the contained values. - //! - //! Effects: Checks if a value can be inserted in the splay_set, using - //! a user provided key instead of the value itself. - //! - //! Returns: If there is an equivalent value - //! returns a pair containing an iterator to the already present value - //! and false. If the value can be inserted returns true in the returned - //! pair boolean and fills "commit_data" that is meant to be used with - //! the "insert_commit" function. - //! - //! Complexity: Amortized logarithmic. - //! - //! Throws: If the key_value_comp ordering function throws. Strong guarantee. - //! - //! Notes: This function is used to improve performance when constructing - //! a value_type is expensive: if there is an equivalent value - //! the constructed object must be discarded. Many times, the part of the - //! node that is used to impose the order is much cheaper to construct - //! than the value_type and this function offers the possibility to use that - //! part to check if the insertion will be successful. - //! - //! If the check is successful, the user can construct the value_type and use - //! "insert_commit" to insert the object in constant-time. This gives a total - //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)). - //! - //! "commit_data" remains valid for a subsequent "insert_commit" only if no more - //! objects are inserted or erased from the splay_set. + //! @copydoc ::boost::intrusive::splaytree::insert_unique_check(const KeyType&,KeyValueCompare,insert_commit_data&) template std::pair insert_check (const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data) - { return tree_.insert_unique_check(key, key_value_comp, commit_data); } + { return tree_type::insert_unique_check(key, key_value_comp, commit_data); } - //! Requires: key_value_comp must be a comparison function that induces - //! the same strict weak ordering as value_compare. The difference is that - //! key_value_comp compares an arbitrary key with the contained values. - //! - //! Effects: Checks if a value can be inserted in the splay_set, using - //! a user provided key instead of the value itself, using "hint" - //! as a hint to where it will be inserted. - //! - //! Returns: If there is an equivalent value - //! returns a pair containing an iterator to the already present value - //! and false. If the value can be inserted returns true in the returned - //! pair boolean and fills "commit_data" that is meant to be used with - //! the "insert_commit" function. - //! - //! Complexity: Amortized logarithmic in general, but it's amortized - //! constant time if t is inserted immediately before hint. - //! - //! Throws: If the key_value_comp ordering function throws. Strong guarantee. - //! - //! Notes: This function is used to improve performance when constructing - //! a value_type is expensive: if there is an equivalent value - //! the constructed object must be discarded. Many times, the part of the - //! constructing that is used to impose the order is much cheaper to construct - //! than the value_type and this function offers the possibility to use that key - //! to check if the insertion will be successful. - //! - //! If the check is successful, the user can construct the value_type and use - //! "insert_commit" to insert the object in constant-time. This can give a total - //! constant-time complexity to the insertion: check(O(1)) + commit(O(1)). - //! - //! "commit_data" remains valid for a subsequent "insert_commit" only if no more - //! objects are inserted or erased from the splay_set. + //! @copydoc ::boost::intrusive::splaytree::insert_unique_check(const_iterator,const KeyType&,KeyValueCompare,insert_commit_data&) template std::pair insert_check (const_iterator hint, const KeyType &key ,KeyValueCompare key_value_comp, insert_commit_data &commit_data) - { return tree_.insert_unique_check(hint, key, key_value_comp, commit_data); } + { return tree_type::insert_unique_check(hint, key, key_value_comp, commit_data); } - //! Requires: value must be an lvalue of type value_type. commit_data - //! must have been obtained from a previous call to "insert_check". - //! No objects should have been inserted or erased from the splay_set between - //! the "insert_check" that filled "commit_data" and the call to "insert_commit". - //! - //! Effects: Inserts the value in the splay_set using the information obtained - //! from the "commit_data" that a previous "insert_check" filled. - //! - //! Returns: An iterator to the newly inserted object. - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Notes: This function has only sense if a "insert_check" has been - //! previously executed to fill "commit_data". No value should be inserted or - //! erased between the "insert_check" and "insert_commit" calls. - iterator insert_commit(reference value, const insert_commit_data &commit_data) - { return tree_.insert_unique_commit(value, commit_data); } - - //! Requires: Dereferencing iterator must yield an lvalue - //! of type value_type. - //! - //! Effects: Inserts a range into the splay_set. - //! - //! Complexity: Insert range is amortized O(N * log(N)), where N is the - //! size of the range. However, it is linear in N if the range is already sorted - //! by value_comp(). - //! - //! Throws: If the internal value_compare ordering function throws. Basic guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + //! @copydoc ::boost::intrusive::splaytree::insert_unique(Iterator,Iterator) template void insert(Iterator b, Iterator e) - { tree_.insert_unique(b, e); } + { tree_type::insert_unique(b, e); } - //! Effects: Erases the element pointed to by pos. - //! - //! Complexity: Average complexity is constant time. - //! - //! Returns: An iterator to the element after the erased element. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - iterator erase(const_iterator i) - { return tree_.erase(i); } + //! @copydoc ::boost::intrusive::splaytree::insert_unique_commit + iterator insert_commit(reference value, const insert_commit_data &commit_data) + { return tree_type::insert_unique_commit(value, commit_data); } - //! Effects: Erases the range pointed to by b end e. - //! - //! Complexity: Average complexity for erase range is amortized - //! O(log(size() + N)), where N is the number of elements in the range. - //! - //! Returns: An iterator to the element after the erased elements. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - iterator erase(const_iterator b, const_iterator e) - { return tree_.erase(b, e); } + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::splaytree::insert_before + iterator insert_before(const_iterator pos, reference value); - //! Effects: Erases all the elements with the given value. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: Amortized O(log(size()) + this->count(value)). - //! - //! Throws: If the internal value_compare ordering function throws. Basic guarantee. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - size_type erase(const_reference value) - { return tree_.erase(value); } + //! @copydoc ::boost::intrusive::splaytree::push_back + void push_back(reference value); - //! Effects: Erases all the elements that compare equal with - //! the given key and the given comparison functor. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: Amortized O(log(size() + this->count(key, comp)). - //! - //! Throws: If the comp ordering function throws. Basic guarantee. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. + //! @copydoc ::boost::intrusive::splaytree::push_front + void push_front(reference value); + + //! @copydoc ::boost::intrusive::splaytree::erase(const_iterator) + iterator erase(const_iterator i); + + //! @copydoc ::boost::intrusive::splaytree::erase(const_iterator,const_iterator) + iterator erase(const_iterator b, const_iterator e); + + //! @copydoc ::boost::intrusive::splaytree::erase(const_reference) + size_type erase(const_reference value); + + //! @copydoc ::boost::intrusive::splaytree::erase(const KeyType&,KeyValueCompare) template - size_type erase(const KeyType& key, KeyValueCompare comp - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) - { return tree_.erase(key, comp); } + size_type erase(const KeyType& key, KeyValueCompare comp); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases the element pointed to by pos. - //! Disposer::operator()(pointer) is called for the removed element. - //! - //! Complexity: Average complexity for erase element is constant time. - //! - //! Returns: An iterator to the element after the erased element. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::splaytree::erase_and_dispose(const_iterator,Disposer) template - iterator erase_and_dispose(const_iterator i, Disposer disposer) - { return tree_.erase_and_dispose(i, disposer); } + iterator erase_and_dispose(const_iterator i, Disposer disposer); - #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + //! @copydoc ::boost::intrusive::splaytree::erase_and_dispose(const_iterator,const_iterator,Disposer) template - iterator erase_and_dispose(iterator i, Disposer disposer) - { return this->erase_and_dispose(const_iterator(i), disposer); } - #endif + iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases the range pointed to by b end e. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Complexity: Average complexity for erase range is at most - //! O(log(size() + N)), where N is the number of elements in the range. - //! - //! Returns: An iterator to the element after the erased elements. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::splaytree::erase_and_dispose(const_reference, Disposer) template - iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer) - { return tree_.erase_and_dispose(b, e, disposer); } + size_type erase_and_dispose(const_reference value, Disposer disposer); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements with the given value. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Throws: If the internal value_compare ordering function throws. - //! - //! Complexity: Amortized O(log(size() + this->count(value)). Basic guarantee. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - template - size_type erase_and_dispose(const_reference value, Disposer disposer) - { return tree_.erase_and_dispose(value, disposer); } - - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements with the given key. - //! according to the comparison functor "comp". - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: Amortized O(log(size() + this->count(key, comp)). - //! - //! Throws: If comp ordering function throws. Basic guarantee. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::splaytree::erase_and_dispose(const KeyType&,KeyValueCompare,Disposer) template - size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) - { return tree_.erase_and_dispose(key, comp, disposer); } + size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer); - //! Effects: Erases all the elements of the container. - //! - //! Complexity: Linear to the number of elements on the container. - //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - void clear() - { return tree_.clear(); } + //! @copydoc ::boost::intrusive::splaytree::clear + void clear(); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements of the container. - //! - //! Complexity: Linear to the number of elements on the container. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. + //! @copydoc ::boost::intrusive::splaytree::clear_and_dispose template - void clear_and_dispose(Disposer disposer) - { return tree_.clear_and_dispose(disposer); } + void clear_and_dispose(Disposer disposer); - //! Effects: Returns the number of contained elements with the given key - //! - //! Complexity: Amortized logarithmic to the number of elements contained plus lineal - //! to number of objects with the given key. - //! - //! Throws: If the internal value_compare ordering function throws. - size_type count(const_reference value) - { return tree_.find(value) != end(); } + //! @copydoc ::boost::intrusive::splaytree::count(const_reference) + size_type count(const_reference value); - //! Effects: Returns the number of contained elements with the same key - //! compared with the given comparison functor. - //! - //! Complexity: Amortized logarithmic to the number of elements contained plus lineal - //! to number of objects with the given key. - //! - //! Throws: If comp ordering function throws. + //! @copydoc ::boost::intrusive::splaytree::count(const KeyType&,KeyValueCompare)const template - size_type count(const KeyType& key, KeyValueCompare comp) - { return tree_.find(key, comp) != end(); } + size_type count(const KeyType& key, KeyValueCompare comp); - //! Effects: Returns the number of contained elements with the given key - //! - //! Complexity: Logarithmic to the number of elements contained plus lineal - //! to number of objects with the given key. - //! - //! Throws: If the internal value_compare ordering function throws. - size_type count_dont_splay(const_reference value)const - { return tree_.find_dont_splay(value) != end(); } + //! @copydoc ::boost::intrusive::splaytree::count(const_reference)const + size_type count(const_reference value) const; - //! Effects: Returns the number of contained elements with the same key - //! compared with the given comparison functor. - //! - //! Complexity: Logarithmic to the number of elements contained plus lineal - //! to number of objects with the given key. - //! - //! Throws: If comp ordering function throws. + //! @copydoc ::boost::intrusive::splaytree::count(const KeyType&,KeyValueCompare)const template - size_type count_dont_splay(const KeyType& key, KeyValueCompare comp)const - { return tree_.find_dont_splay(key, comp) != end(); } + size_type count(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Returns an iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Amortized logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - iterator lower_bound(const_reference value) - { return tree_.lower_bound(value); } + //! @copydoc ::boost::intrusive::splaytree::count_dont_splay(const_reference)const + size_type count_dont_splay(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Returns an iterator to the first element whose - //! key according to the comparison functor is not less than k or - //! end() if that element does not exist. - //! - //! Complexity: Amortized logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::splaytree::count_dont_splay(const KeyType&,KeyValueCompare)const template - iterator lower_bound(const KeyType& key, KeyValueCompare comp) - { return tree_.lower_bound(key, comp); } - - //! Effects: Returns a const iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - const_iterator lower_bound_dont_splay(const_reference value) const - { return tree_.lower_bound_dont_splay(value); } - - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Returns a const_iterator to the first element whose - //! key according to the comparison functor is not less than k or - //! end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + 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); + + //! @copydoc ::boost::intrusive::splaytree::lower_bound(const KeyType&,KeyValueCompare) template - const_iterator lower_bound_dont_splay(const KeyType& key, KeyValueCompare comp) const - { return tree_.lower_bound_dont_splay(key, comp); } + iterator lower_bound(const KeyType& key, KeyValueCompare comp); - //! Effects: Returns an iterator to the first element whose - //! key is greater than k or end() if that element does not exist. - //! - //! Complexity: Amortized logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - iterator upper_bound(const_reference value) - { return tree_.upper_bound(value); } + //! @copydoc ::boost::intrusive::splaytree::lower_bound(const_reference)const + const_iterator lower_bound(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Returns an iterator to the first element whose - //! key according to the comparison functor is greater than key or - //! end() if that element does not exist. - //! - //! Complexity: Amortized logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::splaytree::lower_bound(const KeyType&,KeyValueCompare)const template - iterator upper_bound(const KeyType& key, KeyValueCompare comp) - { return tree_.upper_bound(key, comp); } + const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Returns an iterator to the first element whose - //! key is greater than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - const_iterator upper_bound_dont_splay(const_reference value) const - { return tree_.upper_bound_dont_splay(value); } + //! @copydoc ::boost::intrusive::splaytree::lower_bound_dont_splay(const_reference)const + const_iterator lower_bound_dont_splay(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Returns a const_iterator to the first element whose - //! key according to the comparison functor is greater than key or - //! end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::splaytree::lower_bound_dont_splay(const KeyType&,KeyValueCompare)const template - const_iterator upper_bound_dont_splay(const KeyType& key, KeyValueCompare comp) const - { return tree_.upper_bound_dont_splay(key, comp); } + const_iterator lower_bound_dont_splay(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Finds an iterator to the first element whose value is - //! "value" or end() if that element does not exist. - //! - //! Complexity: Amortized logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - iterator find(const_reference value) - { return tree_.find(value); } + //! @copydoc ::boost::intrusive::splaytree::upper_bound(const_reference) + iterator upper_bound(const_reference value); - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Finds an iterator to the first element whose key is - //! "key" according to the comparison functor or end() if that element - //! does not exist. - //! - //! Complexity: Amortized logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::splaytree::upper_bound(const KeyType&,KeyValueCompare) template - iterator find(const KeyType& key, KeyValueCompare comp) - { return tree_.find(key, comp); } + iterator upper_bound(const KeyType& key, KeyValueCompare comp); - //! Effects: Finds a const_iterator to the first element whose value is - //! "value" or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - const_iterator find_dont_splay(const_reference value) const - { return tree_.find_dont_splay(value); } + //! @copydoc ::boost::intrusive::splaytree::upper_bound(const_reference)const + const_iterator upper_bound(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Finds a const_iterator to the first element whose key is - //! "key" according to the comparison functor or end() if that element - //! does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::splaytree::upper_bound(const KeyType&,KeyValueCompare)const template - const_iterator find_dont_splay(const KeyType& key, KeyValueCompare comp) const - { return tree_.find_dont_splay(key, comp); } + const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Amortized logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - std::pair equal_range(const_reference value) - { return tree_.equal_range(value); } + //! @copydoc ::boost::intrusive::splaytree::upper_bound_dont_splay(const_reference)const + const_iterator upper_bound_dont_splay(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Finds a range containing all elements whose key is k - //! according to the comparison functor or an empty range - //! that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Amortized logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::splaytree::upper_bound_dont_splay(const KeyType&,KeyValueCompare)const template - std::pair equal_range(const KeyType& key, KeyValueCompare comp) - { return tree_.equal_range(key, comp); } + const_iterator upper_bound_dont_splay(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. + //! @copydoc ::boost::intrusive::splaytree::find(const_reference) + iterator find(const_reference value); + + //! @copydoc ::boost::intrusive::splaytree::find(const KeyType&,KeyValueCompare) + template + iterator find(const KeyType& key, KeyValueCompare comp); + + //! @copydoc ::boost::intrusive::splaytree::find(const_reference)const + const_iterator find(const_reference value) const; + + //! @copydoc ::boost::intrusive::splaytree::find(const KeyType&,KeyValueCompare)const + 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); + + //! @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 std::pair - equal_range_dont_splay(const_reference value) const - { return tree_.equal_range_dont_splay(value); } + equal_range(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Finds a range containing all elements whose key is k - //! according to the comparison functor or an empty range - //! that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::splaytree::equal_range(const KeyType&,KeyValueCompare)const template std::pair - equal_range_dont_splay(const KeyType& key, KeyValueCompare comp) const - { return tree_.equal_range_dont_splay(key, comp); } + equal_range(const KeyType& key, KeyValueCompare comp) const; - //! Requires: 'lower_value' must not be greater than 'upper_value'. If - //! 'lower_value' == 'upper_value', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise - //! - //! second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the predicate throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_value and upper_value. + //! @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) - { return tree_.bounded_range(lower_value, upper_value, left_closed, right_closed); } + (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); - //! Requires: KeyValueCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. - //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If - //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key, comp) if left_closed, upper_bound(lower_key, comp) otherwise - //! - //! second = upper_bound(upper_key, comp) if right_closed, lower_bound(upper_key, comp) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_key and upper_key. + //! @copydoc ::boost::intrusive::splaytree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool) template std::pair bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) - { return tree_.bounded_range(lower_key, upper_key, comp, left_closed, right_closed); } + (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed); - //! Requires: 'lower_value' must not be greater than 'upper_value'. If - //! 'lower_value' == 'upper_value', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise - //! - //! second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the predicate throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_value and upper_value. - std::pair - bounded_range_dont_splay_dont_splay - (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const - { return tree_.bounded_range_dont_splay(lower_value, upper_value, left_closed, right_closed); } + //! @copydoc ::boost::intrusive::splaytree::bounded_range(const_reference,const_reference,bool,bool)const + std::pair bounded_range + (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; - //! Requires: KeyValueCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. - //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If - //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key, comp) if left_closed, upper_bound(lower_key, comp) otherwise - //! - //! second = upper_bound(upper_key, comp) if right_closed, lower_bound(upper_key, comp) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_key and upper_key. + //! @copydoc ::boost::intrusive::splaytree::bounded_range(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 - { return tree_.bounded_range_dont_splay(lower_key, upper_key, comp, left_closed, right_closed); } + std::pair bounded_range + (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; - //! Requires: value must be an lvalue and shall be in a splay_set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid iterator i belonging to the splay_set - //! that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This static function is available only if the value traits - //! is stateless. - static iterator s_iterator_to(reference value) - { return tree_type::s_iterator_to(value); } + //! @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; - //! Requires: value must be an lvalue and shall be in a splay_set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid const_iterator i belonging to the - //! splay_set that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This static function is available only if the value traits - //! is stateless. - static const_iterator s_iterator_to(const_reference value) - { return tree_type::s_iterator_to(value); } + //! @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; - //! Requires: value must be an lvalue and shall be in a splay_set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid iterator i belonging to the splay_set - //! that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator iterator_to(reference value) - { return tree_.iterator_to(value); } + //! @copydoc ::boost::intrusive::splaytree::s_iterator_to(reference) + static iterator s_iterator_to(reference value); - //! Requires: value must be an lvalue and shall be in a splay_set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid const_iterator i belonging to the - //! splay_set that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator iterator_to(const_reference value) const - { return tree_.iterator_to(value); } + //! @copydoc ::boost::intrusive::splaytree::s_iterator_to(const_reference) + static const_iterator s_iterator_to(const_reference value); - //! Requires: value shall not be in a splay_set/multisplay_set. - //! - //! Effects: init_node puts the hook of a value in a well-known default - //! state. - //! - //! Throws: Nothing. - //! - //! Complexity: Constant time. - //! - //! Note: This function puts the hook in the well-known default state - //! used by auto_unlink and safe hooks. - static void init_node(reference value) - { tree_type::init_node(value); } + //! @copydoc ::boost::intrusive::splaytree::iterator_to(reference) + iterator iterator_to(reference value); - //! Effects: Unlinks the leftmost node from the tree. - //! - //! Complexity: Average complexity is constant time. - //! - //! Throws: Nothing. - //! - //! Notes: This function breaks the tree and the tree can - //! only be used for more unlink_leftmost_without_rebalance calls. - //! This function is normally used to achieve a step by step - //! controlled destruction of the tree. - pointer unlink_leftmost_without_rebalance() - { return tree_.unlink_leftmost_without_rebalance(); } + //! @copydoc ::boost::intrusive::splaytree::iterator_to(const_reference)const + const_iterator iterator_to(const_reference value) const; - //! Requires: replace_this must be a valid iterator of *this - //! and with_this must not be inserted in any tree. - //! - //! Effects: Replaces replace_this in its position in the - //! tree with with_this. The tree does not need to be rebalanced. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This function will break container ordering invariants if - //! with_this is not equivalent to *replace_this according to the - //! ordering rules. This function is faster than erasing and inserting - //! the node, since no rebalancing or comparison is needed. - void replace_node(iterator replace_this, reference with_this) - { tree_.replace_node(replace_this, with_this); } + //! @copydoc ::boost::intrusive::splaytree::init_node(reference) + static void init_node(reference value); - //! Requires: i must be a valid iterator of *this. - //! - //! Effects: Rearranges the splay set so that the element pointed by i - //! is placed as the root of the tree, improving future searches of this value. - //! - //! Complexity: Amortized logarithmic. - //! - //! Throws: Nothing. - void splay_up(iterator i) - { tree_.splay_up(i); } + //! @copydoc ::boost::intrusive::splaytree::unlink_leftmost_without_rebalance + pointer unlink_leftmost_without_rebalance(); - //! Effects: Rearranges the splay set so that if *this stores an element - //! with a key equivalent to value the element is placed as the root of the - //! tree. If the element is not present returns the last node compared with the key. - //! If the tree is empty, end() is returned. - //! - //! Complexity: Amortized logarithmic. - //! - //! Returns: An iterator to the new root of the tree, end() if the tree is empty. - //! - //! Throws: If the comparison functor throws. - template - iterator splay_down(const KeyType &key, KeyNodePtrCompare comp) - { return tree_.splay_down(key, comp); } + //! @copydoc ::boost::intrusive::splaytree::replace_node + void replace_node(iterator replace_this, reference with_this); - //! Effects: Rearranges the splay set so that if *this stores an element - //! with a key equivalent to value the element is placed as the root of the - //! tree. - //! - //! Complexity: Amortized logarithmic. - //! - //! Returns: An iterator to the new root of the tree, end() if the tree is empty. - //! - //! Throws: If the predicate throws. - iterator splay_down(const value_type &value) - { return tree_.splay_down(value); } + //! @copydoc ::boost::intrusive::splaytree::remove_node + void remove_node(reference value); - //! Effects: Rebalances the tree. - //! - //! Throws: Nothing. - //! - //! Complexity: Linear. - void rebalance() - { tree_.rebalance(); } + //! @copydoc ::boost::intrusive::splaytree::splay_up(iterator) + void splay_up(iterator i); - //! Requires: old_root is a node of a tree. - //! - //! Effects: Rebalances the subtree rooted at old_root. - //! - //! Returns: The new root of the subtree. - //! - //! Throws: Nothing. - //! - //! Complexity: Linear to the elements in the subtree. - iterator rebalance_subtree(iterator root) - { return tree_.rebalance_subtree(root); } + //! @copydoc ::boost::intrusive::splaytree::splay_down(const KeyType&,KeyValueCompare) + template + iterator splay_down(const KeyType &key, KeyValueCompare comp); - /// @cond - friend bool operator==(const splay_set_impl &x, const splay_set_impl &y) - { return x.tree_ == y.tree_; } + //! @copydoc ::boost::intrusive::splaytree::splay_down(const_reference) + iterator splay_down(const_reference value); + + //! @copydoc ::boost::intrusive::splaytree::rebalance + void rebalance(); - friend bool operator<(const splay_set_impl &x, const splay_set_impl &y) - { return x.tree_ < y.tree_; } - /// @endcond + //! @copydoc ::boost::intrusive::splaytree::rebalance_subtree + iterator rebalance_subtree(iterator root); + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED }; #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator!= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const splay_set_impl &x, const splay_set_impl &y) -#else -(const splay_set_impl &x, const splay_set_impl &y) -#endif -{ return !(x == y); } -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator> -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const splay_set_impl &x, const splay_set_impl &y) -#else -(const splay_set_impl &x, const splay_set_impl &y) -#endif -{ return y < x; } +bool operator!= (const splay_set_impl &x, const splay_set_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator<= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const splay_set_impl &x, const splay_set_impl &y) -#else -(const splay_set_impl &x, const splay_set_impl &y) -#endif -{ return !(y < x); } +bool operator>(const splay_set_impl &x, const splay_set_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator>= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const splay_set_impl &x, const splay_set_impl &y) -#else -(const splay_set_impl &x, const splay_set_impl &y) -#endif -{ return !(x < y); } +bool operator<=(const splay_set_impl &x, const splay_set_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline void swap -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(splay_set_impl &x, splay_set_impl &y) -#else -(splay_set_impl &x, splay_set_impl &y) -#endif -{ x.swap(y); } +bool operator>=(const splay_set_impl &x, const splay_set_impl &y); + +template +void swap(splay_set_impl &x, splay_set_impl &y); + +#endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Helper metafunction to define a \c splay_set that yields to the same type when the //! same options (either explicitly or implicitly) are used. #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else -template +template #endif struct make_splay_set { /// @cond + typedef typename pack_options + < splaytree_defaults, + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3, O4 + #else + Options... + #endif + >::type packed_options; + + typedef typename detail::get_value_traits + ::type value_traits; + typedef splay_set_impl - < typename make_splaytree_opt::type - > implementation_defined; + < value_traits + , typename packed_options::compare + , typename packed_options::size_type + , packed_options::constant_time_size + > implementation_defined; /// @endcond typedef implementation_defined type; }; @@ -1281,23 +485,23 @@ template #endif class splay_set : public make_splay_set::type + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3, O4 + #else + Options... + #endif + >::type { typedef typename make_splay_set ::type Base; - BOOST_MOVABLE_BUT_NOT_COPYABLE(splay_set) + BOOST_MOVABLE_BUT_NOT_COPYABLE(splay_set) public: typedef typename Base::value_compare value_compare; typedef typename Base::value_traits value_traits; @@ -1324,7 +528,7 @@ class splay_set {} splay_set& operator=(BOOST_RV_REF(splay_set) x) - { this->Base::operator=(::boost::move(static_cast(x))); return *this; } + { return static_cast(this->Base::operator=(::boost::move(static_cast(x)))); } static splay_set &container_from_end_iterator(iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } @@ -1355,14 +559,16 @@ class splay_set #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class splay_multiset_impl +#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + : public splaytree_impl +#endif { /// @cond - typedef splaytree_impl tree_type; + typedef splaytree_impl tree_type; - //Movable BOOST_MOVABLE_BUT_NOT_COPYABLE(splay_multiset_impl) typedef tree_type implementation_defined; /// @endcond @@ -1389,1111 +595,390 @@ class splay_multiset_impl typedef typename implementation_defined::const_node_ptr const_node_ptr; typedef typename implementation_defined::node_algorithms node_algorithms; - static const bool constant_time_size = Config::constant_time_size; - - /// @cond - private: - tree_type tree_; - /// @endcond + static const bool constant_time_size = tree_type::constant_time_size; public: - //! Effects: Constructs an empty splay_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: If value_traits::node_traits::node - //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) - //! or the copy constructor/operator() of the value_compare object throws. + //! @copydoc ::boost::intrusive::splaytree::splaytree(const value_compare &,const value_traits &) explicit splay_multiset_impl( const value_compare &cmp = value_compare() - , const value_traits &v_traits = value_traits()) - : tree_(cmp, v_traits) + , const value_traits &v_traits = value_traits()) + : tree_type(cmp, v_traits) {} - //! Requires: Dereferencing iterator must yield an lvalue of type value_type. - //! cmp must be a comparison function that induces a strict weak ordering. - //! - //! Effects: Constructs an empty splay_multiset and inserts elements from - //! [b, e). - //! - //! Complexity: Linear in N if [b, e) is already sorted using - //! comp and otherwise amortized N * log N, where N is the distance between first and last. - //! - //! Throws: If value_traits::node_traits::node - //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) - //! or the copy constructor/operator() of the value_compare object throws. + //! @copydoc ::boost::intrusive::splaytree::splaytree(bool,Iterator,Iterator,const value_compare &,const value_traits &) template splay_multiset_impl( Iterator b, Iterator e , const value_compare &cmp = value_compare() , const value_traits &v_traits = value_traits()) - : tree_(false, b, e, cmp, v_traits) + : tree_type(false, b, e, cmp, v_traits) {} - //! Effects: to-do - //! + //! @copydoc ::boost::intrusive::splaytree::splaytree(splaytree &&) splay_multiset_impl(BOOST_RV_REF(splay_multiset_impl) x) - : tree_(::boost::move(x.tree_)) + : tree_type(::boost::move(static_cast(x))) {} - //! Effects: to-do - //! + //! @copydoc ::boost::intrusive::splaytree::operator=(splaytree &&) splay_multiset_impl& operator=(BOOST_RV_REF(splay_multiset_impl) x) - { tree_ = ::boost::move(x.tree_); return *this; } + { return static_cast(tree_type::operator=(::boost::move(static_cast(x)))); } - //! Effects: Detaches all elements from this. The objects in the set - //! are not deleted (i.e. no destructors are called). - //! - //! Complexity: Linear to the number of elements on the container. - //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. - //! - //! Throws: Nothing. - ~splay_multiset_impl() - {} + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::splaytree::~splaytree() + ~splay_multiset_impl(); - //! Effects: Returns an iterator pointing to the beginning of the splay_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator begin() - { return tree_.begin(); } + //! @copydoc ::boost::intrusive::splaytree::begin() + iterator begin(); - //! Effects: Returns a const_iterator pointing to the beginning of the splay_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator begin() const - { return tree_.begin(); } + //! @copydoc ::boost::intrusive::splaytree::begin()const + const_iterator begin() const; - //! Effects: Returns a const_iterator pointing to the beginning of the splay_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator cbegin() const - { return tree_.cbegin(); } + //! @copydoc ::boost::intrusive::splaytree::cbegin()const + const_iterator cbegin() const; - //! Effects: Returns an iterator pointing to the end of the splay_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator end() - { return tree_.end(); } + //! @copydoc ::boost::intrusive::splaytree::end() + iterator end(); - //! Effects: Returns a const_iterator pointing to the end of the splay_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator end() const - { return tree_.end(); } + //! @copydoc ::boost::intrusive::splaytree::end()const + const_iterator end() const; - //! Effects: Returns a const_iterator pointing to the end of the splay_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator cend() const - { return tree_.cend(); } + //! @copydoc ::boost::intrusive::splaytree::cend()const + const_iterator cend() const; - //! Effects: Returns a reverse_iterator pointing to the beginning of the - //! reversed splay_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - reverse_iterator rbegin() - { return tree_.rbegin(); } + //! @copydoc ::boost::intrusive::splaytree::rbegin() + reverse_iterator rbegin(); - //! Effects: Returns a const_reverse_iterator pointing to the beginning - //! of the reversed splay_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator rbegin() const - { return tree_.rbegin(); } + //! @copydoc ::boost::intrusive::splaytree::rbegin()const + const_reverse_iterator rbegin() const; - //! Effects: Returns a const_reverse_iterator pointing to the beginning - //! of the reversed splay_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator crbegin() const - { return tree_.crbegin(); } + //! @copydoc ::boost::intrusive::splaytree::crbegin()const + const_reverse_iterator crbegin() const; - //! Effects: Returns a reverse_iterator pointing to the end - //! of the reversed splay_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - reverse_iterator rend() - { return tree_.rend(); } + //! @copydoc ::boost::intrusive::splaytree::rend() + reverse_iterator rend(); - //! Effects: Returns a const_reverse_iterator pointing to the end - //! of the reversed splay_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator rend() const - { return tree_.rend(); } + //! @copydoc ::boost::intrusive::splaytree::rend()const + const_reverse_iterator rend() const; - //! Effects: Returns a const_reverse_iterator pointing to the end - //! of the reversed splay_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator crend() const - { return tree_.crend(); } + //! @copydoc ::boost::intrusive::splaytree::crend()const + const_reverse_iterator crend() const; - //! Precondition: end_iterator must be a valid end iterator - //! of splay_multiset. - //! - //! Effects: Returns a const reference to the splay_multiset associated to the end iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - static splay_multiset_impl &container_from_end_iterator(iterator end_iterator) - { - return *detail::parent_from_member - ( &tree_type::container_from_end_iterator(end_iterator) - , &splay_multiset_impl::tree_); - } + //! @copydoc ::boost::intrusive::splaytree::container_from_end_iterator(iterator) + static splay_multiset_impl &container_from_end_iterator(iterator end_iterator); - //! Precondition: end_iterator must be a valid end const_iterator - //! of splay_multiset. - //! - //! Effects: Returns a const reference to the splay_multiset associated to the end iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - static const splay_multiset_impl &container_from_end_iterator(const_iterator end_iterator) - { - return *detail::parent_from_member - ( &tree_type::container_from_end_iterator(end_iterator) - , &splay_multiset_impl::tree_); - } + //! @copydoc ::boost::intrusive::splaytree::container_from_end_iterator(const_iterator) + static const splay_multiset_impl &container_from_end_iterator(const_iterator end_iterator); - //! Precondition: it must be a valid iterator of multiset. - //! - //! Effects: Returns a const reference to the multiset associated to the iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Logarithmic. - static splay_multiset_impl &container_from_iterator(iterator it) - { - return *detail::parent_from_member - ( &tree_type::container_from_iterator(it) - , &splay_multiset_impl::tree_); - } + //! @copydoc ::boost::intrusive::splaytree::container_from_iterator(iterator) + static splay_multiset_impl &container_from_iterator(iterator it); - //! Precondition: it must be a valid const_iterator of multiset. - //! - //! Effects: Returns a const reference to the multiset associated to the iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - static const splay_multiset_impl &container_from_iterator(const_iterator it) - { - return *detail::parent_from_member - ( &tree_type::container_from_iterator(it) - , &splay_multiset_impl::tree_); - } + //! @copydoc ::boost::intrusive::splaytree::container_from_iterator(const_iterator) + static const splay_multiset_impl &container_from_iterator(const_iterator it); - //! Effects: Returns the key_compare object used by the splay_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: If key_compare copy-constructor throws. - key_compare key_comp() const - { return tree_.value_comp(); } + //! @copydoc ::boost::intrusive::splaytree::key_comp()const + key_compare key_comp() const; - //! Effects: Returns the value_compare object used by the splay_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: If value_compare copy-constructor throws. - value_compare value_comp() const - { return tree_.value_comp(); } + //! @copydoc ::boost::intrusive::splaytree::value_comp()const + value_compare value_comp() const; - //! Effects: Returns true if the container is empty. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - bool empty() const - { return tree_.empty(); } + //! @copydoc ::boost::intrusive::splaytree::empty()const + bool empty() const; - //! Effects: Returns the number of elements stored in the splay_multiset. - //! - //! Complexity: Linear to elements contained in *this if, - //! constant-time size option is enabled. Constant-time otherwise. - //! - //! Throws: Nothing. - size_type size() const - { return tree_.size(); } + //! @copydoc ::boost::intrusive::splaytree::size()const + size_type size() const; - //! Effects: Swaps the contents of two splay_multisets. - //! - //! Complexity: Constant. - //! - //! Throws: If the swap() call for the comparison functor - //! found using ADL throws. Strong guarantee. - void swap(splay_multiset_impl& other) - { tree_.swap(other.tree_); } + //! @copydoc ::boost::intrusive::splaytree::swap + void swap(splay_multiset_impl& other); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! Cloner should yield to nodes equivalent to the original nodes. - //! - //! Effects: Erases all the elements from *this - //! calling Disposer::operator()(pointer), clones all the - //! elements from src calling Cloner::operator()(const_reference ) - //! and inserts them on *this. Copies the predicate from the source container. - //! - //! If cloner throws, all cloned elements are unlinked and disposed - //! calling Disposer::operator()(pointer). - //! - //! Complexity: Linear to erased plus inserted elements. - //! - //! Throws: If cloner throws or predicate copy assignment throws. Basic guarantee. + //! @copydoc ::boost::intrusive::splaytree::clone_from template - void clone_from(const splay_multiset_impl &src, Cloner cloner, Disposer disposer) - { tree_.clone_from(src.tree_, cloner, disposer); } + void clone_from(const splay_multiset_impl &src, Cloner cloner, Disposer disposer); - //! Requires: value must be an lvalue - //! - //! Effects: Inserts value into the splay_multiset. - //! - //! Returns: An iterator that points to the position where the new - //! element was inserted. - //! - //! Complexity: Amortized logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. Strong guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + #endif //#ifdef BOOST_iNTRUSIVE_DOXYGEN_INVOKED + + //! @copydoc ::boost::intrusive::splaytree::insert_equal(reference) iterator insert(reference value) - { return tree_.insert_equal(this->end(), value); } + { return tree_type::insert_equal(value); } - //! Requires: value must be an lvalue - //! - //! Effects: Inserts x into the splay_multiset, using pos as a hint to - //! where it will be inserted. - //! - //! Returns: An iterator that points to the position where the new - //! element was inserted. - //! - //! Complexity: Amortized logarithmic in general, but it is amortized - //! constant time if t is inserted immediately before hint. - //! - //! Throws: If the internal value_compare ordering function throws. Strong guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + //! @copydoc ::boost::intrusive::splaytree::insert_equal(const_iterator,reference) iterator insert(const_iterator hint, reference value) - { return tree_.insert_equal(hint, value); } + { return tree_type::insert_equal(hint, value); } - //! Requires: Dereferencing iterator must yield an lvalue - //! of type value_type. - //! - //! Effects: Inserts a range into the splay_multiset. - //! - //! Returns: An iterator that points to the position where the new - //! element was inserted. - //! - //! Complexity: Insert range is amortized O(N * log(N)), where N is the - //! size of the range. However, it is linear in N if the range is already sorted - //! by value_comp(). - //! - //! Throws: If the internal value_compare ordering function throws. Basic guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + //! @copydoc ::boost::intrusive::splaytree::insert_equal(Iterator,Iterator) template void insert(Iterator b, Iterator e) - { tree_.insert_equal(b, e); } + { tree_type::insert_equal(b, e); } - //! Effects: Erases the element pointed to by pos. - //! - //! Complexity: Average complexity is constant time. - //! - //! Returns: An iterator to the element after the erased element. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - iterator erase(const_iterator i) - { return tree_.erase(i); } + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::splaytree::insert_before + iterator insert_before(const_iterator pos, reference value); - //! Effects: Erases the range pointed to by b end e. - //! - //! Returns: An iterator to the element after the erased elements. - //! - //! Complexity: Average complexity for erase range is amortized - //! O(log(size() + N)), where N is the number of elements in the range. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - iterator erase(const_iterator b, const_iterator e) - { return tree_.erase(b, e); } + //! @copydoc ::boost::intrusive::splaytree::push_back + void push_back(reference value); - //! Effects: Erases all the elements with the given value. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: Amortized O(log(size() + this->count(value)). - //! - //! Throws: If the internal value_compare ordering function throws. Basic guarantee. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - size_type erase(const_reference value) - { return tree_.erase(value); } + //! @copydoc ::boost::intrusive::splaytree::push_front + void push_front(reference value); - //! Effects: Erases all the elements that compare equal with - //! the given key and the given comparison functor. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: Amortized O(log(size() + this->count(key, comp)). - //! - //! Throws: If comp ordering function throws. Basic guarantee. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. + //! @copydoc ::boost::intrusive::splaytree::erase(const_iterator) + iterator erase(const_iterator i); + + //! @copydoc ::boost::intrusive::splaytree::erase(const_iterator,const_iterator) + iterator erase(const_iterator b, const_iterator e); + + //! @copydoc ::boost::intrusive::splaytree::erase(const_reference) + size_type erase(const_reference value); + + //! @copydoc ::boost::intrusive::splaytree::erase(const KeyType&,KeyValueCompare) template - size_type erase(const KeyType& key, KeyValueCompare comp - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) - { return tree_.erase(key, comp); } + size_type erase(const KeyType& key, KeyValueCompare comp); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Returns: An iterator to the element after the erased element. - //! - //! Effects: Erases the element pointed to by pos. - //! Disposer::operator()(pointer) is called for the removed element. - //! - //! Complexity: Average complexity for erase element is constant time. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::splaytree::erase_and_dispose(const_iterator,Disposer) template - iterator erase_and_dispose(const_iterator i, Disposer disposer) - { return tree_.erase_and_dispose(i, disposer); } + iterator erase_and_dispose(const_iterator i, Disposer disposer); - #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + //! @copydoc ::boost::intrusive::splaytree::erase_and_dispose(const_iterator,const_iterator,Disposer) template - iterator erase_and_dispose(iterator i, Disposer disposer) - { return this->erase_and_dispose(const_iterator(i), disposer); } - #endif + iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Returns: An iterator to the element after the erased elements. - //! - //! Effects: Erases the range pointed to by b end e. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Complexity: Average complexity for erase range is amortized - //! O(log(size() + N)), where N is the number of elements in the range. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::splaytree::erase_and_dispose(const_reference, Disposer) template - iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer) - { return tree_.erase_and_dispose(b, e, disposer); } + size_type erase_and_dispose(const_reference value, Disposer disposer); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements with the given value. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: Amortized O(log(size() + this->count(value)). - //! - //! Throws: If the internal value_compare ordering function throws. Basic guarantee. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - template - size_type erase_and_dispose(const_reference value, Disposer disposer) - { return tree_.erase_and_dispose(value, disposer); } - - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements with the given key. - //! according to the comparison functor "comp". - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: Amortized O(log(size() + this->count(key, comp)). - //! - //! Throws: If comp ordering function throws. Basic guarantee. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::splaytree::erase_and_dispose(const KeyType&,KeyValueCompare,Disposer) template - size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) - { return tree_.erase_and_dispose(key, comp, disposer); } + size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer); - //! Effects: Erases all the elements of the container. - //! - //! Complexity: Linear to the number of elements on the container. - //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - void clear() - { return tree_.clear(); } + //! @copydoc ::boost::intrusive::splaytree::clear + void clear(); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements of the container. - //! - //! Complexity: Linear to the number of elements on the container. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. + //! @copydoc ::boost::intrusive::splaytree::clear_and_dispose template - void clear_and_dispose(Disposer disposer) - { return tree_.clear_and_dispose(disposer); } + void clear_and_dispose(Disposer disposer); - //! Effects: Returns the number of contained elements with the given key - //! - //! Complexity: Amortized logarithmic to the number of elements contained plus lineal - //! to number of objects with the given key. - //! - //! Throws: If the internal value_compare ordering function throws. - size_type count(const_reference value) - { return tree_.count(value); } + //! @copydoc ::boost::intrusive::splaytree::count(const_reference) + size_type count(const_reference value); - //! Effects: Returns the number of contained elements with the same key - //! compared with the given comparison functor. - //! - //! Complexity: Amortized logarithmic to the number of elements contained plus lineal - //! to number of objects with the given key. - //! - //! Throws: If comp ordering function throws. + //! @copydoc ::boost::intrusive::splaytree::count(const KeyType&,KeyValueCompare)const template - size_type count(const KeyType& key, KeyValueCompare comp) - { return tree_.count(key, comp); } + size_type count(const KeyType& key, KeyValueCompare comp); - //! Effects: Returns the number of contained elements with the given key - //! - //! Complexity: Logarithmic to the number of elements contained plus lineal - //! to number of objects with the given key. - //! - //! Throws: If the internal value_compare ordering function throws. - size_type count_dont_splay(const_reference value) const - { return tree_.count_dont_splay(value); } + //! @copydoc ::boost::intrusive::splaytree::count(const_reference)const + size_type count(const_reference value) const; - //! Effects: Returns the number of contained elements with the same key - //! compared with the given comparison functor. - //! - //! Complexity: Logarithmic to the number of elements contained plus lineal - //! to number of objects with the given key. - //! - //! Throws: If comp ordering function throws. + //! @copydoc ::boost::intrusive::splaytree::count(const KeyType&,KeyValueCompare)const template - size_type count_dont_splay(const KeyType& key, KeyValueCompare comp) const - { return tree_.count_dont_splay(key, comp); } + size_type count(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Returns an iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Amortized logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - iterator lower_bound(const_reference value) - { return tree_.lower_bound(value); } + //! @copydoc ::boost::intrusive::splaytree::count_dont_splay(const_reference)const + size_type count_dont_splay(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Returns an iterator to the first element whose - //! key according to the comparison functor is not less than k or - //! end() if that element does not exist. - //! - //! Complexity: Amortized logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::splaytree::count_dont_splay(const KeyType&,KeyValueCompare)const template - iterator lower_bound(const KeyType& key, KeyValueCompare comp) - { return tree_.lower_bound(key, comp); } - - //! Effects: Returns a const iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - const_iterator lower_bound_dont_splay(const_reference value) const - { return tree_.lower_bound_dont_splay(value); } - - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Returns a const_iterator to the first element whose - //! key according to the comparison functor is not less than k or - //! end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + 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); + + //! @copydoc ::boost::intrusive::splaytree::lower_bound(const KeyType&,KeyValueCompare) template - const_iterator lower_bound_dont_splay(const KeyType& key, KeyValueCompare comp) const - { return tree_.lower_bound_dont_splay(key, comp); } + iterator lower_bound(const KeyType& key, KeyValueCompare comp); - //! Effects: Returns an iterator to the first element whose - //! key is greater than k or end() if that element does not exist. - //! - //! Complexity: Amortized logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - iterator upper_bound(const_reference value) - { return tree_.upper_bound(value); } + //! @copydoc ::boost::intrusive::splaytree::lower_bound(const_reference)const + const_iterator lower_bound(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Returns an iterator to the first element whose - //! key according to the comparison functor is greater than key or - //! end() if that element does not exist. - //! - //! Complexity: Amortized logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::splaytree::lower_bound(const KeyType&,KeyValueCompare)const template - iterator upper_bound(const KeyType& key, KeyValueCompare comp) - { return tree_.upper_bound(key, comp); } + const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Returns an iterator to the first element whose - //! key is greater than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - const_iterator upper_bound_dont_splay(const_reference value) const - { return tree_.upper_bound_dont_splay(value); } + //! @copydoc ::boost::intrusive::splaytree::lower_bound_dont_splay(const_reference)const + const_iterator lower_bound_dont_splay(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Returns a const_iterator to the first element whose - //! key according to the comparison functor is greater than key or - //! end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::splaytree::lower_bound_dont_splay(const KeyType&,KeyValueCompare)const template - const_iterator upper_bound_dont_splay(const KeyType& key, KeyValueCompare comp) const - { return tree_.upper_bound_dont_splay(key, comp); } + const_iterator lower_bound_dont_splay(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Finds an iterator to the first element whose value is - //! "value" or end() if that element does not exist. - //! - //! Complexity: Amortized logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - iterator find(const_reference value) - { return tree_.find(value); } + //! @copydoc ::boost::intrusive::splaytree::upper_bound(const_reference) + iterator upper_bound(const_reference value); - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Finds an iterator to the first element whose key is - //! "key" according to the comparison functor or end() if that element - //! does not exist. - //! - //! Complexity: Amortized logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::splaytree::upper_bound(const KeyType&,KeyValueCompare) template - iterator find(const KeyType& key, KeyValueCompare comp) - { return tree_.find(key, comp); } + iterator upper_bound(const KeyType& key, KeyValueCompare comp); - //! Effects: Finds a const_iterator to the first element whose value is - //! "value" or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - const_iterator find_dont_splay(const_reference value) const - { return tree_.find_dont_splay(value); } + //! @copydoc ::boost::intrusive::splaytree::upper_bound(const_reference)const + const_iterator upper_bound(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Finds a const_iterator to the first element whose key is - //! "key" according to the comparison functor or end() if that element - //! does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::splaytree::upper_bound(const KeyType&,KeyValueCompare)const template - const_iterator find_dont_splay(const KeyType& key, KeyValueCompare comp) const - { return tree_.find_dont_splay(key, comp); } + const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Amortized logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - std::pair equal_range(const_reference value) - { return tree_.equal_range(value); } + //! @copydoc ::boost::intrusive::splaytree::upper_bound_dont_splay(const_reference)const + const_iterator upper_bound_dont_splay(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Finds a range containing all elements whose key is k - //! according to the comparison functor or an empty range - //! that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Amortized logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::splaytree::upper_bound_dont_splay(const KeyType&,KeyValueCompare)const template - std::pair equal_range(const KeyType& key, KeyValueCompare comp) - { return tree_.equal_range(key, comp); } + const_iterator upper_bound_dont_splay(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. + //! @copydoc ::boost::intrusive::splaytree::find(const_reference) + iterator find(const_reference value); + + //! @copydoc ::boost::intrusive::splaytree::find(const KeyType&,KeyValueCompare) + template + iterator find(const KeyType& key, KeyValueCompare comp); + + //! @copydoc ::boost::intrusive::splaytree::find(const_reference)const + const_iterator find(const_reference value) const; + + //! @copydoc ::boost::intrusive::splaytree::find(const KeyType&,KeyValueCompare)const + 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); + + //! @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 std::pair - equal_range_dont_splay(const_reference value) const - { return tree_.equal_range_dont_splay(value); } + equal_range(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Finds a range containing all elements whose key is k - //! according to the comparison functor or an empty range - //! that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::splaytree::equal_range(const KeyType&,KeyValueCompare)const template std::pair - equal_range_dont_splay(const KeyType& key, KeyValueCompare comp) const - { return tree_.equal_range_dont_splay(key, comp); } + equal_range(const KeyType& key, KeyValueCompare comp) const; - //! Requires: 'lower_value' must not be greater than 'upper_value'. If - //! 'lower_value' == 'upper_value', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise - //! - //! second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the predicate throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_value and upper_value. + //! @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) - { return tree_.bounded_range(lower_value, upper_value, left_closed, right_closed); } + (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); - //! Requires: KeyValueCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. - //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If - //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key, comp) if left_closed, upper_bound(lower_key, comp) otherwise - //! - //! second = upper_bound(upper_key, comp) if right_closed, lower_bound(upper_key, comp) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_key and upper_key. + //! @copydoc ::boost::intrusive::splaytree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool) template std::pair bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) - { return tree_.bounded_range(lower_key, upper_key, comp, left_closed, right_closed); } + (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed); - //! Requires: 'lower_value' must not be greater than 'upper_value'. If - //! 'lower_value' == 'upper_value', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise - //! - //! second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the predicate throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_value and upper_value. - std::pair - bounded_range_dont_splay - (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const - { return tree_.bounded_range_dont_splay(lower_value, upper_value, left_closed, right_closed); } + //! @copydoc ::boost::intrusive::splaytree::bounded_range(const_reference,const_reference,bool,bool)const + std::pair bounded_range + (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; - //! Requires: KeyValueCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. - //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If - //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key, comp) if left_closed, upper_bound(lower_key, comp) otherwise - //! - //! second = upper_bound(upper_key, comp) if right_closed, lower_bound(upper_key, comp) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_key and upper_key. + //! @copydoc ::boost::intrusive::splaytree::bounded_range(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 - { return tree_.bounded_range_dont_splay(lower_key, upper_key, comp, left_closed, right_closed); } + std::pair bounded_range + (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; - //! Requires: value must be an lvalue and shall be in a set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid iterator i belonging to the set - //! that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This static function is available only if the value traits - //! is stateless. - static iterator s_iterator_to(reference value) - { return tree_type::s_iterator_to(value); } + //! @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; - //! Requires: value must be an lvalue and shall be in a set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid const_iterator i belonging to the - //! set that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This static function is available only if the value traits - //! is stateless. - static const_iterator s_iterator_to(const_reference value) - { return tree_type::s_iterator_to(value); } + //! @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; - //! Requires: value must be an lvalue and shall be in a set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid iterator i belonging to the set - //! that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator iterator_to(reference value) - { return tree_.iterator_to(value); } + //! @copydoc ::boost::intrusive::splaytree::s_iterator_to(reference) + static iterator s_iterator_to(reference value); - //! Requires: value must be an lvalue and shall be in a set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid const_iterator i belonging to the - //! set that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator iterator_to(const_reference value) const - { return tree_.iterator_to(value); } + //! @copydoc ::boost::intrusive::splaytree::s_iterator_to(const_reference) + static const_iterator s_iterator_to(const_reference value); - //! Requires: value shall not be in a set/splay_multiset. - //! - //! Effects: init_node puts the hook of a value in a well-known default - //! state. - //! - //! Throws: Nothing. - //! - //! Complexity: Constant time. - //! - //! Note: This function puts the hook in the well-known default state - //! used by auto_unlink and safe hooks. - static void init_node(reference value) - { tree_type::init_node(value); } + //! @copydoc ::boost::intrusive::splaytree::iterator_to(reference) + iterator iterator_to(reference value); - //! Effects: Unlinks the leftmost node from the tree. - //! - //! Complexity: Average complexity is constant time. - //! - //! Throws: Nothing. - //! - //! Notes: This function breaks the tree and the tree can - //! only be used for more unlink_leftmost_without_rebalance calls. - //! This function is normally used to achieve a step by step - //! controlled destruction of the tree. - pointer unlink_leftmost_without_rebalance() - { return tree_.unlink_leftmost_without_rebalance(); } + //! @copydoc ::boost::intrusive::splaytree::iterator_to(const_reference)const + const_iterator iterator_to(const_reference value) const; - //! Requires: replace_this must be a valid iterator of *this - //! and with_this must not be inserted in any tree. - //! - //! Effects: Replaces replace_this in its position in the - //! tree with with_this. The tree does not need to be rebalanced. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This function will break container ordering invariants if - //! with_this is not equivalent to *replace_this according to the - //! ordering rules. This function is faster than erasing and inserting - //! the node, since no rebalancing or comparison is needed. - void replace_node(iterator replace_this, reference with_this) - { tree_.replace_node(replace_this, with_this); } + //! @copydoc ::boost::intrusive::splaytree::init_node(reference) + static void init_node(reference value); - //! Requires: i must be a valid iterator of *this. - //! - //! Effects: Rearranges the splay set so that the element pointed by i - //! is placed as the root of the tree, improving future searches of this value. - //! - //! Complexity: Amortized logarithmic. - //! - //! Throws: Nothing. - void splay_up(iterator i) - { tree_.splay_up(i); } + //! @copydoc ::boost::intrusive::splaytree::unlink_leftmost_without_rebalance + pointer unlink_leftmost_without_rebalance(); - //! Effects: Rearranges the splay set so that if *this stores an element - //! with a key equivalent to value the element is placed as the root of the - //! tree. If the element is not present returns the last node compared with the key. - //! If the tree is empty, end() is returned. - //! - //! Complexity: Amortized logarithmic. - //! - //! Returns: An iterator to the new root of the tree, end() if the tree is empty. - //! - //! Throws: If the comparison functor throws. - template - iterator splay_down(const KeyType &key, KeyNodePtrCompare comp) - { return tree_.splay_down(key, comp); } + //! @copydoc ::boost::intrusive::splaytree::replace_node + void replace_node(iterator replace_this, reference with_this); - //! Effects: Rearranges the splay set so that if *this stores an element - //! with a key equivalent to value the element is placed as the root of the - //! tree. - //! - //! Complexity: Amortized logarithmic. - //! - //! Returns: An iterator to the new root of the tree, end() if the tree is empty. - //! - //! Throws: If the predicate throws. - iterator splay_down(const value_type &value) - { return tree_.splay_down(value); } + //! @copydoc ::boost::intrusive::splaytree::remove_node + void remove_node(reference value); - //! Effects: Rebalances the tree. - //! - //! Throws: Nothing. - //! - //! Complexity: Linear. - void rebalance() - { tree_.rebalance(); } + //! @copydoc ::boost::intrusive::splaytree::splay_up(iterator) + void splay_up(iterator i); - //! Requires: old_root is a node of a tree. - //! - //! Effects: Rebalances the subtree rooted at old_root. - //! - //! Returns: The new root of the subtree. - //! - //! Throws: Nothing. - //! - //! Complexity: Linear to the elements in the subtree. - iterator rebalance_subtree(iterator root) - { return tree_.rebalance_subtree(root); } + //! @copydoc ::boost::intrusive::splaytree::splay_down(const KeyType&,KeyValueCompare) + template + iterator splay_down(const KeyType &key, KeyValueCompare comp); - /// @cond - friend bool operator==(const splay_multiset_impl &x, const splay_multiset_impl &y) - { return x.tree_ == y.tree_; } + //! @copydoc ::boost::intrusive::splaytree::splay_down(const_reference) + iterator splay_down(const_reference value); + + //! @copydoc ::boost::intrusive::splaytree::rebalance + void rebalance(); - friend bool operator<(const splay_multiset_impl &x, const splay_multiset_impl &y) - { return x.tree_ < y.tree_; } - /// @endcond + //! @copydoc ::boost::intrusive::splaytree::rebalance_subtree + iterator rebalance_subtree(iterator root); + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED }; #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator!= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const splay_multiset_impl &x, const splay_multiset_impl &y) -#else -(const splay_multiset_impl &x, const splay_multiset_impl &y) -#endif -{ return !(x == y); } -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator> -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const splay_multiset_impl &x, const splay_multiset_impl &y) -#else -(const splay_multiset_impl &x, const splay_multiset_impl &y) -#endif -{ return y < x; } +bool operator!= (const splay_multiset_impl &x, const splay_multiset_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator<= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const splay_multiset_impl &x, const splay_multiset_impl &y) -#else -(const splay_multiset_impl &x, const splay_multiset_impl &y) -#endif -{ return !(y < x); } +bool operator>(const splay_multiset_impl &x, const splay_multiset_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator>= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const splay_multiset_impl &x, const splay_multiset_impl &y) -#else -(const splay_multiset_impl &x, const splay_multiset_impl &y) -#endif -{ return !(x < y); } +bool operator<=(const splay_multiset_impl &x, const splay_multiset_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline void swap -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(splay_multiset_impl &x, splay_multiset_impl &y) -#else -(splay_multiset_impl &x, splay_multiset_impl &y) -#endif -{ x.swap(y); } +bool operator>=(const splay_multiset_impl &x, const splay_multiset_impl &y); + +template +void swap(splay_multiset_impl &x, splay_multiset_impl &y); + +#endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Helper metafunction to define a \c splay_multiset that yields to the same type when the //! same options (either explicitly or implicitly) are used. #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else -template +template #endif struct make_splay_multiset { /// @cond + typedef typename pack_options + < splaytree_defaults, + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3, O4 + #else + Options... + #endif + >::type packed_options; + + typedef typename detail::get_value_traits + ::type value_traits; + typedef splay_multiset_impl - < typename make_splaytree_opt::type - > implementation_defined; + < value_traits + , typename packed_options::compare + , typename packed_options::size_type + , packed_options::constant_time_size + > implementation_defined; /// @endcond typedef implementation_defined type; }; @@ -2507,21 +992,21 @@ template #endif class splay_multiset : public make_splay_multiset::type { - typedef typename make_splay_multiset - ::type Base; + BOOST_MOVABLE_BUT_NOT_COPYABLE(splay_multiset) public: @@ -2550,7 +1035,7 @@ class splay_multiset {} splay_multiset& operator=(BOOST_RV_REF(splay_multiset) x) - { this->Base::operator=(::boost::move(static_cast(x))); return *this; } + { return static_cast(this->Base::operator=(::boost::move(static_cast(x)))); } static splay_multiset &container_from_end_iterator(iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } diff --git a/include/boost/intrusive/splay_set_hook.hpp b/include/boost/intrusive/splay_set_hook.hpp index c8698c6..c78b4a3 100644 --- a/include/boost/intrusive/splay_set_hook.hpp +++ b/include/boost/intrusive/splay_set_hook.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 @@ -14,49 +14,37 @@ #define BOOST_INTRUSIVE_SPLAY_SET_HOOK_HPP #include -#include -#include -#include -#include -#include -#include +#include namespace boost { namespace intrusive { -/// @cond -template -struct get_splay_set_node_algo -{ - typedef splaytree_algorithms > type; -}; -/// @endcond - //! 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 +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 pack_options - < hook_defaults, + typedef typename make_bs_set_base_hook + < #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) O1, O2, O3 #else Options... #endif - >::type packed_options; - - typedef detail::generic_hook - < get_splay_set_node_algo - , typename packed_options::tag - , packed_options::link_mode - , detail::SplaySetBaseHook - > implementation_defined; + >::type implementation_defined; /// @endcond typedef implementation_defined type; }; @@ -78,6 +66,8 @@ struct make_splay_set_base_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 @@ -162,29 +152,31 @@ class splay_set_base_hook //! 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 +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 pack_options - < hook_defaults, + typedef typename make_bs_set_member_hook + < #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) O1, O2, O3 #else Options... #endif - >::type packed_options; - - typedef detail::generic_hook - < get_splay_set_node_algo - , member_tag - , packed_options::link_mode - , detail::NoBaseHook - > implementation_defined; + >::type implementation_defined; /// @endcond typedef implementation_defined type; }; @@ -202,6 +194,8 @@ struct make_splay_set_member_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 diff --git a/include/boost/intrusive/splaytree.hpp b/include/boost/intrusive/splaytree.hpp index 7c599b7..6fa1d47 100644 --- a/include/boost/intrusive/splaytree.hpp +++ b/include/boost/intrusive/splaytree.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 @@ -13,53 +13,41 @@ #define BOOST_INTRUSIVE_SPLAYTREE_HPP #include +#include #include #include #include -#include -#include + #include #include #include -#include #include +#include #include #include -#include #include -#include #include +#include +#include +#include #include #include #include #include - namespace boost { namespace intrusive { /// @cond -template -struct splaysetopt +struct splaytree_defaults { - typedef ValueTraits value_traits; - typedef Compare compare; - typedef SizeType size_type; - static const bool constant_time_size = ConstantTimeSize; + typedef detail::default_bstree_hook proto_value_traits; + static const bool constant_time_size = true; + typedef std::size_t size_type; + typedef void compare; }; -template -struct splay_set_defaults - : pack_options - < none - , base_hook - , constant_time_size - , size_type - , compare > - >::type -{}; - /// @endcond //! The class template splaytree is an intrusive splay tree container that @@ -78,866 +66,245 @@ struct splay_set_defaults #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class splaytree_impl - : private detail::clear_on_destructor_base > -{ - template friend class detail::clear_on_destructor_base; - public: - typedef typename Config::value_traits value_traits; /// @cond - static const bool external_value_traits = - detail::external_value_traits_bool_is_true::value; - typedef typename detail::eval_if_c - < external_value_traits - , detail::eval_value_traits - , detail::identity - >::type real_value_traits; + : public bstree_impl + /// @endcond +{ + public: + typedef ValueTraits value_traits; + /// @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 - typedef typename real_value_traits::pointer pointer; - typedef typename real_value_traits::const_pointer const_pointer; - typedef typename pointer_traits::element_type value_type; - typedef typename pointer_traits::reference reference; - typedef typename pointer_traits::reference const_reference; - typedef typename pointer_traits::difference_type difference_type; - typedef typename Config::size_type size_type; - typedef value_type key_type; - typedef typename Config::compare value_compare; - typedef value_compare key_compare; - typedef tree_iterator iterator; - typedef tree_iterator const_iterator; - typedef boost::intrusive::detail::reverse_iterator reverse_iterator; - typedef boost::intrusive::detail::reverse_iteratorconst_reverse_iterator; - typedef typename real_value_traits::node_traits node_traits; - typedef typename node_traits::node node; - typedef typename pointer_traits - ::template rebind_pointer - ::type node_ptr; - typedef typename pointer_traits - ::template rebind_pointer - ::type const_node_ptr; - typedef splaytree_algorithms node_algorithms; - static const bool constant_time_size = Config::constant_time_size; - static const bool stateful_value_traits = detail::is_stateful_value_traits::value; + typedef typename implementation_defined::pointer pointer; + typedef typename implementation_defined::const_pointer const_pointer; + typedef typename implementation_defined::value_type value_type; + typedef typename implementation_defined::key_type key_type; + typedef typename implementation_defined::reference reference; + typedef typename implementation_defined::const_reference const_reference; + typedef typename implementation_defined::difference_type difference_type; + typedef typename implementation_defined::size_type size_type; + typedef typename implementation_defined::value_compare value_compare; + typedef typename implementation_defined::key_compare key_compare; + typedef typename implementation_defined::iterator iterator; + typedef typename implementation_defined::const_iterator const_iterator; + typedef typename implementation_defined::reverse_iterator reverse_iterator; + typedef typename implementation_defined::const_reverse_iterator const_reverse_iterator; + typedef typename implementation_defined::node_traits node_traits; + typedef typename implementation_defined::node node; + typedef typename implementation_defined::node_ptr node_ptr; + typedef typename implementation_defined::const_node_ptr const_node_ptr; + typedef typename implementation_defined::node_algorithms node_algorithms; + static const bool constant_time_size = implementation_defined::constant_time_size; /// @cond private: - typedef detail::size_holder size_traits; //noncopyable BOOST_MOVABLE_BUT_NOT_COPYABLE(splaytree_impl) - enum { safemode_or_autounlink = - (int)real_value_traits::link_mode == (int)auto_unlink || - (int)real_value_traits::link_mode == (int)safe_link }; - - //Constant-time size is incompatible with auto-unlink hooks! - BOOST_STATIC_ASSERT(!(constant_time_size && ((int)real_value_traits::link_mode == (int)auto_unlink))); - - struct header_plus_size : public size_traits - { node header_; }; - - struct node_plus_pred_t : public detail::ebo_functor_holder - { - node_plus_pred_t(const value_compare &comp) - : detail::ebo_functor_holder(comp) - {} - header_plus_size header_plus_size_; - }; - - struct data_t : public splaytree_impl::value_traits - { - typedef typename splaytree_impl::value_traits value_traits; - data_t(const value_compare & comp, const value_traits &val_traits) - : value_traits(val_traits), node_plus_pred_(comp) - {} - node_plus_pred_t node_plus_pred_; - } data_; - - const value_compare &priv_comp() const - { return data_.node_plus_pred_.get(); } - - value_compare &priv_comp() - { return data_.node_plus_pred_.get(); } - - const value_traits &priv_value_traits() const - { return data_; } - - value_traits &priv_value_traits() - { return data_; } - - node_ptr priv_header_ptr() - { return pointer_traits::pointer_to(data_.node_plus_pred_.header_plus_size_.header_); } - - const_node_ptr priv_header_ptr() const - { return pointer_traits::pointer_to(data_.node_plus_pred_.header_plus_size_.header_); } - - static node_ptr uncast(const const_node_ptr & ptr) - { return pointer_traits::const_cast_from(ptr); } - - size_traits &priv_size_traits() - { return data_.node_plus_pred_.header_plus_size_; } - - const size_traits &priv_size_traits() const - { return data_.node_plus_pred_.header_plus_size_; } - - const real_value_traits &get_real_value_traits(detail::bool_) const - { return data_; } - - const real_value_traits &get_real_value_traits(detail::bool_) const - { return data_.get_value_traits(*this); } - - real_value_traits &get_real_value_traits(detail::bool_) - { return data_; } - - real_value_traits &get_real_value_traits(detail::bool_) - { return data_.get_value_traits(*this); } - /// @endcond public: - const real_value_traits &get_real_value_traits() const - { return this->get_real_value_traits(detail::bool_()); } + typedef typename implementation_defined::insert_commit_data insert_commit_data; - real_value_traits &get_real_value_traits() - { return this->get_real_value_traits(detail::bool_()); } + //! @copydoc ::boost::intrusive::bstree::bstree(const value_compare &,const value_traits &) + explicit splaytree_impl( const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : tree_type(cmp, v_traits) + {} - typedef typename node_algorithms::insert_commit_data insert_commit_data; - - //! Effects: Constructs an empty tree. - //! - //! Complexity: Constant. - //! - //! Throws: If value_traits::node_traits::node - //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) - //! or the copy constructorof the value_compare object throws. Basic guarantee. - explicit splaytree_impl( const value_compare &cmp = value_compare() - , const value_traits &v_traits = value_traits()) - : data_(cmp, v_traits) - { - node_algorithms::init_header(this->priv_header_ptr()); - this->priv_size_traits().set_size(size_type(0)); - } - - //! Requires: Dereferencing iterator must yield an lvalue of type value_type. - //! cmp must be a comparison function that induces a strict weak ordering. - //! - //! Effects: Constructs an empty tree and inserts elements from - //! [b, e). - //! - //! Complexity: Linear in N if [b, e) is already sorted using - //! comp and otherwise amortized N * log N, where N is the distance between first and last. - //! - //! Throws: If value_traits::node_traits::node - //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) - //! or the copy constructor/operator() of the value_compare object throws. Basic guarantee. + //! @copydoc ::boost::intrusive::bstree::bstree(bool,Iterator,Iterator,const value_compare &,const value_traits &) template - splaytree_impl ( bool unique, Iterator b, Iterator e - , const value_compare &cmp = value_compare() - , const value_traits &v_traits = value_traits()) - : data_(cmp, v_traits) + splaytree_impl( bool unique, Iterator b, Iterator e + , const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : tree_type(cmp, v_traits) { - node_algorithms::init_header(this->priv_header_ptr()); - this->priv_size_traits().set_size(size_type(0)); if(unique) this->insert_unique(b, e); else this->insert_equal(b, e); } - //! Effects: to-do - //! + //! @copydoc ::boost::intrusive::bstree::bstree(bstree &&) splaytree_impl(BOOST_RV_REF(splaytree_impl) x) - : data_(::boost::move(x.priv_comp()), ::boost::move(x.priv_value_traits())) - { - node_algorithms::init_header(this->priv_header_ptr()); - this->priv_size_traits().set_size(size_type(0)); - this->swap(x); - } - - //! Effects: to-do - //! - splaytree_impl& operator=(BOOST_RV_REF(splaytree_impl) x) - { this->swap(x); return *this; } - - //! Effects: Detaches all elements from this. The objects in the set - //! are not deleted (i.e. no destructors are called), but the nodes according to - //! the value_traits template parameter are reinitialized and thus can be reused. - //! - //! Complexity: Linear to the number of elements on the container. - //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. - //! - //! Throws: Nothing. - ~splaytree_impl() + : tree_type(::boost::move(static_cast(x))) {} - //! Effects: Returns an iterator pointing to the beginning of the tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator begin() - { return iterator(node_algorithms::begin_node(this->priv_header_ptr()), this); } + //! @copydoc ::boost::intrusive::bstree::operator=(bstree &&) + splaytree_impl& operator=(BOOST_RV_REF(splaytree_impl) x) + { return static_cast(tree_type::operator=(::boost::move(static_cast(x)))); } - //! Effects: Returns a const_iterator pointing to the beginning of the tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator begin() const - { return cbegin(); } + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::bstree::~bstree() + ~splaytree_impl(); - //! Effects: Returns a const_iterator pointing to the beginning of the tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator cbegin() const - { return const_iterator(node_algorithms::begin_node(this->priv_header_ptr()), this); } + //! @copydoc ::boost::intrusive::bstree::begin() + iterator begin(); - //! Effects: Returns an iterator pointing to the end of the tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator end() - { return iterator (this->priv_header_ptr(), this); } + //! @copydoc ::boost::intrusive::bstree::begin()const + const_iterator begin() const; - //! Effects: Returns a const_iterator pointing to the end of the tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator end() const - { return cend(); } + //! @copydoc ::boost::intrusive::bstree::cbegin()const + const_iterator cbegin() const; - //! Effects: Returns a const_iterator pointing to the end of the tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator cend() const - { return const_iterator (uncast(this->priv_header_ptr()), this); } + //! @copydoc ::boost::intrusive::bstree::end() + iterator end(); - //! Effects: Returns a reverse_iterator pointing to the beginning of the - //! reversed tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - reverse_iterator rbegin() - { return reverse_iterator(end()); } + //! @copydoc ::boost::intrusive::bstree::end()const + const_iterator end() const; - //! Effects: Returns a const_reverse_iterator pointing to the beginning - //! of the reversed tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator rbegin() const - { return const_reverse_iterator(end()); } + //! @copydoc ::boost::intrusive::bstree::cend()const + const_iterator cend() const; - //! Effects: Returns a const_reverse_iterator pointing to the beginning - //! of the reversed tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator crbegin() const - { return const_reverse_iterator(end()); } + //! @copydoc ::boost::intrusive::bstree::rbegin() + reverse_iterator rbegin(); - //! Effects: Returns a reverse_iterator pointing to the end - //! of the reversed tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - reverse_iterator rend() - { return reverse_iterator(begin()); } + //! @copydoc ::boost::intrusive::bstree::rbegin()const + const_reverse_iterator rbegin() const; - //! Effects: Returns a const_reverse_iterator pointing to the end - //! of the reversed tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator rend() const - { return const_reverse_iterator(begin()); } + //! @copydoc ::boost::intrusive::bstree::crbegin()const + const_reverse_iterator crbegin() const; - //! Effects: Returns a const_reverse_iterator pointing to the end - //! of the reversed tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator crend() const - { return const_reverse_iterator(begin()); } + //! @copydoc ::boost::intrusive::bstree::rend() + reverse_iterator rend(); - //! Precondition: end_iterator must be a valid end iterator - //! of splaytree. - //! - //! Effects: Returns a const reference to the splaytree associated to the end iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - static splaytree_impl &container_from_end_iterator(iterator end_iterator) - { return priv_container_from_end_iterator(end_iterator); } + //! @copydoc ::boost::intrusive::bstree::rend()const + const_reverse_iterator rend() const; - //! Precondition: end_iterator must be a valid end const_iterator - //! of splaytree. - //! - //! Effects: Returns a const reference to the splaytree associated to the end iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - static const splaytree_impl &container_from_end_iterator(const_iterator end_iterator) - { return priv_container_from_end_iterator(end_iterator); } + //! @copydoc ::boost::intrusive::bstree::crend()const + const_reverse_iterator crend() const; - //! Precondition: it must be a valid iterator - //! of rbtree. - //! - //! Effects: Returns a const reference to the tree associated to the iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Logarithmic. - static splaytree_impl &container_from_iterator(iterator it) - { return priv_container_from_iterator(it); } + //! @copydoc ::boost::intrusive::bstree::container_from_end_iterator(iterator) + static splaytree_impl &container_from_end_iterator(iterator end_iterator); - //! Precondition: it must be a valid end const_iterator - //! of rbtree. - //! - //! Effects: Returns a const reference to the tree associated to the iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Logarithmic. - static const splaytree_impl &container_from_iterator(const_iterator it) - { return priv_container_from_iterator(it); } + //! @copydoc ::boost::intrusive::bstree::container_from_end_iterator(const_iterator) + static const splaytree_impl &container_from_end_iterator(const_iterator end_iterator); - //! Effects: Returns the value_compare object used by the tree. - //! - //! Complexity: Constant. - //! - //! Throws: If value_compare copy-constructor throws. - value_compare value_comp() const - { return priv_comp(); } + //! @copydoc ::boost::intrusive::bstree::container_from_iterator(iterator) + static splaytree_impl &container_from_iterator(iterator it); - //! Effects: Returns true if the container is empty. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - bool empty() const - { return this->cbegin() == this->cend(); } + //! @copydoc ::boost::intrusive::bstree::container_from_iterator(const_iterator) + static const splaytree_impl &container_from_iterator(const_iterator it); - //! Effects: Returns the number of elements stored in the tree. - //! - //! Complexity: Linear to elements contained in *this - //! if constant-time size option is disabled. Constant time otherwise. - //! - //! Throws: Nothing. - size_type size() const - { - if(constant_time_size){ - return this->priv_size_traits().get_size(); - } - else{ - return (size_type)node_algorithms::size(this->priv_header_ptr()); - } - } + //! @copydoc ::boost::intrusive::bstree::key_comp()const + key_compare key_comp() const; - //! Effects: Swaps the contents of two splaytrees. - //! - //! Complexity: Constant. - //! - //! Throws: If the comparison functor's swap call throws. - void swap(splaytree_impl& other) - { - //This can throw - using std::swap; - swap(priv_comp(), priv_comp()); - //These can't throw - node_algorithms::swap_tree(this->priv_header_ptr(), other.priv_header_ptr()); - if(constant_time_size){ - size_type backup = this->priv_size_traits().get_size(); - this->priv_size_traits().set_size(other.priv_size_traits().get_size()); - other.priv_size_traits().set_size(backup); - } - } + //! @copydoc ::boost::intrusive::bstree::value_comp()const + value_compare value_comp() const; - //! Requires: value must be an lvalue - //! - //! Effects: Inserts value into the tree before the lower bound. - //! - //! Complexity: Average complexity for insert element is amortized - //! logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. Strong guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. - iterator insert_equal(reference value) - { - detail::key_nodeptr_comp - key_node_comp(priv_comp(), this); - node_ptr to_insert(get_real_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_lower_bound - (this->priv_header_ptr(), to_insert, key_node_comp), this); - this->priv_size_traits().increment(); - return ret; - } + //! @copydoc ::boost::intrusive::bstree::empty()const + bool empty() const; - //! Requires: value must be an lvalue, and "hint" must be - //! a valid iterator. - //! - //! Effects: Inserts x into the tree, using "hint" as a hint to - //! where it will be inserted. If "hint" is the upper_bound - //! the insertion takes constant time (two comparisons in the worst case) - //! - //! Complexity: Amortized logarithmic in general, but it is amortized - //! constant time if t is inserted immediately before hint. - //! - //! Throws: If the internal value_compare ordering function throws. Strong guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. - iterator insert_equal(const_iterator hint, reference value) - { - detail::key_nodeptr_comp - key_node_comp(priv_comp(), this); - node_ptr to_insert(get_real_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->priv_header_ptr(), hint.pointed_node(), to_insert, key_node_comp), this); - this->priv_size_traits().increment(); - return ret; - } + //! @copydoc ::boost::intrusive::bstree::size()const + size_type size() const; - //! Requires: Dereferencing iterator must yield an lvalue - //! of type value_type. - //! - //! Effects: Inserts a each element of a range into the tree - //! before the upper bound of the key of each element. - //! - //! Complexity: Insert range is in general amortized O(N * log(N)), where N is the - //! size of the range. However, it is linear in N if the range is already sorted - //! by value_comp(). - //! - //! Throws: Nothing. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + //! @copydoc ::boost::intrusive::bstree::swap + void swap(splaytree_impl& other); + + //! @copydoc ::boost::intrusive::bstree::clone_from + template + void clone_from(const splaytree_impl &src, Cloner cloner, Disposer disposer); + + //! @copydoc ::boost::intrusive::bstree::insert_equal(reference) + iterator insert_equal(reference value); + + //! @copydoc ::boost::intrusive::bstree::insert_equal(const_iterator,reference) + iterator insert_equal(const_iterator hint, reference value); + + //! @copydoc ::boost::intrusive::bstree::insert_equal(Iterator,Iterator) template - void insert_equal(Iterator b, Iterator e) - { - if(this->empty()){ - iterator iend(this->end()); - for (; b != e; ++b) - this->insert_equal(iend, *b); - } - } + void insert_equal(Iterator b, Iterator e); - //! Requires: value must be an lvalue - //! - //! Effects: Inserts value into the tree if the value - //! is not already present. - //! - //! Complexity: Amortized logarithmic. - //! - //! Throws: Nothing. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. - std::pair insert_unique(reference value) - { - insert_commit_data commit_data; - std::pair ret = insert_unique_check(value, priv_comp(), commit_data); - if(!ret.second) - return ret; - return std::pair (insert_unique_commit(value, commit_data), true); - } + //! @copydoc ::boost::intrusive::bstree::insert_unique(reference) + std::pair insert_unique(reference value); - //! Requires: value must be an lvalue, and "hint" must be - //! a valid iterator - //! - //! Effects: Tries to insert x into the tree, using "hint" as a hint - //! to where it will be inserted. - //! - //! Complexity: Amortized logarithmic in general, but it is amortized - //! constant time (two comparisons in the worst case) - //! if t is inserted immediately before hint. - //! - //! Throws: Nothing. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. - iterator insert_unique(const_iterator hint, reference value) - { - insert_commit_data commit_data; - std::pair ret = insert_unique_check(hint, value, priv_comp(), commit_data); - if(!ret.second) - return ret.first; - return insert_unique_commit(value, commit_data); - } + //! @copydoc ::boost::intrusive::bstree::insert_unique(const_iterator,reference) + iterator insert_unique(const_iterator hint, reference value); - //! Requires: Dereferencing iterator must yield an lvalue - //! of type value_type. - //! - //! Effects: Tries to insert each element of a range into the tree. - //! - //! Complexity: Insert range is in general amortized O(N * log(N)), where N is the - //! size of the range. However, it is linear in N if the range is already sorted - //! by value_comp(). - //! - //! Throws: Nothing. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. - template - void insert_unique(Iterator b, Iterator e) - { - for (; b != e; ++b) - this->insert_unique(*b); - } - - //! Requires: key_value_comp must be a comparison function that induces - //! the same strict weak ordering as value_compare. The difference is that - //! key_value_comp compares an arbitrary key with the contained values. - //! - //! Effects: Checks if a value can be inserted in the container, using - //! a user provided key instead of the value itself. - //! - //! Returns: If there is an equivalent value - //! returns a pair containing an iterator to the already present value - //! and false. If the value can be inserted returns true in the returned - //! pair boolean and fills "commit_data" that is meant to be used with - //! the "insert_commit" function. - //! - //! Complexity: Average complexity is at most logarithmic. - //! - //! Throws: If the key_value_comp ordering function throws. Strong guarantee. - //! - //! Notes: This function is used to improve performance when constructing - //! a value_type is expensive: if there is an equivalent value - //! the constructed object must be discarded. Many times, the part of the - //! node that is used to impose the order is much cheaper to construct - //! than the value_type and this function offers the possibility to use that - //! part to check if the insertion will be successful. - //! - //! If the check is successful, the user can construct the value_type and use - //! "insert_commit" to insert the object in constant-time. This gives a total - //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)). - //! - //! "commit_data" remains valid for a subsequent "insert_commit" only if no more - //! objects are inserted or erased from the container. + //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const KeyType&,KeyValueCompare,insert_commit_data&) template 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); - std::pair ret = - (node_algorithms::insert_unique_check - (this->priv_header_ptr(), key, comp, commit_data)); - return std::pair(iterator(ret.first, this), ret.second); - } + (const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data); - //! Requires: key_value_comp must be a comparison function that induces - //! the same strict weak ordering as value_compare. The difference is that - //! key_value_comp compares an arbitrary key with the contained values. - //! - //! Effects: Checks if a value can be inserted in the container, using - //! a user provided key instead of the value itself, using "hint" - //! as a hint to where it will be inserted. - //! - //! Returns: If there is an equivalent value - //! returns a pair containing an iterator to the already present value - //! and false. If the value can be inserted returns true in the returned - //! pair boolean and fills "commit_data" that is meant to be used with - //! the "insert_commit" function. - //! - //! Complexity: Logarithmic in general, but it's amortized - //! constant time if t is inserted immediately before hint. - //! - //! Throws: If the key_value_comp ordering function throws. Strong guarantee. - //! - //! Notes: This function is used to improve performance when constructing - //! a value_type is expensive: if there is an equivalent value - //! the constructed object must be discarded. Many times, the part of the - //! constructing that is used to impose the order is much cheaper to construct - //! than the value_type and this function offers the possibility to use that key - //! to check if the insertion will be successful. - //! - //! If the check is successful, the user can construct the value_type and use - //! "insert_commit" to insert the object in constant-time. This can give a total - //! constant-time complexity to the insertion: check(O(1)) + commit(O(1)). - //! - //! "commit_data" remains valid for a subsequent "insert_commit" only if no more - //! objects are inserted or erased from the container. + //! @copydoc ::boost::intrusive::bstree::insert_unique_check(const_iterator,const KeyType&,KeyValueCompare,insert_commit_data&) template std::pair insert_unique_check (const_iterator hint, const KeyType &key - ,KeyValueCompare key_value_comp, insert_commit_data &commit_data) - { - detail::key_nodeptr_comp - comp(key_value_comp, this); - std::pair ret = - node_algorithms::insert_unique_check - (this->priv_header_ptr(), hint.pointed_node(), key, comp, commit_data); - return std::pair(iterator(ret.first, this), ret.second); - } + ,KeyValueCompare key_value_comp, insert_commit_data &commit_data); - //! Requires: value must be an lvalue of type value_type. commit_data - //! must have been obtained from a previous call to "insert_check". - //! No objects should have been inserted or erased from the container between - //! the "insert_check" that filled "commit_data" and the call to "insert_commit". - //! - //! Effects: Inserts the value in the avl_set using the information obtained - //! from the "commit_data" that a previous "insert_check" filled. - //! - //! Returns: An iterator to the newly inserted object. - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Notes: This function has only sense if a "insert_check" has been - //! previously executed to fill "commit_data". No value should be inserted or - //! 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(get_real_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->priv_header_ptr(), to_insert, commit_data); - this->priv_size_traits().increment(); - return iterator(to_insert, this); - } + //! @copydoc ::boost::intrusive::bstree::insert_unique_commit + iterator insert_unique_commit(reference value, const insert_commit_data &commit_data); - //! Effects: Erases the element pointed to by pos. - //! - //! Complexity: Average complexity for erase element is constant time. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - iterator erase(const_iterator i) - { - const_iterator ret(i); - ++ret; - node_ptr to_erase(i.pointed_node()); - if(safemode_or_autounlink) - BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!node_algorithms::unique(to_erase)); - node_algorithms::erase(this->priv_header_ptr(), to_erase); - this->priv_size_traits().decrement(); - if(safemode_or_autounlink) - node_algorithms::init(to_erase); - return ret.unconst(); - } + //! @copydoc ::boost::intrusive::bstree::insert_unique(Iterator,Iterator) + template + void insert_unique(Iterator b, Iterator e); - //! Effects: Erases the range pointed to by b end e. - //! - //! Complexity: Average complexity for erase range is amortized - //! O(log(size() + N)), where N is the number of elements in the range. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - iterator erase(const_iterator b, const_iterator e) - { size_type n; return private_erase(b, e, n); } + //! @copydoc ::boost::intrusive::bstree::insert_before + iterator insert_before(const_iterator pos, reference value); - //! Effects: Erases all the elements with the given value. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: Amortized O(log(size() + N). - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - size_type erase(const_reference value) - { return this->erase(value, priv_comp()); } + //! @copydoc ::boost::intrusive::bstree::push_back + void push_back(reference value); - //! Effects: Erases all the elements with the given key. - //! according to the comparison functor "comp". - //! - //! Returns: The number of erased elements. - //! - //! Complexity: Amortized O(log(size() + N). - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. + //! @copydoc ::boost::intrusive::bstree::push_front + void push_front(reference value); + + //! @copydoc ::boost::intrusive::bstree::erase(const_iterator) + iterator erase(const_iterator i); + + //! @copydoc ::boost::intrusive::bstree::erase(const_iterator,const_iterator) + iterator erase(const_iterator b, const_iterator e); + + //! @copydoc ::boost::intrusive::bstree::erase(const_reference) + size_type erase(const_reference value); + + //! @copydoc ::boost::intrusive::bstree::erase(const KeyType&,KeyValueCompare) template - size_type erase(const KeyType& key, KeyValueCompare comp - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) - { - std::pair p = this->equal_range(key, comp); - size_type n; - private_erase(p.first, p.second, n); - return n; - } - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases the element pointed to by pos. - //! Disposer::operator()(pointer) is called for the removed element. - //! - //! Complexity: Average complexity for erase element is constant time. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + size_type erase(const KeyType& key, KeyValueCompare comp); + + //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_iterator,Disposer) template - iterator erase_and_dispose(const_iterator i, Disposer disposer) - { - node_ptr to_erase(i.pointed_node()); - iterator ret(this->erase(i)); - disposer(get_real_value_traits().to_value_ptr(to_erase)); - return ret; - } + iterator erase_and_dispose(const_iterator i, Disposer disposer); - #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_iterator,const_iterator,Disposer) template - iterator erase_and_dispose(iterator i, Disposer disposer) - { return this->erase_and_dispose(const_iterator(i), disposer); } - #endif + iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases the range pointed to by b end e. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Complexity: Average complexity for erase range is amortized - //! O(log(size() + N)), where N is the number of elements in the range. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_reference, Disposer) template - iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer) - { size_type n; return private_erase(b, e, n, disposer); } + size_type erase_and_dispose(const_reference value, Disposer disposer); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements with the given value. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: Amortized O(log(size() + N). - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - template - size_type erase_and_dispose(const_reference value, Disposer disposer) - { - std::pair p = this->equal_range(value); - size_type n; - private_erase(p.first, p.second, n, disposer); - return n; - } - - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements with the given key. - //! according to the comparison functor "comp". - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: Amortized O(log(size() + N). - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const KeyType&,KeyValueCompare,Disposer) template - size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) - { - std::pair p = this->equal_range(key, comp); - size_type n; - private_erase(p.first, p.second, n, disposer); - return n; - } + size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer); - //! Effects: Erases all of the elements. - //! - //! Complexity: Linear to the number of elements on the container. - //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - void clear() - { - if(safemode_or_autounlink){ - this->clear_and_dispose(detail::null_disposer()); - } - else{ - node_algorithms::init_header(this->priv_header_ptr()); - this->priv_size_traits().set_size(0); - } - } + //! @copydoc ::boost::intrusive::bstree::clear + void clear(); - //! Effects: Erases all of the elements calling disposer(p) for - //! each node to be erased. - //! Complexity: Amortized O(log(size() + N)), - //! where N is the number of elements in the container. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. Calls N times to disposer functor. + //! @copydoc ::boost::intrusive::bstree::clear_and_dispose template - void clear_and_dispose(Disposer disposer) - { - node_algorithms::clear_and_dispose(this->priv_header_ptr() - , detail::node_disposer(disposer, this)); - this->priv_size_traits().set_size(0); - } + void clear_and_dispose(Disposer disposer); - //! Effects: Returns the number of contained elements with the given value - //! - //! Complexity: Amortized logarithmic to the number of elements contained plus lineal - //! to number of objects with the given value. - //! - //! Throws: Nothing. + #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, priv_comp()); } + { return this->count(value, this->value_comp()); } - //! Effects: Returns the number of contained elements with the given key - //! - //! Complexity: Amortized logarithmic to the number of elements contained plus lineal - //! to number of objects with the given key. - //! - //! Throws: Nothing. + //! @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" template size_type count(const KeyType &key, KeyValueCompare comp) { @@ -945,394 +312,212 @@ class splaytree_impl return std::distance(ret.first, ret.second); } - //! Effects: Returns the number of contained elements with the given value - //! - //! Complexity: Amortized logarithmic to the number of elements contained plus lineal - //! to number of objects with the given value. - //! - //! Throws: Nothing. - size_type count_dont_splay(const_reference value) const - { return this->count_dont_splay(value, priv_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); } - //! Effects: Returns the number of contained elements with the given key - //! - //! Complexity: Amortized logarithmic to the number of elements contained plus lineal - //! to number of objects with the given key. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const + //! Additional note: Deprecated function, use count const overload instead. + template + size_type count(const KeyType &key, KeyValueCompare comp) const + { return tree_type::count(key, comp); } + + //! @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 - { - std::pair ret = this->equal_range_dont_splay(key, comp); - return std::distance(ret.first, ret.second); - } + { return tree_type::count(key, comp); } - //! Effects: Returns an iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Amortized logarithmic. - //! - //! Throws: Nothing. - iterator lower_bound(const_reference value) - { return this->lower_bound(value, priv_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" + iterator lower_bound(const_reference value); - //! Effects: Returns an iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - const_iterator lower_bound_dont_splay(const_reference value) const - { return this->lower_bound_dont_splay(value, priv_comp()); } + //! @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; - //! Effects: Returns an iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + //! @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" template - iterator lower_bound(const KeyType &key, KeyValueCompare comp) - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - return iterator(node_algorithms::lower_bound - (this->priv_header_ptr(), key, key_node_comp), this); - } + iterator lower_bound(const KeyType &key, KeyValueCompare comp); - //! Effects: Returns a const iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare)const + //! Additional note: const function, no splaying is performed template - const_iterator lower_bound_dont_splay(const KeyType &key, KeyValueCompare comp) const - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - return const_iterator(node_algorithms::lower_bound - (this->priv_header_ptr(), key, key_node_comp, false), this); - } + const_iterator lower_bound(const KeyType &key, KeyValueCompare comp) const; - //! Effects: Returns an iterator to the first element whose - //! key is greater than k or end() if that element does not exist. - //! - //! Complexity: Amortized logarithmic. - //! - //! Throws: Nothing. - iterator upper_bound(const_reference value) - { return this->upper_bound(value, priv_comp()); } - - //! Effects: Returns an iterator to the first element whose - //! key is greater than k according to comp or end() if that element - //! does not exist. - //! - //! Complexity: Amortized logarithmic. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare) + //! Additional note: Deprecated function, use lower_bound const overload instead. template - iterator upper_bound(const KeyType &key, KeyValueCompare comp) - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - return iterator(node_algorithms::upper_bound - (this->priv_header_ptr(), key, key_node_comp), this); - } + iterator lower_bound_dont_splay(const KeyType &key, KeyValueCompare comp) const; - //! Effects: Returns an iterator to the first element whose - //! key is greater than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - const_iterator upper_bound_dont_splay(const_reference value) const - { return this->upper_bound_dont_splay(value, priv_comp()); } + //! @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" + iterator upper_bound(const_reference value); - //! Effects: Returns an iterator to the first element whose - //! key is greater than k according to comp or end() if that element - //! does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference)const + //! 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" template - const_iterator upper_bound_dont_splay(const KeyType &key, KeyValueCompare comp) const - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - return const_iterator(node_algorithms::upper_bound_dont_splay - (this->priv_header_ptr(), key, key_node_comp, false), this); - } + iterator upper_bound(const KeyType &key, KeyValueCompare comp); - //! Effects: Finds an iterator to the first element whose key is - //! k or end() if that element does not exist. - //! - //! Complexity: Amortized logarithmic. - //! - //! Throws: Nothing. - iterator find(const_reference value) - { return this->find(value, priv_comp()); } - - //! Effects: Finds an iterator to the first element whose key is - //! k or end() if that element does not exist. - //! - //! Complexity: Amortized logarithmic. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare)const + //! Additional note: const function, no splaying is performed template - iterator find(const KeyType &key, KeyValueCompare comp) - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - return iterator - (node_algorithms::find(this->priv_header_ptr(), key, key_node_comp), this); - } + const_iterator upper_bound(const KeyType &key, KeyValueCompare comp) const; - //! Effects: Finds a const_iterator to the first element whose key is - //! k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - const_iterator find_dont_splay(const_reference value) const - { return this->find_dont_splay(value, priv_comp()); } - - //! Effects: Finds a const_iterator to the first element whose key is - //! k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare) + //! Additional note: Deprecated function, use upper_bound const overload instead. template - const_iterator find_dont_splay(const KeyType &key, KeyValueCompare comp) const - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - return const_iterator - (node_algorithms::find(this->priv_header_ptr(), key, key_node_comp, false), this); - } + const_iterator upper_bound_dont_splay(const KeyType &key, KeyValueCompare comp) const; - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Amortized logarithmic. - //! - //! Throws: Nothing. - std::pair equal_range(const_reference value) - { return this->equal_range(value, priv_comp()); } + //! @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" + iterator find(const_reference value); - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Amortized logarithmic. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::find(const_reference)const + //! 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" template - std::pair equal_range(const KeyType &key, KeyValueCompare comp) - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - std::pair ret - (node_algorithms::equal_range(this->priv_header_ptr(), key, key_node_comp)); - return std::pair(iterator(ret.first, this), iterator(ret.second, this)); - } + iterator find(const KeyType &key, KeyValueCompare comp); - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - std::pair - equal_range_dont_splay(const_reference value) const - { return this->equal_range_dont_splay(value, priv_comp()); } - - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare)const + //! Additional note: const function, no splaying is performed template - std::pair - equal_range_dont_splay(const KeyType &key, KeyValueCompare comp) const - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - std::pair ret - (node_algorithms::equal_range(this->priv_header_ptr(), key, key_node_comp, false)); - return std::pair(const_iterator(ret.first, this), const_iterator(ret.second, this)); - } + const_iterator find(const KeyType &key, KeyValueCompare comp) const; - //! Requires: 'lower_value' must not be greater than 'upper_value'. If - //! 'lower_value' == 'upper_value', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise - //! - //! second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the predicate throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_value and upper_value. + //! @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" + std::pair equal_range(const_reference value); + + //! @copydoc ::boost::intrusive::bstree::equal_range(const_reference)const + //! 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" + template + std::pair equal_range(const KeyType &key, KeyValueCompare comp); + + //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare)const + //! Additional note: const function, no splaying is performed + 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) - { return this->bounded_range(lower_value, upper_value, priv_comp(), left_closed, right_closed); } + (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); - //! Requires: KeyValueCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. - //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If - //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key, comp) if left_closed, upper_bound(lower_key, comp) otherwise - //! - //! second = upper_bound(upper_key, comp) if right_closed, lower_bound(upper_key, comp) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_key and upper_key. + //! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool) template std::pair bounded_range - (const KeyType &lower_key, const KeyType &upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - std::pair ret - (node_algorithms::bounded_range - (this->priv_header_ptr(), lower_key, upper_key, key_node_comp, left_closed, right_closed)); - return std::pair(iterator(ret.first, this), iterator(ret.second, this)); - } + (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed); - //! Requires: 'lower_value' must not be greater than 'upper_value'. If - //! 'lower_value' == 'upper_value', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise - //! - //! second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the predicate throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_value and upper_value. - std::pair bounded_range - (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const - { return this->bounded_range_dont_splay(lower_value, upper_value, priv_comp(), left_closed, right_closed); } + //! @copydoc ::boost::intrusive::bstree::bounded_range(const_reference,const_reference,bool,bool)const + std::pair bounded_range + (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; - //! Requires: KeyValueCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. - //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If - //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key, comp) if left_closed, upper_bound(lower_key, comp) otherwise - //! - //! second = upper_bound(upper_key, comp) if right_closed, lower_bound(upper_key, comp) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_key and upper_key. + //! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const template - std::pair bounded_range - (const KeyType &lower_key, const KeyType &upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - std::pair ret - (node_algorithms::bounded_range - (this->priv_header_ptr(), lower_key, upper_key, key_node_comp, left_closed, right_closed, false)); - return std::pair(const_iterator(ret.first, this), const_iterator(ret.second, this)); - } + std::pair bounded_range + (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! Cloner should yield to nodes equivalent to the original nodes. - //! - //! Effects: Erases all the elements from *this - //! calling Disposer::operator()(pointer), clones all the - //! elements from src calling Cloner::operator()(const_reference ) - //! and inserts them on *this. Copies the predicate from the source container. - //! - //! If cloner throws, all cloned elements are unlinked and disposed - //! calling Disposer::operator()(pointer). - //! - //! Complexity: Linear to erased plus inserted elements. - //! - //! Throws: If cloner throws or predicate copy assignment throws. Basic guarantee. - template - void clone_from(const splaytree_impl &src, Cloner cloner, Disposer disposer) - { - this->clear_and_dispose(disposer); - if(!src.empty()){ - detail::exception_disposer - rollback(*this, disposer); - node_algorithms::clone - (src.priv_header_ptr() - ,this->priv_header_ptr() - ,detail::node_cloner(cloner, this) - ,detail::node_disposer(disposer, this)); - this->priv_size_traits().set_size(src.priv_size_traits().get_size()); - this->priv_comp() = src.priv_comp(); - rollback.release(); - } - } + //! @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; - //! Effects: Unlinks the leftmost node from the tree. - //! - //! Complexity: Average complexity is constant time. - //! - //! Throws: Nothing. - //! - //! Notes: This function breaks the tree and the tree can - //! only be used for more unlink_leftmost_without_rebalance calls. - //! This function is normally used to achieve a step by step - //! controlled destruction of the tree. - pointer unlink_leftmost_without_rebalance() - { - node_ptr to_be_disposed(node_algorithms::unlink_leftmost_without_rebalance - (this->priv_header_ptr())); - if(!to_be_disposed) - return 0; - this->priv_size_traits().decrement(); - if(safemode_or_autounlink)//If this is commented does not work with normal_link - node_algorithms::init(to_be_disposed); - return get_real_value_traits().to_value_ptr(to_be_disposed); - } + //! @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); + + //! @copydoc ::boost::intrusive::bstree::s_iterator_to(const_reference) + static const_iterator s_iterator_to(const_reference value); + + //! @copydoc ::boost::intrusive::bstree::iterator_to(reference) + iterator iterator_to(reference value); + + //! @copydoc ::boost::intrusive::bstree::iterator_to(const_reference)const + const_iterator iterator_to(const_reference value) const; + + //! @copydoc ::boost::intrusive::bstree::init_node(reference) + static void init_node(reference value); + + //! @copydoc ::boost::intrusive::bstree::unlink_leftmost_without_rebalance + pointer unlink_leftmost_without_rebalance(); + + //! @copydoc ::boost::intrusive::bstree::replace_node + void replace_node(iterator replace_this, reference with_this); + + //! @copydoc ::boost::intrusive::bstree::remove_node + void remove_node(reference value); + + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! Requires: i must be a valid iterator of *this. //! - //! Effects: Rearranges the splay set so that the element pointed by i + //! Effects: Rearranges the container so that the element pointed by i //! is placed as the root of the tree, improving future searches of this value. //! //! Complexity: Amortized logarithmic. //! //! Throws: Nothing. void splay_up(iterator i) - { return node_algorithms::splay_up(i.pointed_node(), this->priv_header_ptr()); } + { return node_algorithms::splay_up(i.pointed_node(), tree_type::header_ptr()); } - //! Effects: Rearranges the splay set so that if *this stores an element + //! Effects: Rearranges the container so that if *this stores an element //! with a key equivalent to value the element is placed as the root of the //! tree. If the element is not present returns the last node compared with the key. //! If the tree is empty, end() is returned. @@ -1345,13 +530,13 @@ class splaytree_impl template iterator splay_down(const KeyType &key, KeyValueCompare comp) { - detail::key_nodeptr_comp - key_node_comp(comp, this); - node_ptr r = node_algorithms::splay_down(this->priv_header_ptr(), key, key_node_comp); - return iterator(r, this); + detail::key_nodeptr_comp + key_node_comp(comp, &this->get_real_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()); } - //! Effects: Rearranges the splay set so that if *this stores an element + //! Effects: Rearranges the container so that if *this stores an element //! with a key equivalent to value the element is placed as the root of the //! tree. //! @@ -1360,359 +545,79 @@ class splaytree_impl //! Returns: An iterator to the new root of the tree, end() if the tree is empty. //! //! Throws: If the predicate throws. - iterator splay_down(const value_type &value) - { return this->splay_down(value, priv_comp()); } + iterator splay_down(const_reference value) + { return this->splay_down(value, this->value_comp()); } - //! Requires: replace_this must be a valid iterator of *this - //! and with_this must not be inserted in any tree. - //! - //! Effects: Replaces replace_this in its position in the - //! tree with with_this. The tree does not need to be rebalanced. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This function will break container ordering invariants if - //! with_this is not equivalent to *replace_this according to the - //! ordering rules. This function is faster than erasing and inserting - //! the node, since no rebalancing or comparison is needed. - void replace_node(iterator replace_this, reference with_this) - { - node_algorithms::replace_node( get_real_value_traits().to_node_ptr(*replace_this) - , this->priv_header_ptr() - , get_real_value_traits().to_node_ptr(with_this)); - if(safemode_or_autounlink) - node_algorithms::init(replace_this.pointed_node()); - } + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::bstree::rebalance + void rebalance(); - //! Requires: value must be an lvalue and shall be in a set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid iterator i belonging to the set - //! that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This static function is available only if the value traits - //! is stateless. - static iterator s_iterator_to(reference value) - { - BOOST_STATIC_ASSERT((!stateful_value_traits)); - return iterator (value_traits::to_node_ptr(value), 0); - } - - //! Requires: value must be an lvalue and shall be in a set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid const_iterator i belonging to the - //! set that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This static function is available only if the value traits - //! is stateless. - static const_iterator s_iterator_to(const_reference value) - { - BOOST_STATIC_ASSERT((!stateful_value_traits)); - return const_iterator (value_traits::to_node_ptr(const_cast (value)), 0); - } - - //! Requires: value must be an lvalue and shall be in a set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid iterator i belonging to the set - //! that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator iterator_to(reference value) - { return iterator (value_traits::to_node_ptr(value), this); } - - //! Requires: value must be an lvalue and shall be in a set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid const_iterator i belonging to the - //! set that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator iterator_to(const_reference value) const - { return const_iterator (value_traits::to_node_ptr(const_cast (value)), this); } - - //! Requires: value shall not be in a tree. - //! - //! Effects: init_node puts the hook of a value in a well-known default - //! state. - //! - //! Throws: Nothing. - //! - //! Complexity: Constant time. - //! - //! Note: This function puts the hook in the well-known default state - //! used by auto_unlink and safe hooks. - static void init_node(reference value) - { node_algorithms::init(value_traits::to_node_ptr(value)); } - - //! Effects: Rebalances the tree. - //! - //! Throws: Nothing. - //! - //! Complexity: Linear. - void rebalance() - { node_algorithms::rebalance(this->priv_header_ptr()); } - - //! Requires: old_root is a node of a tree. - //! - //! Effects: Rebalances the subtree rooted at old_root. - //! - //! Returns: The new root of the subtree. - //! - //! Throws: Nothing. - //! - //! Complexity: Linear to the elements in the subtree. - iterator rebalance_subtree(iterator root) - { return iterator(node_algorithms::rebalance_subtree(root.pointed_node()), this); } - -/* - //! Effects: removes x from a tree of the appropriate type. It has no effect, - //! if x is not in such a tree. - //! - //! Throws: Nothing. - //! - //! Complexity: Constant time. - //! - //! Note: This static function is only usable with the "safe mode" - //! hook and non-constant time size lists. Otherwise, the user must use - //! the non-static "erase(reference )" member. If the user calls - //! this function with a non "safe mode" or constant time size list - //! a compilation error will be issued. - template - static void remove_node(T& value) - { - //This function is only usable for safe mode hooks and non-constant - //time lists. - //BOOST_STATIC_ASSERT((!(safemode_or_autounlink && constant_time_size))); - BOOST_STATIC_ASSERT((!constant_time_size)); - BOOST_STATIC_ASSERT((boost::is_convertible::value)); - node_ptr to_remove(value_traits::to_node_ptr(value)); - node_algorithms::unlink_and_rebalance(to_remove); - if(safemode_or_autounlink) - node_algorithms::init(to_remove); - } -*/ - - /// @cond - private: - template - iterator private_erase(const_iterator b, const_iterator e, size_type &n, Disposer disposer) - { - for(n = 0; b != e; ++n) - this->erase_and_dispose(b++, disposer); - return b.unconst(); - } - - iterator private_erase(const_iterator b, const_iterator e, size_type &n) - { - for(n = 0; b != e; ++n) - this->erase(b++); - return b.unconst(); - } - /// @endcond - - private: - static splaytree_impl &priv_container_from_end_iterator(const const_iterator &end_iterator) - { - header_plus_size *r = detail::parent_from_member - ( boost::intrusive::detail::to_raw_pointer(end_iterator.pointed_node()), &header_plus_size::header_); - node_plus_pred_t *n = detail::parent_from_member - (r, &node_plus_pred_t::header_plus_size_); - data_t *d = detail::parent_from_member(n, &data_t::node_plus_pred_); - splaytree_impl *rb = detail::parent_from_member(d, &splaytree_impl::data_); - return *rb; - } - - static splaytree_impl &priv_container_from_iterator(const const_iterator &it) - { return priv_container_from_end_iterator(it.end_iterator_from_it()); } + //! @copydoc ::boost::intrusive::bstree::rebalance_subtree + iterator rebalance_subtree(iterator root); + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED }; #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + template -#else -template -#endif -inline bool operator< -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const splaytree_impl &x, const splaytree_impl &y) -#else -(const splaytree_impl &x, const splaytree_impl &y) -#endif -{ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } +bool operator< (const splaytree_impl &x, const splaytree_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -bool operator== -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const splaytree_impl &x, const splaytree_impl &y) -#else -(const splaytree_impl &x, const splaytree_impl &y) -#endif -{ - typedef splaytree_impl tree_type; - typedef typename tree_type::const_iterator const_iterator; +bool operator==(const splaytree_impl &x, const splaytree_impl &y); - if(tree_type::constant_time_size && x.size() != y.size()){ - return false; - } - const_iterator end1 = x.end(); - const_iterator i1 = x.begin(); - const_iterator i2 = y.begin(); - if(tree_type::constant_time_size){ - while (i1 != end1 && *i1 == *i2) { - ++i1; - ++i2; - } - return i1 == end1; - } - else{ - const_iterator end2 = y.end(); - while (i1 != end1 && i2 != end2 && *i1 == *i2) { - ++i1; - ++i2; - } - return i1 == end1 && i2 == end2; - } -} - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator!= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const splaytree_impl &x, const splaytree_impl &y) -#else -(const splaytree_impl &x, const splaytree_impl &y) -#endif -{ return !(x == y); } +bool operator!= (const splaytree_impl &x, const splaytree_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator> -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const splaytree_impl &x, const splaytree_impl &y) -#else -(const splaytree_impl &x, const splaytree_impl &y) -#endif -{ return y < x; } +bool operator>(const splaytree_impl &x, const splaytree_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator<= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const splaytree_impl &x, const splaytree_impl &y) -#else -(const splaytree_impl &x, const splaytree_impl &y) -#endif -{ return !(y < x); } +bool operator<=(const splaytree_impl &x, const splaytree_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator>= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const splaytree_impl &x, const splaytree_impl &y) -#else -(const splaytree_impl &x, const splaytree_impl &y) -#endif -{ return !(x < y); } +bool operator>=(const splaytree_impl &x, const splaytree_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline void swap -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(splaytree_impl &x, splaytree_impl &y) -#else -(splaytree_impl &x, splaytree_impl &y) -#endif -{ x.swap(y); } +void swap(splaytree_impl &x, splaytree_impl &y); -/// @cond - -#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) -template -#else -template -#endif -struct make_splaytree_opt -{ - typedef typename pack_options - < splay_set_defaults, - #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - O1, O2, O3, O4 - #else - Options... - #endif - >::type packed_options; - typedef typename detail::get_value_traits - ::type value_traits; - - typedef splaysetopt - < value_traits - , typename packed_options::compare - , typename packed_options::size_type - , packed_options::constant_time_size - > type; -}; -/// @endcond +#endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Helper metafunction to define a \c splaytree that yields to the same type when the //! same options (either explicitly or implicitly) are used. #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else -template +template #endif struct make_splaytree { /// @cond + typedef typename pack_options + < splaytree_defaults, + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3, O4 + #else + Options... + #endif + >::type packed_options; + + typedef typename detail::get_value_traits + ::type value_traits; + typedef splaytree_impl - < typename make_splaytree_opt::type - > implementation_defined; + < value_traits + , typename packed_options::compare + , typename packed_options::size_type + , packed_options::constant_time_size + > implementation_defined; /// @endcond typedef implementation_defined type; }; + #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else @@ -1720,20 +625,20 @@ template #endif class splaytree : public make_splaytree::type { typedef typename make_splaytree ::type Base; BOOST_MOVABLE_BUT_NOT_COPYABLE(splaytree) @@ -1743,19 +648,21 @@ class splaytree 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)); splaytree( const value_compare &cmp = value_compare() - , const value_traits &v_traits = value_traits()) + , const value_traits &v_traits = value_traits()) : Base(cmp, v_traits) {} template splaytree( bool unique, Iterator b, Iterator e - , const value_compare &cmp = value_compare() - , const value_traits &v_traits = value_traits()) + , const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) : Base(unique, b, e, cmp, v_traits) {} @@ -1764,18 +671,23 @@ class splaytree {} splaytree& operator=(BOOST_RV_REF(splaytree) x) - { this->Base::operator=(::boost::move(static_cast(x))); return *this; } + { return static_cast(this->Base::operator=(::boost::move(static_cast(x)))); } static splaytree &container_from_end_iterator(iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } static const splaytree &container_from_end_iterator(const_iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } + + static splaytree &container_from_iterator(iterator it) + { return static_cast(Base::container_from_iterator(it)); } + + static const splaytree &container_from_iterator(const_iterator it) + { return static_cast(Base::container_from_iterator(it)); } }; #endif - } //namespace intrusive } //namespace boost diff --git a/include/boost/intrusive/splaytree_algorithms.hpp b/include/boost/intrusive/splaytree_algorithms.hpp index 8155648..71fbf87 100644 --- a/include/boost/intrusive/splaytree_algorithms.hpp +++ b/include/boost/intrusive/splaytree_algorithms.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 @@ -12,8 +12,9 @@ // The implementation of splay trees is based on the article and code published // in C++ Users Journal "Implementing Splay Trees in C++" (September 1, 2005). // -// The code has been modified and (supposely) improved by Ion Gaztanaga. -// Here is the header of the file used as base code: +// The splay code has been modified and (supposedly) improved by Ion Gaztanaga. +// +// Here is the copyright notice of the original file containing the splay code: // // splay_tree.h -- implementation of a STL compatible splay tree. // @@ -24,24 +25,7 @@ // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // -// Please send questions, comments, complaints, performance data, etc to -// ralf.mattethat@teknologisk.dk -// -// Requirements for element type -// * must be copy-constructible -// * destructor must not throw exception -// -// Methods marked with note A only throws an exception if the evaluation of the -// predicate throws an exception. If an exception is thrown the call has no -// effect on the containers state -// -// Methods marked with note B only throws an exception if the coppy constructor -// or assignment operator of the predicate throws an exception. If an exception -// is thrown the call has no effect on the containers state -// -// iterators are only invalidated, if the element pointed to by the iterator -// is deleted. The same goes for element references -// +///////////////////////////////////////////////////////////////////////////// #ifndef BOOST_INTRUSIVE_SPLAYTREE_ALGORITHMS_HPP #define BOOST_INTRUSIVE_SPLAYTREE_ALGORITHMS_HPP @@ -52,7 +36,7 @@ #include #include #include -#include +#include namespace boost { namespace intrusive { @@ -100,14 +84,14 @@ struct splaydown_rollback //! by Daniel Dominic Sleator and Robert Endre Tarjan //! AT&T Bell Laboratories, Murray Hill, NJ //! Journal of the ACM, Vol 32, no 3, July 1985, pp 652-686 - +//! //! splaytree_algorithms is configured with a NodeTraits class, which encapsulates the //! information about the node to be manipulated. NodeTraits must support the //! following interface: //! //! Typedefs: //! -//! node: The type of the node that forms the circular list +//! node: The type of the node that forms the binary search tree //! //! node_ptr: A pointer to a node //! @@ -128,10 +112,13 @@ struct splaydown_rollback //! static void set_right(node_ptr n, node_ptr right); template class splaytree_algorithms + #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + : public bstree_algorithms + #endif { /// @cond private: - typedef detail::tree_algorithms tree_algorithms; + typedef bstree_algorithms bstree_algorithms; /// @endcond public: @@ -142,596 +129,77 @@ class splaytree_algorithms //! This type is the information that will be //! filled by insert_unique_check - typedef typename tree_algorithms::insert_commit_data insert_commit_data; - - /// @cond - private: - static node_ptr uncast(const const_node_ptr & ptr) - { return pointer_traits::const_cast_from(ptr); } - /// @endcond + typedef typename bstree_algorithms::insert_commit_data insert_commit_data; public: - static node_ptr begin_node(const const_node_ptr & header) - { return tree_algorithms::begin_node(header); } + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::bstree_algorithms::get_header(const const_node_ptr&) + static node_ptr get_header(const const_node_ptr & n); - static node_ptr end_node(const const_node_ptr & header) - { return tree_algorithms::end_node(header); } + //! @copydoc ::boost::intrusive::bstree_algorithms::begin_node + static node_ptr begin_node(const const_node_ptr & header); - //! Requires: node is a node of the tree or an node initialized - //! by init(...). - //! - //! Effects: Returns true if the node is initialized by init(). - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - static bool unique(const const_node_ptr & node) - { return tree_algorithms::unique(node); } + //! @copydoc ::boost::intrusive::bstree_algorithms::end_node + static node_ptr end_node(const const_node_ptr & header); - static void unlink(const node_ptr & node) - { tree_algorithms::unlink(node); } + //! @copydoc ::boost::intrusive::bstree_algorithms::swap_tree + static void swap_tree(const node_ptr & header1, const node_ptr & header2); - //! Requires: node1 and node2 can't be header nodes - //! of two trees. - //! - //! Effects: Swaps two nodes. After the function node1 will be inserted - //! in the position node2 before the function. node2 will be inserted in the - //! position node1 had before the function. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - //! - //! Note: This function will break container ordering invariants if - //! node1 and node2 are not equivalent according to the ordering rules. - //! - //!Experimental function - static void swap_nodes(const node_ptr & node1, const node_ptr & node2) - { - if(node1 == node2) - return; + //! @copydoc ::boost::intrusive::bstree_algorithms::swap_nodes(const node_ptr&,const node_ptr&) + static void swap_nodes(const node_ptr & node1, const node_ptr & node2); - node_ptr header1(tree_algorithms::get_header(node1)), header2(tree_algorithms::get_header(node2)); - swap_nodes(node1, header1, node2, header2); - } + //! @copydoc ::boost::intrusive::bstree_algorithms::swap_nodes(const node_ptr&,const node_ptr&,const node_ptr&,const node_ptr&) + static void swap_nodes(const node_ptr & node1, const node_ptr & header1, const node_ptr & node2, const node_ptr & header2); - //! Requires: node1 and node2 can't be header nodes - //! of two trees with header header1 and header2. - //! - //! Effects: Swaps two nodes. After the function node1 will be inserted - //! in the position node2 before the function. node2 will be inserted in the - //! position node1 had before the function. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This function will break container ordering invariants if - //! node1 and node2 are not equivalent according to the ordering rules. - //! - //!Experimental function - static void swap_nodes(const node_ptr & node1, const node_ptr & header1, const node_ptr & node2, const node_ptr & header2) - { tree_algorithms::swap_nodes(node1, header1, node2, header2); } + //! @copydoc ::boost::intrusive::bstree_algorithms::replace_node(const node_ptr&,const node_ptr&) + static void replace_node(const node_ptr & node_to_be_replaced, const node_ptr & new_node); - //! Requires: node_to_be_replaced must be inserted in a tree - //! and new_node must not be inserted in a tree. - //! - //! Effects: Replaces node_to_be_replaced in its position in the - //! tree with new_node. The tree does not need to be rebalanced - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - //! - //! Note: This function will break container ordering invariants if - //! new_node is not equivalent to node_to_be_replaced according to the - //! ordering rules. This function is faster than erasing and inserting - //! the node, since no rebalancing and comparison is needed. - //! - //!Experimental function - static void replace_node(const node_ptr & node_to_be_replaced, const node_ptr & new_node) - { - if(node_to_be_replaced == new_node) - return; - replace_node(node_to_be_replaced, tree_algorithms::get_header(node_to_be_replaced), new_node); - } + //! @copydoc ::boost::intrusive::bstree_algorithms::replace_node(const node_ptr&,const node_ptr&,const node_ptr&) + static void replace_node(const node_ptr & node_to_be_replaced, const node_ptr & header, const node_ptr & new_node); - //! Requires: node_to_be_replaced must be inserted in a tree - //! with header "header" and new_node must not be inserted in a tree. - //! - //! Effects: Replaces node_to_be_replaced in its position in the - //! tree with new_node. The tree does not need to be rebalanced - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This function will break container ordering invariants if - //! new_node is not equivalent to node_to_be_replaced according to the - //! ordering rules. This function is faster than erasing and inserting - //! the node, since no rebalancing or comparison is needed. - //! - //!Experimental function - static void replace_node(const node_ptr & node_to_be_replaced, const node_ptr & header, const node_ptr & new_node) - { tree_algorithms::replace_node(node_to_be_replaced, header, new_node); } + //! @copydoc ::boost::intrusive::bstree_algorithms::unlink(const node_ptr&) + static void unlink(const node_ptr & node); - //! Requires: p is a node from the tree except the header. - //! - //! Effects: Returns the next node of the tree. - //! - //! Complexity: Average constant time. - //! - //! Throws: Nothing. - static node_ptr next_node(const node_ptr & p) - { return tree_algorithms::next_node(p); } + //! @copydoc ::boost::intrusive::bstree_algorithms::unlink_leftmost_without_rebalance + static node_ptr unlink_leftmost_without_rebalance(const node_ptr & header); - //! Requires: p is a node from the tree except the leftmost node. - //! - //! Effects: Returns the previous node of the tree. - //! - //! Complexity: Average constant time. - //! - //! Throws: Nothing. - static node_ptr prev_node(const node_ptr & p) - { return tree_algorithms::prev_node(p); } + //! @copydoc ::boost::intrusive::bstree_algorithms::unique(const const_node_ptr&) + static bool unique(const const_node_ptr & node); - //! Requires: node must not be part of any tree. - //! - //! Effects: After the function unique(node) == true. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Nodes: If node is inserted in a tree, this function corrupts the tree. - static void init(const node_ptr & node) - { tree_algorithms::init(node); } + //! @copydoc ::boost::intrusive::bstree_algorithms::size(const const_node_ptr&) + static std::size_t size(const const_node_ptr & header); - //! Requires: node must not be part of any tree. - //! - //! Effects: Initializes the header to represent an empty tree. - //! unique(header) == true. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Nodes: If node is inserted in a tree, this function corrupts the tree. - static void init_header(const node_ptr & header) - { tree_algorithms::init_header(header); } + //! @copydoc ::boost::intrusive::bstree_algorithms::next_node(const node_ptr&) + static node_ptr next_node(const node_ptr & node); - //! Requires: "disposer" must be an object function - //! taking a node_ptr parameter and shouldn't throw. - //! - //! Effects: Empties the target tree calling - //! void disposer::operator()(const node_ptr &) for every node of the tree - //! except the header. - //! - //! Complexity: Linear to the number of element of the source tree plus the. - //! number of elements of tree target tree when calling this function. - //! - //! Throws: If cloner functor throws. If this happens target nodes are disposed. - template - static void clear_and_dispose(const node_ptr & header, Disposer disposer) - { tree_algorithms::clear_and_dispose(header, disposer); } + //! @copydoc ::boost::intrusive::bstree_algorithms::prev_node(const node_ptr&) + static node_ptr prev_node(const node_ptr & node); - //! Requires: node is a node of the tree but it's not the header. - //! - //! Effects: Returns the number of nodes of the subtree. - //! - //! Complexity: Linear time. - //! - //! Throws: Nothing. - static std::size_t count(const const_node_ptr & node) - { return tree_algorithms::count(node); } + //! @copydoc ::boost::intrusive::bstree_algorithms::init(const node_ptr&) + static void init(const node_ptr & node); - //! Requires: header is the header node of the tree. - //! - //! Effects: Returns the number of nodes above the header. - //! - //! Complexity: Linear time. - //! - //! Throws: Nothing. - static std::size_t size(const const_node_ptr & header) - { return tree_algorithms::size(header); } + //! @copydoc ::boost::intrusive::bstree_algorithms::init_header(const node_ptr&) + static void init_header(const node_ptr & header); + + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! Requires: header1 and header2 must be the header nodes - //! of two trees. - //! - //! Effects: Swaps two trees. After the function header1 will contain - //! links to the second tree and header2 will have links to the first tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - static void swap_tree(const node_ptr & header1, const node_ptr & header2) - { return tree_algorithms::swap_tree(header1, header2); } - - //! Requires: "header" must be the header node of a tree. - //! "commit_data" must have been obtained from a previous call to - //! "insert_unique_check". No objects should have been inserted or erased - //! from the set between the "insert_unique_check" that filled "commit_data" - //! and the call to "insert_commit". - //! - //! - //! Effects: Inserts new_node in the set using the information obtained - //! from the "commit_data" that a previous "insert_check" filled. - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Notes: This function has only sense if a "insert_unique_check" has been - //! previously executed to fill "commit_data". No value should be inserted or - //! erased between the "insert_check" and "insert_commit" calls. - static void insert_unique_commit - (const node_ptr & header, const node_ptr & new_value, const insert_commit_data &commit_data) - { tree_algorithms::insert_unique_commit(header, new_value, commit_data); } - - //! 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. NodePtrCompare compares KeyType with a node_ptr. - //! - //! Effects: Checks if there is an equivalent node to "key" in the - //! tree according to "comp" and obtains the needed information to realize - //! a constant-time node insertion if there is no equivalent node. - //! - //! Returns: If there is an equivalent value - //! returns a pair containing a node_ptr to the already present node - //! and false. If there is not equivalent key can be inserted returns true - //! in the returned pair's boolean and fills "commit_data" that is meant to - //! be used with the "insert_commit" function to achieve a constant-time - //! insertion function. - //! - //! Complexity: Average complexity is at most logarithmic. - //! - //! Throws: If "comp" throws. - //! - //! Notes: This function is used to improve performance when constructing - //! a node is expensive and the user does not want to have two equivalent nodes - //! in the tree: if there is an equivalent value - //! the constructed object must be discarded. Many times, the part of the - //! node that is used to impose the order is much cheaper to construct - //! than the node and this function offers the possibility to use that part - //! to check if the insertion will be successful. - //! - //! If the check is successful, the user can construct the node and use - //! "insert_commit" to insert the node in constant-time. This gives a total - //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)). - //! - //! "commit_data" remains valid for a subsequent "insert_unique_commit" only - //! if no more objects are inserted or erased from the set. - template - static std::pair insert_unique_check - (const node_ptr & header, const KeyType &key - ,KeyNodePtrCompare comp, insert_commit_data &commit_data) - { - splay_down(header, key, comp); - return tree_algorithms::insert_unique_check(header, key, comp, commit_data); - } - - template - static std::pair insert_unique_check - (const node_ptr & header, const node_ptr &hint, const KeyType &key - ,KeyNodePtrCompare comp, insert_commit_data &commit_data) - { - splay_down(header, key, comp); - return tree_algorithms::insert_unique_check(header, hint, key, comp, commit_data); - } - - static bool is_header(const const_node_ptr & p) - { return tree_algorithms::is_header(p); } - - //! 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 an node_ptr to the element that is equivalent to - //! "key" according to "comp" or "header" if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. - template - static node_ptr find - (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool splay = true) - { - if(splay) - splay_down(uncast(header), key, comp); - node_ptr end = uncast(header); - node_ptr y = lower_bound(header, key, comp, false); - node_ptr r = (y == end || comp(key, y)) ? end : y; - return r; - } - - //! 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 an a pair of node_ptr delimiting a range containing - //! all elements that are equivalent to "key" according to "comp" or an - //! empty range that indicates the position where those elements would be - //! if they there are no equivalent elements. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. - template - static std::pair equal_range - (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool splay = true) - { - //if(splay) - //splay_down(uncast(header), key, comp); - std::pair ret = - tree_algorithms::equal_range(header, key, comp); - - if(splay) - splay_up(ret.first, uncast(header)); - return ret; - } - - //! 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. - //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If - //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise - //! - //! second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_key and upper_key. - template - static std::pair bounded_range - (const const_node_ptr & header, const KeyType &lower_key, const KeyType &upper_key, KeyNodePtrCompare comp - , bool left_closed, bool right_closed, bool splay = true) - { - std::pair ret = - tree_algorithms::bounded_range(header, lower_key, upper_key, comp, left_closed, right_closed); - - if(splay) - splay_up(ret.first, uncast(header)); - return ret; - } - - //! 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 an node_ptr to the first element that is - //! not less than "key" according to "comp" or "header" if that element does - //! not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. - template - static node_ptr lower_bound - (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool splay = true) - { - //if(splay) - //splay_down(uncast(header), key, comp); - node_ptr y = tree_algorithms::lower_bound(header, key, comp); - if(splay) - splay_up(y, uncast(header)); - return y; - } - - //! 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 an node_ptr to the first element that is greater - //! than "key" according to "comp" or "header" if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. - template - static node_ptr upper_bound - (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool splay = true) - { - //if(splay) - //splay_down(uncast(header), key, comp); - node_ptr y = tree_algorithms::upper_bound(header, key, comp); - if(splay) - splay_up(y, uncast(header)); - return y; - } - - //! Requires: "header" must be the header node of a tree. - //! NodePtrCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. NodePtrCompare compares two node_ptrs. "hint" is node from - //! the "header"'s tree. - //! - //! Effects: Inserts new_node into the tree, using "hint" as a hint to - //! where it will be inserted. If "hint" is the upper_bound - //! the insertion takes constant time (two comparisons in the worst case). - //! - //! Complexity: Logarithmic in general, but it is amortized - //! constant time if new_node is inserted immediately before "hint". - //! - //! Throws: If "comp" throws. - template - static node_ptr insert_equal - (const node_ptr & header, const node_ptr & hint, const node_ptr & new_node, NodePtrCompare comp) - { - splay_down(header, new_node, comp); - return tree_algorithms::insert_equal(header, hint, new_node, comp); - } - - - //! Requires: "header" must be the header node of a tree. - //! "pos" must be a valid iterator or header (end) node. - //! "pos" must be an iterator pointing to the successor to "new_node" - //! once inserted according to the order of already inserted nodes. This function does not - //! check "pos" and this precondition must be guaranteed by the caller. - //! - //! Effects: Inserts new_node into the tree before "pos". - //! - //! Complexity: Constant-time. - //! - //! Throws: Nothing. - //! - //! Note: If "pos" is not the successor of the newly inserted "new_node" - //! tree invariants might be broken. - static node_ptr insert_before - (const node_ptr & header, const node_ptr & pos, const node_ptr & new_node) - { - tree_algorithms::insert_before(header, pos, new_node); - splay_up(new_node, header); - return new_node; - } - - //! Requires: "header" must be the header node of a tree. - //! "new_node" must be, according to the used ordering no less than the - //! greatest inserted key. - //! - //! Effects: Inserts new_node into the tree before "pos". - //! - //! Complexity: Constant-time. - //! - //! Throws: Nothing. - //! - //! Note: If "new_node" is less than the greatest inserted key - //! tree invariants are broken. This function is slightly faster than - //! using "insert_before". - static void push_back(const node_ptr & header, const node_ptr & new_node) - { - tree_algorithms::push_back(header, new_node); - splay_up(new_node, header); - } - - //! Requires: "header" must be the header node of a tree. - //! "new_node" must be, according to the used ordering, no greater than the - //! lowest inserted key. - //! - //! Effects: Inserts new_node into the tree before "pos". - //! - //! Complexity: Constant-time. - //! - //! Throws: Nothing. - //! - //! Note: If "new_node" is greater than the lowest inserted key - //! tree invariants are broken. This function is slightly faster than - //! using "insert_before". - static void push_front(const node_ptr & header, const node_ptr & new_node) - { - tree_algorithms::push_front(header, new_node); - splay_up(new_node, header); - } - - //! Requires: "header" must be the header node of a tree. - //! NodePtrCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. NodePtrCompare compares two node_ptrs. - //! - //! Effects: Inserts new_node into the tree before the upper bound - //! according to "comp". - //! - //! Complexity: Average complexity for insert element is at - //! most logarithmic. - //! - //! Throws: If "comp" throws. - template - static node_ptr insert_equal_upper_bound - (const node_ptr & header, const node_ptr & new_node, NodePtrCompare comp) - { - splay_down(header, new_node, comp); - return tree_algorithms::insert_equal_upper_bound(header, new_node, comp); - } - - //! Requires: "header" must be the header node of a tree. - //! NodePtrCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. NodePtrCompare compares two node_ptrs. - //! - //! Effects: Inserts new_node into the tree before the lower bound - //! according to "comp". - //! - //! Complexity: Average complexity for insert element is at - //! most logarithmic. - //! - //! Throws: If "comp" throws. - template - static node_ptr insert_equal_lower_bound - (const node_ptr & header, const node_ptr & new_node, NodePtrCompare comp) - { - splay_down(header, new_node, comp); - return tree_algorithms::insert_equal_lower_bound(header, new_node, comp); - } - - //! Requires: "cloner" must be a function - //! object taking a node_ptr and returning a new cloned node of it. "disposer" must - //! take a node_ptr and shouldn't throw. - //! - //! Effects: First empties target tree calling - //! void disposer::operator()(const node_ptr &) for every node of the tree - //! except the header. - //! - //! Then, duplicates the entire tree pointed by "source_header" cloning each - //! source node with node_ptr Cloner::operator()(const node_ptr &) to obtain - //! the nodes of the target tree. If "cloner" throws, the cloned target nodes - //! are disposed using void disposer(const node_ptr &). - //! - //! Complexity: Linear to the number of element of the source tree plus the. - //! number of elements of tree target tree when calling this function. - //! - //! Throws: If cloner functor throws. If this happens target nodes are disposed. - template - static void clone - (const const_node_ptr & source_header, const node_ptr & target_header, Cloner cloner, Disposer disposer) - { tree_algorithms::clone(source_header, target_header, cloner, disposer); } - - // delete node | complexity : constant | exception : nothrow + //! @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) { -// node_base* n = t->right; -// if( t->left != node_ptr() ){ -// node_base* l = t->previous(); -// splay_up( l , t ); -// n = t->left; -// n->right = t->right; -// if( n->right != node_ptr() ) -// n->right->parent = n; -// } -// -// if( n != node_ptr() ) -// n->parent = t->parent; -// -// if( t->parent->left == t ) -// t->parent->left = n; -// else // must be ( t->parent->right == t ) -// t->parent->right = n; -// -// if( data_->parent == t ) -// data_->parent = find_leftmost(); - //posibility 1 + //posibility 1 if(splay && NodeTraits::get_left(z)){ - splay_up(prev_node(z), header); + splay_up(bstree_algorithms::prev_node(z), header); } /* //possibility 2 - if(splay && NodeTraits::get_left(z) != node_ptr() ){ + if(splay && NodeTraits::get_left(z)){ node_ptr l = NodeTraits::get_left(z); splay_up(l, header); }*//* - if(splay && NodeTraits::get_left(z) != node_ptr() ){ - node_ptr l = prev_node(z); + if(splay && NodeTraits::get_left(z)){ + node_ptr l = bstree_algorithms::prev_node(z); splay_up_impl(l, z); }*/ /* @@ -742,9 +210,239 @@ class splaytree_algorithms //if(splay) //splay_up(z, header); - tree_algorithms::erase(header, z); + bstree_algorithms::erase(header, z); } + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::bstree_algorithms::clone(const const_node_ptr&,const node_ptr&,Cloner,Disposer) + template + static void clone + (const const_node_ptr & source_header, const node_ptr & target_header, Cloner cloner, Disposer disposer); + + //! @copydoc ::boost::intrusive::bstree_algorithms::clear_and_dispose(const node_ptr&,Disposer) + template + static void clear_and_dispose(const node_ptr & header, Disposer disposer); + + #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. + template + static std::size_t count + (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) + { + std::pair ret = equal_range(header, key, comp); + std::size_t n = 0; + while(ret.first != ret.second){ + ++n; + ret.first = next_node(ret.first); + } + return n; + } + + //! @copydoc ::boost::intrusive::bstree_algorithms::count(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) + //! Additional note: no splaying is performed + template + static std::size_t count + (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) + { return bstree_algorithms::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. + template + static node_ptr lower_bound + (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool splay = true) + { + //splay_down(detail::uncast(header), key, comp); + node_ptr y = bstree_algorithms::lower_bound(header, key, comp); + if(splay) splay_up(y, detail::uncast(header)); + return y; + } + + //! @copydoc ::boost::intrusive::bstree_algorithms::lower_bound(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) + //! Additional note: no splaying is performed + template + static node_ptr lower_bound + (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) + { return bstree_algorithms::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. + template + static node_ptr upper_bound + (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool splay = true) + { + //splay_down(detail::uncast(header), key, comp); + node_ptr y = bstree_algorithms::upper_bound(header, key, comp); + if(splay) splay_up(y, detail::uncast(header)); + return y; + } + + //! @copydoc ::boost::intrusive::bstree_algorithms::upper_bound(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) + //! Additional note: no splaying is performed + template + static node_ptr upper_bound + (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) + { return bstree_algorithms::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. + template + static node_ptr find + (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool splay = true) + { + if(splay) splay_down(detail::uncast(header), key, comp); + node_ptr end = detail::uncast(header); + node_ptr y = bstree_algorithms::lower_bound(header, key, comp); + node_ptr r = (y == end || comp(key, y)) ? end : y; + return r; + } + + //! @copydoc ::boost::intrusive::bstree_algorithms::find(const const_node_ptr&, const KeyType&,KeyNodePtrCompare) + //! Additional note: no splaying is performed + template + static node_ptr find + (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) + { return bstree_algorithms::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. + template + static std::pair equal_range + (const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool splay = true) + { + //splay_down(detail::uncast(header), key, comp); + std::pair ret = bstree_algorithms::equal_range(header, key, comp); + if(splay) splay_up(ret.first, detail::uncast(header)); + return ret; + } + + //! @copydoc ::boost::intrusive::bstree_algorithms::equal_range(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) + //! Additional note: no splaying is performed + template + static std::pair equal_range + (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) + { return bstree_algorithms::equal_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. + 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) + { + std::pair ret = + bstree_algorithms::bounded_range(header, lower_key, upper_key, comp, left_closed, right_closed); + if(splay) splay_up(ret.first, detail::uncast(header)); + return ret; + } + + //! @copydoc ::boost::intrusive::bstree_algorithms::bounded_range(const const_node_ptr&,const KeyType&,const KeyType&,KeyNodePtrCompare,bool,bool) + //! Additional note: no splaying is performed + template + static std::pair bounded_range + (const const_node_ptr & header, const KeyType &lower_key, const KeyType &upper_key, KeyNodePtrCompare comp + , bool left_closed, bool right_closed) + { return bstree_algorithms::bounded_range(header, lower_key, upper_key, comp, left_closed, right_closed); } + + //! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal_upper_bound(const node_ptr&,const node_ptr&,NodePtrCompare) + //! Additional note: the inserted node is splayed + template + static node_ptr insert_equal_upper_bound + (const node_ptr & header, const node_ptr & new_node, NodePtrCompare comp) + { + splay_down(header, new_node, comp); + return bstree_algorithms::insert_equal_upper_bound(header, new_node, comp); + } + + //! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal_lower_bound(const node_ptr&,const node_ptr&,NodePtrCompare) + //! Additional note: the inserted node is splayed + template + static node_ptr insert_equal_lower_bound + (const node_ptr & header, const node_ptr & new_node, NodePtrCompare comp) + { + splay_down(header, new_node, comp); + return bstree_algorithms::insert_equal_lower_bound(header, new_node, comp); + } + + //! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal(const node_ptr&,const node_ptr&,const node_ptr&,NodePtrCompare) + //! Additional note: the inserted node is splayed + template + static node_ptr insert_equal + (const node_ptr & header, const node_ptr & hint, const node_ptr & new_node, NodePtrCompare comp) + { + splay_down(header, new_node, comp); + return bstree_algorithms::insert_equal(header, hint, new_node, comp); + } + + //! @copydoc ::boost::intrusive::bstree_algorithms::insert_before(const node_ptr&,const node_ptr&,const node_ptr&) + //! Additional note: the inserted node is splayed + static node_ptr insert_before + (const node_ptr & header, const node_ptr & pos, const node_ptr & new_node) + { + bstree_algorithms::insert_before(header, pos, new_node); + splay_up(new_node, header); + return new_node; + } + + //! @copydoc ::boost::intrusive::bstree_algorithms::push_back(const node_ptr&,const node_ptr&) + //! Additional note: the inserted node is splayed + static void push_back(const node_ptr & header, const node_ptr & new_node) + { + bstree_algorithms::push_back(header, new_node); + splay_up(new_node, header); + } + + //! @copydoc ::boost::intrusive::bstree_algorithms::push_front(const node_ptr&,const node_ptr&) + //! Additional note: the inserted node is splayed + static void push_front(const node_ptr & header, const node_ptr & new_node) + { + bstree_algorithms::push_front(header, new_node); + splay_up(new_node, header); + } + + //! @copydoc ::boost::intrusive::bstree_algorithms::insert_unique_check(const const_node_ptr&,const KeyType&,KeyNodePtrCompare,insert_commit_data&) + //! Additional note: nodes with the given key are splayed + template + static std::pair insert_unique_check + (const node_ptr & header, const KeyType &key + ,KeyNodePtrCompare comp, insert_commit_data &commit_data) + { + splay_down(header, key, comp); + return bstree_algorithms::insert_unique_check(header, key, comp, commit_data); + } + + //! @copydoc ::boost::intrusive::bstree_algorithms::insert_unique_check(const const_node_ptr&,const node_ptr&,const KeyType&,KeyNodePtrCompare,insert_commit_data&) + //! Additional note: nodes with the given key are splayed + template + static std::pair insert_unique_check + (const node_ptr & header, const node_ptr &hint, const KeyType &key + ,KeyNodePtrCompare comp, insert_commit_data &commit_data) + { + splay_down(header, key, comp); + return bstree_algorithms::insert_unique_check(header, hint, key, comp, commit_data); + } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::bstree_algorithms::insert_unique_commit(const node_ptr&,const node_ptr&,const insert_commit_data&) + static void insert_unique_commit + (const node_ptr & header, const node_ptr & new_value, const insert_commit_data &commit_data); + + //! @copydoc ::boost::intrusive::bstree_algorithms::is_header + static bool is_header(const const_node_ptr & p); + + //! @copydoc ::boost::intrusive::bstree_algorithms::rebalance + static void rebalance(const node_ptr & header); + + //! @copydoc ::boost::intrusive::bstree_algorithms::rebalance_subtree + static node_ptr rebalance_subtree(const node_ptr & old_root); + + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + // 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) { @@ -815,7 +513,7 @@ class splaytree_algorithms if(NodeTraits::get_left(t) == node_ptr() ) break; if(comp(key, NodeTraits::get_left(t))){ - t = tree_algorithms::rotate_right(t); + t = bstree_algorithms::rotate_right(t); if(NodeTraits::get_left(t) == node_ptr()) break; @@ -837,7 +535,7 @@ class splaytree_algorithms break; if(comp(NodeTraits::get_right(t), key)){ - t = tree_algorithms::rotate_left( t ); + t = bstree_algorithms::rotate_left( t ); if(NodeTraits::get_right(t) == node_ptr() ) break; @@ -875,39 +573,6 @@ class splaytree_algorithms return t; } - //! Requires: header must be the header of a tree. - //! - //! Effects: Rebalances the tree. - //! - //! Throws: Nothing. - //! - //! Complexity: Linear. - static void rebalance(const node_ptr & header) - { tree_algorithms::rebalance(header); } - - //! Requires: old_root is a node of a tree. - //! - //! Effects: Rebalances the subtree rooted at old_root. - //! - //! Returns: The new root of the subtree. - //! - //! Throws: Nothing. - //! - //! Complexity: Linear. - static node_ptr rebalance_subtree(const node_ptr & old_root) - { return tree_algorithms::rebalance_subtree(old_root); } - - - //! Requires: "n" must be a node inserted in a tree. - //! - //! Effects: Returns a pointer to the header node of the tree. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - static node_ptr get_header(const node_ptr & n) - { return tree_algorithms::get_header(n); } - private: /// @cond @@ -963,7 +628,7 @@ class splaytree_algorithms node_ptr g = NodeTraits::get_parent(p); //Test if g is header before breaking tree //invariants that would make is_header invalid - bool g_is_header = is_header(g); + bool g_is_header = bstree_algorithms::is_header(g); if(NodeTraits::get_left(p) == n){ NodeTraits::set_left(p, NodeTraits::get_right(n)); @@ -1000,6 +665,16 @@ class splaytree_algorithms /// @endcond }; +/// @cond + +template +struct get_algo +{ + typedef splaytree_algorithms type; +}; + +/// @endcond + } //namespace intrusive } //namespace boost diff --git a/include/boost/intrusive/treap.hpp b/include/boost/intrusive/treap.hpp index 53eb2f3..d7a998f 100644 --- a/include/boost/intrusive/treap.hpp +++ b/include/boost/intrusive/treap.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008-2012 +// (C) Copyright Ion Gaztanaga 2008-2013 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -41,28 +42,15 @@ namespace intrusive { /// @cond -template -struct treap_setopt +struct treap_defaults { - typedef ValueTraits value_traits; - typedef Compare compare; - typedef PrioCompare priority_compare; - typedef SizeType size_type; - static const bool constant_time_size = ConstantTimeSize; + typedef detail::default_bstree_hook proto_value_traits; + static const bool constant_time_size = true; + typedef std::size_t size_type; + typedef void compare; + typedef void priority; }; -template -struct treap_set_defaults - : pack_options - < none - , base_hook - , constant_time_size - , size_type - , compare > - , priority > - >::type -{}; - /// @endcond //! The class template treap is an intrusive treap container that @@ -81,151 +69,78 @@ struct treap_set_defaults #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class treap_impl - : private detail::clear_on_destructor_base > -{ - template friend class detail::clear_on_destructor_base; - public: - typedef typename Config::value_traits value_traits; /// @cond - static const bool external_value_traits = - detail::external_value_traits_bool_is_true::value; - typedef typename detail::eval_if_c - < external_value_traits - , detail::eval_value_traits - , detail::identity - >::type real_value_traits; + : public bstree_impl + , public detail::ebo_functor_holder + < typename get_prio + < VoidOrPrioComp + , typename bstree_impl + ::value_type>::type + > /// @endcond - typedef typename real_value_traits::pointer pointer; - typedef typename real_value_traits::const_pointer const_pointer; - typedef typename pointer_traits::element_type value_type; - typedef typename pointer_traits::reference reference; - typedef typename pointer_traits::reference const_reference; - typedef typename pointer_traits::difference_type difference_type; - typedef value_type key_type; - typedef typename Config::size_type size_type; - typedef typename Config::compare value_compare; - typedef typename Config::priority_compare priority_compare; - typedef value_compare key_compare; - typedef tree_iterator iterator; - typedef tree_iterator const_iterator; - typedef boost::intrusive::detail::reverse_iterator reverse_iterator; - typedef boost::intrusive::detail::reverse_iteratorconst_reverse_iterator; - typedef typename real_value_traits::node_traits node_traits; - typedef typename node_traits::node node; - typedef typename pointer_traits - ::template rebind_pointer - ::type node_ptr; - typedef typename pointer_traits - ::template rebind_pointer - ::type const_node_ptr; - typedef treap_algorithms node_algorithms; +{ + public: + typedef ValueTraits value_traits; + /// @cond + 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; - static const bool constant_time_size = Config::constant_time_size; - static const bool stateful_value_traits = detail::is_stateful_value_traits::value; + typedef detail::ebo_functor_holder + 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; + typedef typename implementation_defined::key_type key_type; + typedef typename implementation_defined::reference reference; + typedef typename implementation_defined::const_reference const_reference; + typedef typename implementation_defined::difference_type difference_type; + typedef typename implementation_defined::size_type size_type; + typedef typename implementation_defined::value_compare value_compare; + typedef typename implementation_defined::key_compare key_compare; + typedef typename implementation_defined::iterator iterator; + typedef typename implementation_defined::const_iterator const_iterator; + typedef typename implementation_defined::reverse_iterator reverse_iterator; + typedef typename implementation_defined::const_reverse_iterator const_reverse_iterator; + typedef typename implementation_defined::node_traits node_traits; + typedef typename implementation_defined::node node; + typedef typename implementation_defined::node_ptr node_ptr; + typedef typename implementation_defined::const_node_ptr const_node_ptr; + typedef BOOST_INTRUSIVE_IMPDEF(treap_algorithms) node_algorithms; + typedef BOOST_INTRUSIVE_IMPDEF(typename get_prio_type::type) priority_compare; + + 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; /// @cond private: - typedef detail::size_holder size_traits; //noncopyable BOOST_MOVABLE_BUT_NOT_COPYABLE(treap_impl) - enum { safemode_or_autounlink = - (int)real_value_traits::link_mode == (int)auto_unlink || - (int)real_value_traits::link_mode == (int)safe_link }; - - //Constant-time size is incompatible with auto-unlink hooks! - BOOST_STATIC_ASSERT(!(constant_time_size && ((int)real_value_traits::link_mode == (int)auto_unlink))); - - struct header_plus_size : public size_traits - { node header_; }; - - struct node_plus_pred_t : public detail::ebo_functor_holder - { - node_plus_pred_t(const value_compare &comp, const priority_compare &p_comp) - : detail::ebo_functor_holder(comp) - , header_plus_priority_size_(p_comp) - {} - struct header_plus_priority_size - : public detail::ebo_functor_holder - { - header_plus_priority_size(const priority_compare &p_comp) - : detail::ebo_functor_holder(p_comp) - {} - header_plus_size header_plus_size_; - } header_plus_priority_size_; - }; - - struct data_t : public treap_impl::value_traits - { - typedef typename treap_impl::value_traits value_traits; - data_t(const value_compare & comp, const priority_compare &pcomp, const value_traits &val_traits) - : value_traits(val_traits), node_plus_pred_(comp, pcomp) - {} - node_plus_pred_t node_plus_pred_; - } data_; - - const value_compare &priv_comp() const - { return data_.node_plus_pred_.get(); } - - value_compare &priv_comp() - { return data_.node_plus_pred_.get(); } - const priority_compare &priv_pcomp() const - { return data_.node_plus_pred_.header_plus_priority_size_.get(); } + { return static_cast(*this).get(); } priority_compare &priv_pcomp() - { return data_.node_plus_pred_.header_plus_priority_size_.get(); } - - const value_traits &priv_value_traits() const - { return data_; } - - value_traits &priv_value_traits() - { return data_; } - - node_ptr priv_header_ptr() - { return pointer_traits::pointer_to(data_.node_plus_pred_.header_plus_priority_size_.header_plus_size_.header_); } - - const_node_ptr priv_header_ptr() const - { return pointer_traits::pointer_to(data_.node_plus_pred_.header_plus_priority_size_.header_plus_size_.header_); } - - static node_ptr uncast(const const_node_ptr & ptr) - { return pointer_traits::const_cast_from(ptr); } - - size_traits &priv_size_traits() - { return data_.node_plus_pred_.header_plus_priority_size_.header_plus_size_; } - - const size_traits &priv_size_traits() const - { return data_.node_plus_pred_.header_plus_priority_size_.header_plus_size_; } - - const real_value_traits &get_real_value_traits(detail::bool_) const - { return data_; } - - const real_value_traits &get_real_value_traits(detail::bool_) const - { return data_.get_value_traits(*this); } - - real_value_traits &get_real_value_traits(detail::bool_) - { return data_; } - - real_value_traits &get_real_value_traits(detail::bool_) - { return data_.get_value_traits(*this); } + { return static_cast(*this).get(); } /// @endcond public: - - const real_value_traits &get_real_value_traits() const - { return this->get_real_value_traits(detail::bool_()); } - - real_value_traits &get_real_value_traits() - { return this->get_real_value_traits(detail::bool_()); } - typedef typename node_algorithms::insert_commit_data insert_commit_data; - //! Effects: Constructs an empty treap. + //! Effects: Constructs an empty container. //! //! Complexity: Constant. //! @@ -235,16 +150,13 @@ class treap_impl explicit treap_impl( const value_compare &cmp = value_compare() , const priority_compare &pcmp = priority_compare() , const value_traits &v_traits = value_traits()) - : data_(cmp, pcmp, v_traits) - { - node_algorithms::init_header(this->priv_header_ptr()); - this->priv_size_traits().set_size(size_type(0)); - } + : tree_type(cmp, v_traits), prio_base(pcmp) + {} //! Requires: Dereferencing iterator must yield an lvalue of type value_type. //! cmp must be a comparison function that induces a strict weak ordering. //! - //! Effects: Constructs an empty treap and inserts elements from + //! Effects: Constructs an empty container and inserts elements from //! [b, e). //! //! Complexity: Linear in N if [b, e) is already sorted using @@ -259,92 +171,46 @@ class treap_impl , const value_compare &cmp = value_compare() , const priority_compare &pcmp = priority_compare() , const value_traits &v_traits = value_traits()) - : data_(cmp, pcmp, v_traits) + : tree_type(cmp, v_traits), prio_base(pcmp) { - node_algorithms::init_header(this->priv_header_ptr()); - this->priv_size_traits().set_size(size_type(0)); if(unique) this->insert_unique(b, e); else this->insert_equal(b, e); } - //! Effects: to-do - //! + //! @copydoc ::boost::intrusive::bstree::bstree(bstree &&) treap_impl(BOOST_RV_REF(treap_impl) x) - : data_( ::boost::move(x.priv_comp()) - , ::boost::move(x.priv_pcomp()) - , ::boost::move(x.priv_value_traits())) - { - node_algorithms::init_header(this->priv_header_ptr()); - this->priv_size_traits().set_size(size_type(0)); - this->swap(x); - } + : tree_type(::boost::move(static_cast(x))) + , prio_base(::boost::move(x.priv_pcomp())) + {} - //! Effects: to-do - //! + //! @copydoc ::boost::intrusive::bstree::operator=(bstree &&) treap_impl& operator=(BOOST_RV_REF(treap_impl) x) { this->swap(x); return *this; } - //! Effects: Detaches all elements from this. The objects in the set - //! are not deleted (i.e. no destructors are called), but the nodes according to - //! the value_traits template parameter are reinitialized and thus can be reused. - //! - //! Complexity: Linear to elements contained in *this - //! if constant-time size option is disabled. Constant time otherwise. - //! - //! Throws: Nothing. - ~treap_impl() - {} + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::bstree::~bstree() + ~treap_impl(); - //! Effects: Returns an iterator pointing to the beginning of the treap. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator begin() - { return iterator (node_traits::get_left(this->priv_header_ptr()), this); } + //! @copydoc ::boost::intrusive::bstree::begin() + iterator begin(); - //! Effects: Returns a const_iterator pointing to the beginning of the treap. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator begin() const - { return this->cbegin(); } + //! @copydoc ::boost::intrusive::bstree::begin()const + const_iterator begin() const; - //! Effects: Returns a const_iterator pointing to the beginning of the treap. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator cbegin() const - { return const_iterator (node_traits::get_left(this->priv_header_ptr()), this); } + //! @copydoc ::boost::intrusive::bstree::cbegin()const + const_iterator cbegin() const; - //! Effects: Returns an iterator pointing to the end of the treap. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator end() - { return iterator (this->priv_header_ptr(), this); } + //! @copydoc ::boost::intrusive::bstree::end() + iterator end(); - //! Effects: Returns a const_iterator pointing to the end of the treap. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator end() const - { return this->cend(); } - - //! Effects: Returns a const_iterator pointing to the end of the treap. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator cend() const - { return const_iterator (uncast(this->priv_header_ptr()), this); } + //! @copydoc ::boost::intrusive::bstree::end()const + const_iterator end() const; + //! @copydoc ::boost::intrusive::bstree::cend()const + const_iterator cend() const; + #endif //! Effects: Returns an iterator pointing to the highest priority object of the treap. //! @@ -352,7 +218,7 @@ class treap_impl //! //! Throws: Nothing. iterator top() - { return this->empty() ? this->end() : iterator (node_traits::get_parent(this->priv_header_ptr()), this); } + { return this->empty() ? this->end() : iterator(node_traits::get_parent(this->tree_type::header_ptr()), this); } //! Effects: Returns a const_iterator pointing to the highest priority object of the treap.. //! @@ -368,61 +234,27 @@ class treap_impl //! //! Throws: Nothing. const_iterator ctop() const - { return this->empty() ? this->cend() : const_iterator (node_traits::get_parent(this->priv_header_ptr()), this); } + { return this->empty() ? this->cend() : const_iterator(node_traits::get_parent(this->tree_type::header_ptr()), this); } - //! Effects: Returns a reverse_iterator pointing to the beginning of the - //! reversed treap. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - reverse_iterator rbegin() - { return reverse_iterator(this->end()); } + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::bstree::rbegin() + reverse_iterator rbegin(); - //! Effects: Returns a const_reverse_iterator pointing to the beginning - //! of the reversed treap. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator rbegin() const - { return const_reverse_iterator(this->end()); } + //! @copydoc ::boost::intrusive::bstree::rbegin()const + const_reverse_iterator rbegin() const; - //! Effects: Returns a const_reverse_iterator pointing to the beginning - //! of the reversed treap. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator crbegin() const - { return const_reverse_iterator(this->end()); } + //! @copydoc ::boost::intrusive::bstree::crbegin()const + const_reverse_iterator crbegin() const; - //! Effects: Returns a reverse_iterator pointing to the end - //! of the reversed treap. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - reverse_iterator rend() - { return reverse_iterator(this->begin()); } + //! @copydoc ::boost::intrusive::bstree::rend() + reverse_iterator rend(); - //! Effects: Returns a const_reverse_iterator pointing to the end - //! of the reversed treap. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator rend() const - { return const_reverse_iterator(this->begin()); } + //! @copydoc ::boost::intrusive::bstree::rend()const + const_reverse_iterator rend() const; - //! Effects: Returns a const_reverse_iterator pointing to the end - //! of the reversed treap. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator crend() const - { return const_reverse_iterator(this->begin()); } + //! @copydoc ::boost::intrusive::bstree::crend()const + const_reverse_iterator crend() const; + #endif //! Effects: Returns a reverse_iterator pointing to the highest priority object of the //! reversed treap. @@ -451,59 +283,33 @@ class treap_impl const_reverse_iterator crtop() const { return const_reverse_iterator(this->top()); } - //! Precondition: end_iterator must be a valid end iterator - //! of treap. - //! - //! Effects: Returns a const reference to the treap associated to the end iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - static treap_impl &container_from_end_iterator(iterator end_iterator) - { return priv_container_from_end_iterator(end_iterator); } + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::bstree::container_from_end_iterator(iterator) + static treap_impl &container_from_end_iterator(iterator end_iterator); - //! Precondition: end_iterator must be a valid end const_iterator - //! of treap. - //! - //! Effects: Returns a const reference to the treap associated to the iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - static const treap_impl &container_from_end_iterator(const_iterator end_iterator) - { return priv_container_from_end_iterator(end_iterator); } + //! @copydoc ::boost::intrusive::bstree::container_from_end_iterator(const_iterator) + static const treap_impl &container_from_end_iterator(const_iterator end_iterator); - //! Precondition: it must be a valid iterator - //! of treap. - //! - //! Effects: Returns a const reference to the treap associated to the iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Logarithmic. - static treap_impl &container_from_iterator(iterator it) - { return priv_container_from_iterator(it); } + //! @copydoc ::boost::intrusive::bstree::container_from_iterator(iterator) + static treap_impl &container_from_iterator(iterator it); - //! Precondition: it must be a valid end const_iterator - //! of treap. - //! - //! Effects: Returns a const reference to the treap associated to the end iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Logarithmic. - static const treap_impl &container_from_iterator(const_iterator it) - { return priv_container_from_iterator(it); } + //! @copydoc ::boost::intrusive::bstree::container_from_iterator(const_iterator) + static const treap_impl &container_from_iterator(const_iterator it); - //! Effects: Returns the value_compare object used by the treap. - //! - //! Complexity: Constant. - //! - //! Throws: If value_compare copy-constructor throws. - value_compare value_comp() const - { return this->priv_comp(); } + //! @copydoc ::boost::intrusive::bstree::key_comp()const + key_compare key_comp() const; - //! Effects: Returns the priority_compare object used by the treap. + //! @copydoc ::boost::intrusive::bstree::value_comp()const + value_compare value_comp() const; + + //! @copydoc ::boost::intrusive::bstree::empty()const + bool empty() const; + + //! @copydoc ::boost::intrusive::bstree::size()const + size_type size() const; + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + + //! Effects: Returns the priority_compare object used by the container. //! //! Complexity: Constant. //! @@ -511,29 +317,6 @@ class treap_impl priority_compare priority_comp() const { return this->priv_pcomp(); } - //! Effects: Returns true if the container is empty. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - bool empty() const - { return node_algorithms::unique(this->priv_header_ptr()); } - - //! Effects: Returns the number of elements stored in the treap. - //! - //! Complexity: Linear to elements contained in *this - //! if constant-time size option is disabled. Constant time otherwise. - //! - //! Throws: Nothing. - size_type size() const - { - if(constant_time_size) - return this->priv_size_traits().get_size(); - else{ - return (size_type)node_algorithms::size(this->priv_header_ptr()); - } - } - //! Effects: Swaps the contents of two treaps. //! //! Complexity: Constant. @@ -541,22 +324,36 @@ class treap_impl //! Throws: If the comparison functor's swap call throws. void swap(treap_impl& other) { + tree_type::swap(other); //This can throw using std::swap; - swap(priv_comp(), priv_comp()); - swap(priv_pcomp(), priv_pcomp()); - //These can't throw - node_algorithms::swap_tree(this->priv_header_ptr(), other.priv_header_ptr()); - if(constant_time_size){ - size_type backup = this->priv_size_traits().get_size(); - this->priv_size_traits().set_size(other.priv_size_traits().get_size()); - other.priv_size_traits().set_size(backup); - } + swap(this->priv_pcomp(), other.priv_pcomp()); + } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! Cloner should yield to nodes equivalent to the original nodes. + //! + //! Effects: Erases all the elements from *this + //! calling Disposer::operator()(pointer), clones all the + //! elements from src calling Cloner::operator()(const_reference ) + //! and inserts them on *this. Copies the predicate from the source container. + //! + //! If cloner throws, all cloned elements are unlinked and disposed + //! calling Disposer::operator()(pointer). + //! + //! Complexity: Linear to erased plus inserted elements. + //! + //! Throws: If cloner throws or predicate copy assignment throws. Basic guarantee. + template + void clone_from(const treap_impl &src, Cloner cloner, Disposer disposer) + { + tree_type::clone_from(src, cloner, disposer); + this->priv_pcomp() = src.priv_pcomp(); } //! Requires: value must be an lvalue //! - //! Effects: Inserts value into the treap before the upper bound. + //! Effects: Inserts value into the container before the upper bound. //! //! Complexity: Average complexity for insert element is at //! most logarithmic. @@ -567,23 +364,23 @@ class treap_impl //! No copy-constructors are called. iterator insert_equal(reference value) { - detail::key_nodeptr_comp - key_node_comp(priv_comp(), this); - detail::key_nodeptr_comp - key_node_pcomp(priv_pcomp(), this); - node_ptr to_insert(get_real_value_traits().to_node_ptr(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)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); iterator ret(node_algorithms::insert_equal_upper_bound - (this->priv_header_ptr(), to_insert, key_node_comp, key_node_pcomp), this); - this->priv_size_traits().increment(); + (this->tree_type::header_ptr(), to_insert, key_node_comp, key_node_pcomp), this->real_value_traits_ptr()); + this->tree_type::sz_traits().increment(); return ret; } //! Requires: value must be an lvalue, and "hint" must be //! a valid iterator. //! - //! Effects: Inserts x into the treap, using "hint" as a hint to + //! Effects: Inserts x into the container, using "hint" as a hint to //! where it will be inserted. If "hint" is the upper_bound //! the insertion takes constant time (two comparisons in the worst case) //! @@ -596,23 +393,23 @@ class treap_impl //! No copy-constructors are called. iterator insert_equal(const_iterator hint, reference value) { - detail::key_nodeptr_comp - key_node_comp(priv_comp(), this); - detail::key_nodeptr_comp - key_node_pcomp(priv_pcomp(), this); - node_ptr to_insert(get_real_value_traits().to_node_ptr(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)); if(safemode_or_autounlink) BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); iterator ret (node_algorithms::insert_equal - (this->priv_header_ptr(), hint.pointed_node(), to_insert, key_node_comp, key_node_pcomp), this); - this->priv_size_traits().increment(); + (this->tree_type::header_ptr(), hint.pointed_node(), to_insert, key_node_comp, key_node_pcomp), this->real_value_traits_ptr()); + this->tree_type::sz_traits().increment(); return ret; } //! Requires: Dereferencing iterator must yield an lvalue //! of type value_type. //! - //! Effects: Inserts a each element of a range into the treap + //! Effects: Inserts a each element of a range into the container //! before the upper bound of the key of each element. //! //! Complexity: Insert range is in general O(N * log(N)), where N is the @@ -634,7 +431,7 @@ class treap_impl //! Requires: value must be an lvalue //! - //! Effects: Inserts value into the treap if the value + //! Effects: Inserts value into the container if the value //! is not already present. //! //! Complexity: Average complexity for insert element is at @@ -648,7 +445,7 @@ class treap_impl std::pair insert_unique(reference value) { insert_commit_data commit_data; - std::pair ret = insert_unique_check(value, priv_comp(), priv_pcomp(), commit_data); + std::pair ret = insert_unique_check(value, this->value_comp(), this->priv_pcomp(), commit_data); if(!ret.second) return ret; return std::pair (insert_unique_commit(value, commit_data), true); @@ -657,7 +454,7 @@ class treap_impl //! Requires: value must be an lvalue, and "hint" must be //! a valid iterator //! - //! Effects: Tries to insert x into the treap, using "hint" as a hint + //! Effects: Tries to insert x into the container, using "hint" as a hint //! to where it will be inserted. //! //! Complexity: Logarithmic in general, but it is amortized @@ -672,7 +469,7 @@ class treap_impl iterator insert_unique(const_iterator hint, reference value) { insert_commit_data commit_data; - std::pair ret = insert_unique_check(hint, value, priv_comp(), priv_pcomp(), commit_data); + std::pair ret = insert_unique_check(hint, value, this->value_comp(), this->priv_pcomp(), commit_data); if(!ret.second) return ret.first; return insert_unique_commit(value, commit_data); @@ -681,7 +478,7 @@ class treap_impl //! Requires: Dereferencing iterator must yield an lvalue //! of type value_type. //! - //! Effects: Tries to insert each element of a range into the treap. + //! Effects: Tries to insert each element of a range into the container. //! //! Complexity: Insert range is in general O(N * log(N)), where N is the //! size of the range. However, it is linear in N if the range is already sorted @@ -744,14 +541,14 @@ class treap_impl ( const KeyType &key, KeyValueCompare key_value_comp , KeyValuePrioCompare key_value_pcomp, insert_commit_data &commit_data) { - detail::key_nodeptr_comp - comp(key_value_comp, this); - detail::key_nodeptr_comp - pcomp(key_value_pcomp, this); + detail::key_nodeptr_comp + comp(key_value_comp, &this->get_real_value_traits()); + detail::key_nodeptr_comp + pcomp(key_value_pcomp, &this->get_real_value_traits()); std::pair ret = (node_algorithms::insert_unique_check - (this->priv_header_ptr(), key, comp, pcomp, commit_data)); - return std::pair(iterator(ret.first, this), ret.second); + (this->tree_type::header_ptr(), key, comp, pcomp, commit_data)); + return std::pair(iterator(ret.first, this->real_value_traits_ptr()), ret.second); } //! Requires: key_value_comp must be a comparison function that induces @@ -796,14 +593,14 @@ class treap_impl , KeyValuePrioCompare key_value_pcomp , insert_commit_data &commit_data) { - detail::key_nodeptr_comp - comp(key_value_comp, this); - detail::key_nodeptr_comp - pcomp(key_value_pcomp, this); + detail::key_nodeptr_comp + comp(key_value_comp, &this->get_real_value_traits()); + detail::key_nodeptr_comp + pcomp(key_value_pcomp, &this->get_real_value_traits()); std::pair ret = (node_algorithms::insert_unique_check - (this->priv_header_ptr(), hint.pointed_node(), key, comp, pcomp, commit_data)); - return std::pair(iterator(ret.first, this), ret.second); + (this->tree_type::header_ptr(), hint.pointed_node(), key, comp, pcomp, commit_data)); + return std::pair(iterator(ret.first, this->real_value_traits_ptr()), ret.second); } //! Requires: value must be an lvalue of type value_type. commit_data @@ -825,89 +622,89 @@ 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(get_real_value_traits().to_node_ptr(value)); + node_ptr to_insert(this->get_real_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->priv_header_ptr(), to_insert, commit_data); - this->priv_size_traits().increment(); - return iterator(to_insert, this); + 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()); } //! Requires: value must be an lvalue, "pos" must be //! a valid iterator (or end) and must be the succesor of value //! once inserted according to the predicate //! - //! Effects: Inserts x into the treap before "pos". + //! Effects: Inserts x into the container before "pos". //! //! Complexity: Constant time. //! //! Throws: If the internal priority_compare function throws. Strong guarantee. //! //! Note: This function does not check preconditions so if "pos" is not - //! the successor of "value" treap ordering invariant will be broken. + //! the successor of "value" container ordering invariant will be broken. //! This is a low-level function to be used only for performance reasons //! by advanced users. iterator insert_before(const_iterator pos, reference value) { - node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + node_ptr to_insert(this->get_real_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(priv_pcomp(), this); + detail::key_nodeptr_comp + pcomp(this->priv_pcomp(), &this->get_real_value_traits()); iterator ret (node_algorithms::insert_before - (this->priv_header_ptr(), pos.pointed_node(), to_insert, pcomp), this); - this->priv_size_traits().increment(); + (this->tree_type::header_ptr(), pos.pointed_node(), to_insert, pcomp), this->real_value_traits_ptr()); + this->tree_type::sz_traits().increment(); return ret; } //! Requires: value must be an lvalue, and it must be no less //! than the greatest inserted key //! - //! Effects: Inserts x into the treap in the last position. + //! Effects: Inserts x into the container in the last position. //! //! Complexity: Constant time. //! //! Throws: If the internal priority_compare function throws. Strong guarantee. //! //! Note: This function does not check preconditions so if value is - //! less than the greatest inserted key treap ordering invariant will be broken. + //! less than the greatest inserted key container ordering invariant will be broken. //! This function is slightly more efficient than using "insert_before". //! This is a low-level function to be used only for performance reasons //! by advanced users. void push_back(reference value) { - node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + node_ptr to_insert(this->get_real_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(priv_pcomp(), this); - node_algorithms::push_back(this->priv_header_ptr(), to_insert, pcomp); - this->priv_size_traits().increment(); + detail::key_nodeptr_comp + pcomp(this->priv_pcomp(), &this->get_real_value_traits()); + node_algorithms::push_back(this->tree_type::header_ptr(), to_insert, pcomp); + this->tree_type::sz_traits().increment(); } //! Requires: value must be an lvalue, and it must be no greater //! than the minimum inserted key //! - //! Effects: Inserts x into the treap in the first position. + //! Effects: Inserts x into the container in the first position. //! //! Complexity: Constant time. //! //! Throws: If the internal priority_compare function throws. Strong guarantee. //! //! Note: This function does not check preconditions so if value is - //! greater than the minimum inserted key treap ordering invariant will be broken. + //! greater than the minimum inserted key container ordering invariant will be broken. //! This function is slightly more efficient than using "insert_before". //! This is a low-level function to be used only for performance reasons //! by advanced users. void push_front(reference value) { - node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + node_ptr to_insert(this->get_real_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(priv_pcomp(), this); - node_algorithms::push_front(this->priv_header_ptr(), to_insert, pcomp); - this->priv_size_traits().increment(); + detail::key_nodeptr_comp + pcomp(this->priv_pcomp(), &this->get_real_value_traits()); + node_algorithms::push_front(this->tree_type::header_ptr(), to_insert, pcomp); + this->tree_type::sz_traits().increment(); } //! Effects: Erases the element pointed to by pos. @@ -925,10 +722,10 @@ 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(priv_pcomp(), this); - node_algorithms::erase(this->priv_header_ptr(), to_erase, key_node_pcomp); - this->priv_size_traits().decrement(); + detail::key_nodeptr_comp + key_node_pcomp(this->priv_pcomp(), &this->get_real_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) node_algorithms::init(to_erase); return ret.unconst(); @@ -957,7 +754,7 @@ class treap_impl //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. size_type erase(const_reference value) - { return this->erase(value, priv_comp()); } + { return this->erase(value, this->value_comp()); } //! Effects: Erases all the elements with the given key. //! according to the comparison functor "comp". @@ -1000,7 +797,7 @@ class treap_impl { node_ptr to_erase(i.pointed_node()); iterator ret(this->erase(i)); - disposer(get_real_value_traits().to_value_ptr(to_erase)); + disposer(this->get_real_value_traits().to_value_ptr(to_erase)); return ret; } @@ -1087,15 +884,7 @@ class treap_impl //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. void clear() - { - if(safemode_or_autounlink){ - this->clear_and_dispose(detail::null_disposer()); - } - else{ - node_algorithms::init_header(priv_header_ptr()); - this->priv_size_traits().set_size(0); - } - } + { tree_type::clear(); } //! Effects: Erases all of the elements calling disposer(p) for //! each node to be erased. @@ -1109,484 +898,121 @@ class treap_impl template void clear_and_dispose(Disposer disposer) { - node_algorithms::clear_and_dispose(this->priv_header_ptr() - , detail::node_disposer(disposer, this)); - node_algorithms::init_header(this->priv_header_ptr()); - this->priv_size_traits().set_size(0); + node_algorithms::clear_and_dispose(this->tree_type::header_ptr() + , detail::node_disposer(disposer, &this->get_real_value_traits())); + node_algorithms::init_header(this->tree_type::header_ptr()); + this->tree_type::sz_traits().set_size(0); } - //! Effects: Returns the number of contained elements with the given value - //! - //! Complexity: Logarithmic to the number of elements contained plus lineal - //! to number of objects with the given value. - //! - //! Throws: Nothing. - size_type count(const_reference value) const - { return this->count(value, priv_comp()); } + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::bstree::count(const_reference)const + size_type count(const_reference value) const; - //! Effects: Returns the number of contained elements with the given key - //! - //! Complexity: Logarithmic to the number of elements contained plus lineal - //! to number of objects with the given key. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const template - size_type count(const KeyType &key, KeyValueCompare comp) const - { - std::pair ret = this->equal_range(key, comp); - return std::distance(ret.first, ret.second); - } - - //! Effects: Returns an iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - iterator lower_bound(const_reference value) - { return this->lower_bound(value, priv_comp()); } - - //! Effects: Returns an iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - const_iterator lower_bound(const_reference value) const - { return this->lower_bound(value, priv_comp()); } - - //! Effects: Returns an iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + size_type count(const KeyType& key, KeyValueCompare comp) const; + + //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference) + iterator lower_bound(const_reference value); + + //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare) template - iterator lower_bound(const KeyType &key, KeyValueCompare comp) - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - return iterator(node_algorithms::lower_bound - (this->priv_header_ptr(), key, key_node_comp), this); - } + iterator lower_bound(const KeyType& key, KeyValueCompare comp); - //! Effects: Returns a const iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference)const + const_iterator lower_bound(const_reference value) const; + + //! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare)const template - const_iterator lower_bound(const KeyType &key, KeyValueCompare comp) const - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - return const_iterator(node_algorithms::lower_bound - (this->priv_header_ptr(), key, key_node_comp), this); - } + const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Returns an iterator to the first element whose - //! key is greater than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - iterator upper_bound(const_reference value) - { return this->upper_bound(value, priv_comp()); } + //! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference) + iterator upper_bound(const_reference value); - //! Effects: Returns an iterator to the first element whose - //! key is greater than k according to comp or end() if that element - //! does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare) template - iterator upper_bound(const KeyType &key, KeyValueCompare comp) - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - return iterator(node_algorithms::upper_bound - (this->priv_header_ptr(), key, key_node_comp), this); - } + iterator upper_bound(const KeyType& key, KeyValueCompare comp); - //! Effects: Returns an iterator to the first element whose - //! key is greater than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - const_iterator upper_bound(const_reference value) const - { return this->upper_bound(value, priv_comp()); } + //! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference)const + const_iterator upper_bound(const_reference value) const; - //! Effects: Returns an iterator to the first element whose - //! key is greater than k according to comp or end() if that element - //! does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare)const template - const_iterator upper_bound(const KeyType &key, KeyValueCompare comp) const - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - return const_iterator(node_algorithms::upper_bound - (this->priv_header_ptr(), key, key_node_comp), this); - } + const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Finds an iterator to the first element whose key is - //! k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - iterator find(const_reference value) - { return this->find(value, priv_comp()); } + //! @copydoc ::boost::intrusive::bstree::find(const_reference) + iterator find(const_reference value); - //! Effects: Finds an iterator to the first element whose key is - //! k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare) template - iterator find(const KeyType &key, KeyValueCompare comp) - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - return iterator - (node_algorithms::find(this->priv_header_ptr(), key, key_node_comp), this); - } + iterator find(const KeyType& key, KeyValueCompare comp); - //! Effects: Finds a const_iterator to the first element whose key is - //! k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - const_iterator find(const_reference value) const - { return this->find(value, priv_comp()); } + //! @copydoc ::boost::intrusive::bstree::find(const_reference)const + const_iterator find(const_reference value) const; - //! Effects: Finds a const_iterator to the first element whose key is - //! k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare)const template - const_iterator find(const KeyType &key, KeyValueCompare comp) const - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - return const_iterator - (node_algorithms::find(this->priv_header_ptr(), key, key_node_comp), this); - } + const_iterator find(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - std::pair equal_range(const_reference value) - { return this->equal_range(value, priv_comp()); } + //! @copydoc ::boost::intrusive::bstree::equal_range(const_reference) + std::pair equal_range(const_reference value); - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare) template - std::pair equal_range(const KeyType &key, KeyValueCompare comp) - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - std::pair ret - (node_algorithms::equal_range(this->priv_header_ptr(), key, key_node_comp)); - return std::pair(iterator(ret.first, this), iterator(ret.second, this)); - } + std::pair equal_range(const KeyType& key, KeyValueCompare comp); - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::equal_range(const_reference)const std::pair - equal_range(const_reference value) const - { return this->equal_range(value, priv_comp()); } + equal_range(const_reference value) const; - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. + //! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare)const template std::pair - equal_range(const KeyType &key, KeyValueCompare comp) const - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - std::pair ret - (node_algorithms::equal_range(this->priv_header_ptr(), key, key_node_comp)); - return std::pair(const_iterator(ret.first, this), const_iterator(ret.second, this)); - } + equal_range(const KeyType& key, KeyValueCompare comp) const; - //! Requires: 'lower_value' must not be greater than 'upper_value'. If - //! 'lower_value' == 'upper_value', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise - //! - //! second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the predicate throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_value and upper_value. + //! @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) - { return this->bounded_range(lower_value, upper_value, priv_comp(), left_closed, right_closed); } + (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); - //! Requires: KeyValueCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. - //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If - //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key, comp) if left_closed, upper_bound(lower_key, comp) otherwise - //! - //! second = upper_bound(upper_key, comp) if right_closed, lower_bound(upper_key, comp) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_key and upper_key. + //! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool) template std::pair bounded_range - (const KeyType &lower_key, const KeyType &upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - std::pair ret - (node_algorithms::bounded_range - (this->priv_header_ptr(), lower_key, upper_key, key_node_comp, left_closed, right_closed)); - return std::pair(iterator(ret.first, this), iterator(ret.second, this)); - } + (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed); - //! Requires: 'lower_value' must not be greater than 'upper_value'. If - //! 'lower_value' == 'upper_value', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise - //! - //! second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the predicate throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_value and upper_value. - std::pair bounded_range - (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const - { return this->bounded_range(lower_value, upper_value, priv_comp(), left_closed, right_closed); } + //! @copydoc ::boost::intrusive::bstree::bounded_range(const_reference,const_reference,bool,bool)const + std::pair + bounded_range(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; - //! Requires: KeyValueCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. - //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If - //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key, comp) if left_closed, upper_bound(lower_key, comp) otherwise - //! - //! second = upper_bound(upper_key, comp) if right_closed, lower_bound(upper_key, comp) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_key and upper_key. + //! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const template - std::pair bounded_range - (const KeyType &lower_key, const KeyType &upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const - { - detail::key_nodeptr_comp - key_node_comp(comp, this); - std::pair ret - (node_algorithms::bounded_range - (this->priv_header_ptr(), lower_key, upper_key, key_node_comp, left_closed, right_closed)); - return std::pair(const_iterator(ret.first, this), const_iterator(ret.second, this)); - } + std::pair bounded_range + (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! Cloner should yield to nodes equivalent to the original nodes. - //! - //! Effects: Erases all the elements from *this - //! calling Disposer::operator()(pointer), clones all the - //! elements from src calling Cloner::operator()(const_reference ) - //! and inserts them on *this. Copies the predicate from the source container. - //! - //! If cloner throws, all cloned elements are unlinked and disposed - //! calling Disposer::operator()(pointer). - //! - //! Complexity: Linear to erased plus inserted elements. - //! - //! Throws: If cloner throws or predicate copy assignment throws. Basic guarantee. - template - void clone_from(const treap_impl &src, Cloner cloner, Disposer disposer) - { - this->clear_and_dispose(disposer); - if(!src.empty()){ - detail::exception_disposer - rollback(*this, disposer); - node_algorithms::clone - (src.priv_header_ptr() - ,this->priv_header_ptr() - ,detail::node_cloner(cloner, this) - ,detail::node_disposer(disposer, this)); - this->priv_size_traits().set_size(src.priv_size_traits().get_size()); - this->priv_comp() = src.priv_comp(); - rollback.release(); - } - } + //! @copydoc ::boost::intrusive::bstree::s_iterator_to(reference) + static iterator s_iterator_to(reference value); - //! Effects: Unlinks the leftmost node from the treap. - //! - //! Complexity: Average complexity is constant time. - //! - //! Throws: Nothing. - //! - //! Notes: This function breaks the treap and the treap can - //! only be used for more unlink_leftmost_without_rebalance calls. - //! This function is normally used to achieve a step by step - //! controlled destruction of the treap. - pointer unlink_leftmost_without_rebalance() - { - node_ptr to_be_disposed(node_algorithms::unlink_leftmost_without_rebalance - (this->priv_header_ptr())); - if(!to_be_disposed) - return 0; - this->priv_size_traits().decrement(); - if(safemode_or_autounlink)//If this is commented does not work with normal_link - node_algorithms::init(to_be_disposed); - return get_real_value_traits().to_value_ptr(to_be_disposed); - } + //! @copydoc ::boost::intrusive::bstree::s_iterator_to(const_reference) + static const_iterator s_iterator_to(const_reference value); - //! Requires: replace_this must be a valid iterator of *this - //! and with_this must not be inserted in any treap. - //! - //! Effects: Replaces replace_this in its position in the - //! treap with with_this. The treap does not need to be rebalanced. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This function will break container ordering invariants if - //! with_this is not equivalent to *replace_this according to the - //! ordering and priority rules. This function is faster than erasing and inserting - //! the node, since no rebalancing or comparison is needed. - void replace_node(iterator replace_this, reference with_this) - { - node_algorithms::replace_node( get_real_value_traits().to_node_ptr(*replace_this) - , this->priv_header_ptr() - , get_real_value_traits().to_node_ptr(with_this)); - if(safemode_or_autounlink) - node_algorithms::init(replace_this.pointed_node()); - } + //! @copydoc ::boost::intrusive::bstree::iterator_to(reference) + iterator iterator_to(reference value); - //! Requires: value must be an lvalue and shall be in a set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid iterator i belonging to the set - //! that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This static function is available only if the value traits - //! is stateless. - static iterator s_iterator_to(reference value) - { - BOOST_STATIC_ASSERT((!stateful_value_traits)); - return iterator (value_traits::to_node_ptr(value), 0); - } + //! @copydoc ::boost::intrusive::bstree::iterator_to(const_reference)const + const_iterator iterator_to(const_reference value) const; - //! Requires: value must be an lvalue and shall be in a set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid const_iterator i belonging to the - //! set that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This static function is available only if the value traits - //! is stateless. - static const_iterator s_iterator_to(const_reference value) - { - BOOST_STATIC_ASSERT((!stateful_value_traits)); - return const_iterator (value_traits::to_node_ptr(const_cast (value)), 0); - } + //! @copydoc ::boost::intrusive::bstree::init_node(reference) + static void init_node(reference value); - //! Requires: value must be an lvalue and shall be in a set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid iterator i belonging to the set - //! that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator iterator_to(reference value) - { return iterator (value_traits::to_node_ptr(value), this); } + //! @copydoc ::boost::intrusive::bstree::unlink_leftmost_without_rebalance + pointer unlink_leftmost_without_rebalance(); - //! Requires: value must be an lvalue and shall be in a set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid const_iterator i belonging to the - //! set that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator iterator_to(const_reference value) const - { return const_iterator (value_traits::to_node_ptr(const_cast (value)), this); } + //! @copydoc ::boost::intrusive::bstree::replace_node + void replace_node(iterator replace_this, reference with_this); - //! Requires: value shall not be in a treap. - //! - //! Effects: init_node puts the hook of a value in a well-known default - //! state. - //! - //! Throws: Nothing. - //! - //! Complexity: Constant time. - //! - //! Note: This function puts the hook in the well-known default state - //! used by auto_unlink and safe hooks. - static void init_node(reference value) - { node_algorithms::init(value_traits::to_node_ptr(value)); } + //! @copydoc ::boost::intrusive::bstree::remove_node + void remove_node(reference value); + + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED /// @cond private: @@ -1605,197 +1031,62 @@ class treap_impl return b.unconst(); } /// @endcond - - private: - static treap_impl &priv_container_from_end_iterator(const const_iterator &end_iterator) - { - header_plus_size *r = detail::parent_from_member - ( boost::intrusive::detail::to_raw_pointer(end_iterator.pointed_node()), &header_plus_size::header_); - typename node_plus_pred_t::header_plus_priority_size *n = - detail::parent_from_member - < typename node_plus_pred_t::header_plus_priority_size - , header_plus_size> - (r, &node_plus_pred_t::header_plus_priority_size::header_plus_size_); - node_plus_pred_t *pn = detail::parent_from_member - < node_plus_pred_t - , typename node_plus_pred_t::header_plus_priority_size> - (n, &node_plus_pred_t::header_plus_priority_size_); - data_t *d = detail::parent_from_member(pn, &data_t::node_plus_pred_); - treap_impl *tr = detail::parent_from_member(d, &treap_impl::data_); - return *tr; - } - - static treap_impl &priv_container_from_iterator(const const_iterator &it) - { return priv_container_from_end_iterator(it.end_iterator_from_it()); } }; #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + template -#else -template -#endif -inline bool operator< -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const treap_impl &x, const treap_impl &y) -#else -(const treap_impl &x, const treap_impl &y) -#endif -{ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } +bool operator< (const treap_impl &x, const treap_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -bool operator== -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const treap_impl &x, const treap_impl &y) -#else -(const treap_impl &x, const treap_impl &y) -#endif -{ - typedef treap_impl tree_type; - typedef typename tree_type::const_iterator const_iterator; +bool operator==(const treap_impl &x, const treap_impl &y); - if(tree_type::constant_time_size && x.size() != y.size()){ - return false; - } - const_iterator end1 = x.end(); - const_iterator i1 = x.begin(); - const_iterator i2 = y.begin(); - if(tree_type::constant_time_size){ - while (i1 != end1 && *i1 == *i2) { - ++i1; - ++i2; - } - return i1 == end1; - } - else{ - const_iterator end2 = y.end(); - while (i1 != end1 && i2 != end2 && *i1 == *i2) { - ++i1; - ++i2; - } - return i1 == end1 && i2 == end2; - } -} - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator!= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const treap_impl &x, const treap_impl &y) -#else -(const treap_impl &x, const treap_impl &y) -#endif -{ return !(x == y); } +bool operator!= (const treap_impl &x, const treap_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator> -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const treap_impl &x, const treap_impl &y) -#else -(const treap_impl &x, const treap_impl &y) -#endif -{ return y < x; } +bool operator>(const treap_impl &x, const treap_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator<= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const treap_impl &x, const treap_impl &y) -#else -(const treap_impl &x, const treap_impl &y) -#endif -{ return !(y < x); } +bool operator<=(const treap_impl &x, const treap_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline bool operator>= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const treap_impl &x, const treap_impl &y) -#else -(const treap_impl &x, const treap_impl &y) -#endif -{ return !(x < y); } +bool operator>=(const treap_impl &x, const treap_impl &y); -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template -#else -template -#endif -inline void swap -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(treap_impl &x, treap_impl &y) -#else -(treap_impl &x, treap_impl &y) -#endif -{ x.swap(y); } +void swap(treap_impl &x, treap_impl &y); -/// @cond -#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) -template -#else -template -#endif -struct make_treap_opt -{ - typedef typename pack_options - < treap_set_defaults, - #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) - O1, O2, O3, O4 - #else - Options... - #endif - >::type packed_options; - typedef typename detail::get_value_traits - ::type value_traits; - - typedef treap_setopt - < value_traits - , typename packed_options::compare - , typename packed_options::priority - , typename packed_options::size_type - , packed_options::constant_time_size - > type; -}; -/// @endcond +#endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) //! Helper metafunction to define a \c treap that yields to the same type when the //! same options (either explicitly or implicitly) are used. #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else -template +template #endif -struct make_trie +struct make_treap { - /// @cond + typedef typename pack_options + < treap_defaults, + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3, O4 + #else + Options... + #endif + >::type packed_options; + + typedef typename detail::get_value_traits + ::type value_traits; + typedef treap_impl - < typename make_treap_opt::type - > implementation_defined; + < value_traits + , typename packed_options::compare + , typename packed_options::priority + , typename packed_options::size_type + , packed_options::constant_time_size + > implementation_defined; /// @endcond typedef implementation_defined type; }; @@ -1808,7 +1099,7 @@ template template #endif class treap - : public make_trie::type { - typedef typename make_trie + typedef typename make_treap ::value)); @@ -1856,7 +1149,7 @@ class treap {} treap& operator=(BOOST_RV_REF(treap) x) - { this->Base::operator=(::boost::move(static_cast(x))); return *this; } + { return static_cast(this->Base::operator=(::boost::move(static_cast(x)))); } static treap &container_from_end_iterator(iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } @@ -1864,16 +1157,15 @@ class treap static const treap &container_from_end_iterator(const_iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } - static treap &container_from_it(iterator it) + static treap &container_from_iterator(iterator it) { return static_cast(Base::container_from_iterator(it)); } - static const treap &container_from_it(const_iterator it) + static const treap &container_from_iterator(const_iterator it) { return static_cast(Base::container_from_iterator(it)); } }; #endif - } //namespace intrusive } //namespace boost diff --git a/include/boost/intrusive/treap_algorithms.hpp b/include/boost/intrusive/treap_algorithms.hpp index e891ef9..443075c 100644 --- a/include/boost/intrusive/treap_algorithms.hpp +++ b/include/boost/intrusive/treap_algorithms.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012. +// (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 @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include @@ -47,7 +47,7 @@ namespace intrusive { //! //! Typedefs: //! -//! node: The type of the node that forms the circular list +//! node: The type of the node that forms the treap //! //! node_ptr: A pointer to a node //! @@ -68,6 +68,9 @@ namespace intrusive { //! static void set_right(node_ptr n, node_ptr right); template class treap_algorithms + #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + : public bstree_algorithms + #endif { public: typedef NodeTraits node_traits; @@ -78,32 +81,8 @@ class treap_algorithms /// @cond private: - class remove_on_destroy - { - remove_on_destroy(const remove_on_destroy&); - remove_on_destroy& operator=(const remove_on_destroy&); - public: - remove_on_destroy(const node_ptr & header, const node_ptr & z) - : header_(header), z_(z), remove_it_(true) - {} - ~remove_on_destroy() - { - if(remove_it_){ - tree_algorithms::erase(header_, z_); - } - } - - void release() - { remove_it_ = false; } - - const node_ptr header_; - const node_ptr z_; - bool remove_it_; - }; - class rerotate_on_destroy { - rerotate_on_destroy(const remove_on_destroy&); rerotate_on_destroy& operator=(const rerotate_on_destroy&); public: @@ -134,33 +113,24 @@ class treap_algorithms ; p_parent = NodeTraits::get_parent(p)){ //Check if left child if(p == NodeTraits::get_left(p_parent)){ - tree_algorithms::rotate_right(p_parent, header); + bstree_algorithms::rotate_right(p_parent, header); } else{ //Right child - tree_algorithms::rotate_left(p_parent, header); + bstree_algorithms::rotate_left(p_parent, header); } } } - typedef detail::tree_algorithms tree_algorithms; - - static node_ptr uncast(const const_node_ptr & ptr) - { return pointer_traits::const_cast_from(ptr); } + typedef bstree_algorithms bstree_algorithms; /// @endcond public: - static node_ptr begin_node(const const_node_ptr & header) - { return tree_algorithms::begin_node(header); } - - static node_ptr end_node(const const_node_ptr & header) - { return tree_algorithms::end_node(header); } - //! This type is the information that will be //! filled by insert_unique_check struct insert_commit_data /// @cond - : public tree_algorithms::insert_commit_data + : public bstree_algorithms::insert_commit_data /// @endcond { /// @cond @@ -168,360 +138,117 @@ class treap_algorithms /// @endcond }; - //! Requires: header1 and header2 must be the header nodes - //! of two trees. - //! - //! Effects: Swaps two trees. After the function header1 will contain - //! links to the second tree and header2 will have links to the first tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - static void swap_tree(const node_ptr & header1, const node_ptr & header2) - { return tree_algorithms::swap_tree(header1, header2); } + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! Requires: node1 and node2 can't be header nodes - //! of two trees. - //! - //! Effects: Swaps two nodes. After the function node1 will be inserted - //! in the position node2 before the function. node2 will be inserted in the - //! position node1 had before the function. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - //! - //! Note: This function will break container ordering invariants if - //! node1 and node2 are not equivalent according to the ordering rules. - //! - //!Experimental function - static void swap_nodes(const node_ptr & node1, const node_ptr & node2) - { - if(node1 == node2) - return; + //! @copydoc ::boost::intrusive::bstree_algorithms::get_header(const const_node_ptr&) + static node_ptr get_header(const const_node_ptr & n); - node_ptr header1(tree_algorithms::get_header(node1)), header2(tree_algorithms::get_header(node2)); - swap_nodes(node1, header1, node2, header2); - } + //! @copydoc ::boost::intrusive::bstree_algorithms::begin_node + static node_ptr begin_node(const const_node_ptr & header); - //! Requires: node1 and node2 can't be header nodes - //! of two trees with header header1 and header2. - //! - //! Effects: Swaps two nodes. After the function node1 will be inserted - //! in the position node2 before the function. node2 will be inserted in the - //! position node1 had before the function. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This function will break container ordering invariants if - //! node1 and node2 are not equivalent according to the ordering rules. - //! - //!Experimental function - static void swap_nodes(const node_ptr & node1, const node_ptr & header1, const node_ptr & node2, const node_ptr & header2) - { tree_algorithms::swap_nodes(node1, header1, node2, header2); } + //! @copydoc ::boost::intrusive::bstree_algorithms::end_node + static node_ptr end_node(const const_node_ptr & header); - //! Requires: node_to_be_replaced must be inserted in a tree - //! and new_node must not be inserted in a tree. - //! - //! Effects: Replaces node_to_be_replaced in its position in the - //! tree with new_node. The tree does not need to be rebalanced - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - //! - //! Note: This function will break container ordering invariants if - //! new_node is not equivalent to node_to_be_replaced according to the - //! ordering rules. This function is faster than erasing and inserting - //! the node, since no rebalancing and comparison is needed. - //! - //!Experimental function - static void replace_node(const node_ptr & node_to_be_replaced, const node_ptr & new_node) - { - if(node_to_be_replaced == new_node) - return; - replace_node(node_to_be_replaced, tree_algorithms::get_header(node_to_be_replaced), new_node); - } + //! @copydoc ::boost::intrusive::bstree_algorithms::swap_tree + static void swap_tree(const node_ptr & header1, const node_ptr & header2); - //! Requires: node_to_be_replaced must be inserted in a tree - //! with header "header" and new_node must not be inserted in a tree. - //! - //! Effects: Replaces node_to_be_replaced in its position in the - //! tree with new_node. The tree does not need to be rebalanced - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This function will break container ordering invariants if - //! new_node is not equivalent to node_to_be_replaced according to the - //! ordering rules. This function is faster than erasing and inserting - //! the node, since no rebalancing or comparison is needed. - //! - //!Experimental function - static void replace_node(const node_ptr & node_to_be_replaced, const node_ptr & header, const node_ptr & new_node) - { tree_algorithms::replace_node(node_to_be_replaced, header, new_node); } + //! @copydoc ::boost::intrusive::bstree_algorithms::swap_nodes(const node_ptr&,const node_ptr&) + static void swap_nodes(const node_ptr & node1, const node_ptr & node2); - //! Requires: node is a tree node but not the header. - //! - //! Effects: Unlinks the node and rebalances the tree. - //! - //! Complexity: Average complexity is constant time. - //! - //! Throws: If "pcomp" throws, strong guarantee + //! @copydoc ::boost::intrusive::bstree_algorithms::swap_nodes(const node_ptr&,const node_ptr&,const node_ptr&,const node_ptr&) + static void swap_nodes(const node_ptr & node1, const node_ptr & header1, const node_ptr & node2, const node_ptr & header2); + + //! @copydoc ::boost::intrusive::bstree_algorithms::replace_node(const node_ptr&,const node_ptr&) + static void replace_node(const node_ptr & node_to_be_replaced, const node_ptr & new_node); + + //! @copydoc ::boost::intrusive::bstree_algorithms::replace_node(const node_ptr&,const node_ptr&,const node_ptr&) + static void replace_node(const node_ptr & node_to_be_replaced, const node_ptr & header, const node_ptr & new_node); + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + + //! @copydoc ::boost::intrusive::bstree_algorithms::unlink(const node_ptr&) template static void unlink(const node_ptr & node, NodePtrPriorityCompare pcomp) { node_ptr x = NodeTraits::get_parent(node); if(x){ - while(!is_header(x)) + while(!bstree_algorithms::is_header(x)) x = NodeTraits::get_parent(x); erase(x, node, pcomp); } } - //! Requires: header is the header of a tree. - //! - //! Effects: Unlinks the leftmost node from the tree, and - //! updates the header link to the new leftmost node. - //! - //! Complexity: Average complexity is constant time. - //! - //! Throws: Nothing. - //! - //! Notes: This function breaks the tree and the tree can - //! only be used for more unlink_leftmost_without_rebalance calls. - //! This function is normally used to achieve a step by step - //! controlled destruction of the tree. - static node_ptr unlink_leftmost_without_rebalance(const node_ptr & header) - { return tree_algorithms::unlink_leftmost_without_rebalance(header); } + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::bstree_algorithms::unlink_leftmost_without_rebalance + static node_ptr unlink_leftmost_without_rebalance(const node_ptr & header); - //! Requires: node is a node of the tree or an node initialized - //! by init(...). - //! - //! Effects: Returns true if the node is initialized by init(). - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - static bool unique(const const_node_ptr & node) - { return tree_algorithms::unique(node); } + //! @copydoc ::boost::intrusive::bstree_algorithms::unique(const const_node_ptr&) + static bool unique(const const_node_ptr & node); - //! Requires: node is a node of the tree but it's not the header. - //! - //! Effects: Returns the number of nodes of the subtree. - //! - //! Complexity: Linear time. - //! - //! Throws: Nothing. - static std::size_t count(const const_node_ptr & node) - { return tree_algorithms::count(node); } + //! @copydoc ::boost::intrusive::bstree_algorithms::size(const const_node_ptr&) + static std::size_t size(const const_node_ptr & header); - //! Requires: header is the header node of the tree. - //! - //! Effects: Returns the number of nodes above the header. - //! - //! Complexity: Linear time. - //! - //! Throws: Nothing. - static std::size_t size(const const_node_ptr & header) - { return tree_algorithms::size(header); } + //! @copydoc ::boost::intrusive::bstree_algorithms::next_node(const node_ptr&) + static node_ptr next_node(const node_ptr & node); - //! Requires: p is a node from the tree except the header. - //! - //! Effects: Returns the next node of the tree. - //! - //! Complexity: Average constant time. - //! - //! Throws: Nothing. - static node_ptr next_node(const node_ptr & p) - { return tree_algorithms::next_node(p); } + //! @copydoc ::boost::intrusive::bstree_algorithms::prev_node(const node_ptr&) + static node_ptr prev_node(const node_ptr & node); - //! Requires: p is a node from the tree except the leftmost node. - //! - //! Effects: Returns the previous node of the tree. - //! - //! Complexity: Average constant time. - //! - //! Throws: Nothing. - static node_ptr prev_node(const node_ptr & p) - { return tree_algorithms::prev_node(p); } + //! @copydoc ::boost::intrusive::bstree_algorithms::init(const node_ptr&) + static void init(const node_ptr & node); - //! Requires: node must not be part of any tree. - //! - //! Effects: After the function unique(node) == true. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Nodes: If node is inserted in a tree, this function corrupts the tree. - static void init(const node_ptr & node) - { tree_algorithms::init(node); } + //! @copydoc ::boost::intrusive::bstree_algorithms::init_header(const node_ptr&) + static void init_header(const node_ptr & header); + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED - //! Requires: node must not be part of any tree. - //! - //! Effects: Initializes the header to represent an empty tree. - //! unique(header) == true. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Nodes: If node is inserted in a tree, this function corrupts the tree. - static void init_header(const node_ptr & header) - { - tree_algorithms::init_header(header); - } - - //! Requires: header must be the header of a tree, z a node - //! of that tree and z != header. - //! - //! Effects: Erases node "z" from the tree with header "header". - //! - //! Complexity: Amortized constant time. - //! - //! Throws: If "pcomp" throws, strong guarantee. + //! @copydoc ::boost::intrusive::bstree_algorithms::erase(const node_ptr&,const node_ptr&) template static node_ptr erase(const node_ptr & header, const node_ptr & z, NodePtrPriorityCompare pcomp) { rebalance_for_erasure(header, z, pcomp); - tree_algorithms::erase(header, z); + bstree_algorithms::erase(header, z); return z; } - //! Requires: "cloner" must be a function - //! object taking a node_ptr and returning a new cloned node of it. "disposer" must - //! take a node_ptr and shouldn't throw. - //! - //! Effects: First empties target tree calling - //! void disposer::operator()(const node_ptr &) for every node of the tree - //! except the header. - //! - //! Then, duplicates the entire tree pointed by "source_header" cloning each - //! source node with node_ptr Cloner::operator()(const node_ptr &) to obtain - //! the nodes of the target tree. If "cloner" throws, the cloned target nodes - //! are disposed using void disposer(const node_ptr &). - //! - //! Complexity: Linear to the number of element of the source tree plus the. - //! number of elements of tree target tree when calling this function. - //! - //! Throws: If cloner functor throws. If this happens target nodes are disposed. + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::bstree_algorithms::clone(const const_node_ptr&,const node_ptr&,Cloner,Disposer) template static void clone - (const const_node_ptr & source_header, const node_ptr & target_header, Cloner cloner, Disposer disposer) - { - tree_algorithms::clone(source_header, target_header, cloner, disposer); - } + (const const_node_ptr & source_header, const node_ptr & target_header, Cloner cloner, Disposer disposer); - //! Requires: "disposer" must be an object function - //! taking a node_ptr parameter and shouldn't throw. - //! - //! Effects: Empties the target tree calling - //! void disposer::operator()(const node_ptr &) for every node of the tree - //! except the header. - //! - //! Complexity: Linear to the number of element of the source tree plus the. - //! number of elements of tree target tree when calling this function. - //! - //! Throws: If cloner functor throws. If this happens target nodes are disposed. + //! @copydoc ::boost::intrusive::bstree_algorithms::clear_and_dispose(const node_ptr&,Disposer) template - static void clear_and_dispose(const node_ptr & header, Disposer disposer) - { tree_algorithms::clear_and_dispose(header, disposer); } + static void clear_and_dispose(const node_ptr & header, Disposer disposer); - //! 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 an node_ptr to the first element that is - //! not less than "key" according to "comp" or "header" if that element does - //! not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. + //! @copydoc ::boost::intrusive::bstree_algorithms::lower_bound(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) template static node_ptr lower_bound - (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) - { return tree_algorithms::lower_bound(header, key, comp); } + (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp); - //! 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 an node_ptr to the first element that is greater - //! than "key" according to "comp" or "header" if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. + //! @copydoc ::boost::intrusive::bstree_algorithms::upper_bound(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) template static node_ptr upper_bound - (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) - { return tree_algorithms::upper_bound(header, key, comp); } + (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp); - //! 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 an node_ptr to the element that is equivalent to - //! "key" according to "comp" or "header" if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. + //! @copydoc ::boost::intrusive::bstree_algorithms::find(const const_node_ptr&, const KeyType&,KeyNodePtrCompare) template static node_ptr find - (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) - { return tree_algorithms::find(header, key, comp); } + (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp); - //! 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 an a pair of node_ptr delimiting a range containing - //! all elements that are equivalent to "key" according to "comp" or an - //! empty range that indicates the position where those elements would be - //! if they there are no equivalent elements. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. + //! @copydoc ::boost::intrusive::bstree_algorithms::equal_range(const const_node_ptr&,const KeyType&,KeyNodePtrCompare) template static std::pair equal_range - (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp) - { return tree_algorithms::equal_range(header, key, comp); } + (const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp); - //! 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. - //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If - //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise - //! - //! second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_key and upper_key. + //! @copydoc ::boost::intrusive::bstree_algorithms::bounded_range(const const_node_ptr&,const KeyType&,const KeyType&,KeyNodePtrCompare,bool,bool) template static std::pair bounded_range (const const_node_ptr & header, const KeyType &lower_key, const KeyType &upper_key, KeyNodePtrCompare comp - , bool left_closed, bool right_closed) - { return tree_algorithms::bounded_range(header, lower_key, upper_key, comp, left_closed, right_closed); } + , bool left_closed, bool right_closed); + + //! @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. //! NodePtrCompare is a function object that induces a strict weak @@ -543,7 +270,7 @@ class treap_algorithms (const node_ptr & h, const node_ptr & new_node, NodePtrCompare comp, NodePtrPriorityCompare pcomp) { insert_commit_data commit_data; - tree_algorithms::insert_equal_upper_bound_check(h, new_node, comp, commit_data); + bstree_algorithms::insert_equal_upper_bound_check(h, new_node, comp, commit_data); rebalance_check_and_commit(h, new_node, pcomp, commit_data); return new_node; } @@ -568,7 +295,7 @@ class treap_algorithms (const node_ptr & h, const node_ptr & new_node, NodePtrCompare comp, NodePtrPriorityCompare pcomp) { insert_commit_data commit_data; - tree_algorithms::insert_equal_lower_bound_check(h, new_node, comp, commit_data); + bstree_algorithms::insert_equal_lower_bound_check(h, new_node, comp, commit_data); rebalance_check_and_commit(h, new_node, pcomp, commit_data); return new_node; } @@ -596,7 +323,7 @@ class treap_algorithms (const node_ptr & h, const node_ptr & hint, const node_ptr & new_node, NodePtrCompare comp, NodePtrPriorityCompare pcomp) { insert_commit_data commit_data; - tree_algorithms::insert_equal_check(h, hint, new_node, comp, commit_data); + bstree_algorithms::insert_equal_check(h, hint, new_node, comp, commit_data); rebalance_check_and_commit(h, new_node, pcomp, commit_data); return new_node; } @@ -624,7 +351,7 @@ class treap_algorithms (const node_ptr & header, const node_ptr & pos, const node_ptr & new_node, NodePtrPriorityCompare pcomp) { insert_commit_data commit_data; - tree_algorithms::insert_before_check(header, pos, commit_data); + bstree_algorithms::insert_before_check(header, pos, commit_data); rebalance_check_and_commit(header, new_node, pcomp, commit_data); return new_node; } @@ -650,7 +377,7 @@ class treap_algorithms static void push_back(const node_ptr & header, const node_ptr & new_node, NodePtrPriorityCompare pcomp) { insert_commit_data commit_data; - tree_algorithms::push_back_check(header, commit_data); + bstree_algorithms::push_back_check(header, commit_data); rebalance_check_and_commit(header, new_node, pcomp, commit_data); } @@ -675,7 +402,7 @@ class treap_algorithms static void push_front(const node_ptr & header, const node_ptr & new_node, NodePtrPriorityCompare pcomp) { insert_commit_data commit_data; - tree_algorithms::push_front_check(header, commit_data); + bstree_algorithms::push_front_check(header, commit_data); rebalance_check_and_commit(header, new_node, pcomp, commit_data); } @@ -720,7 +447,7 @@ class treap_algorithms ,insert_commit_data &commit_data) { std::pair ret = - tree_algorithms::insert_unique_check(header, key, comp, commit_data); + bstree_algorithms::insert_unique_check(header, key, comp, commit_data); if(ret.second) rebalance_after_insertion_check(header, commit_data.node, key, pcomp, commit_data.rotations); return ret; @@ -771,7 +498,7 @@ class treap_algorithms ,KeyNodePtrCompare comp, KeyNodePtrPrioCompare pcomp, insert_commit_data &commit_data) { std::pair ret = - tree_algorithms::insert_unique_check(header, hint, key, comp, commit_data); + bstree_algorithms::insert_unique_check(header, hint, key, comp, commit_data); if(ret.second) rebalance_after_insertion_check(header, commit_data.node, key, pcomp, commit_data.rotations); return ret; @@ -797,35 +524,19 @@ class treap_algorithms static void insert_unique_commit (const node_ptr & header, const node_ptr & new_node, const insert_commit_data &commit_data) { - tree_algorithms::insert_unique_commit(header, new_node, commit_data); + bstree_algorithms::insert_unique_commit(header, new_node, commit_data); rebalance_after_insertion_commit(header, new_node, commit_data.rotations); } - //! Requires: "n" must be a node inserted in a tree. - //! - //! Effects: Returns a pointer to the header node of the tree. - //! - //! Complexity: Logarithmic. - //! - //! Throws: Nothing. - static node_ptr get_header(const node_ptr & n) - { return tree_algorithms::get_header(n); } + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + + //! @copydoc ::boost::intrusive::bstree_algorithms::is_header + static bool is_header(const const_node_ptr & p); + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED /// @cond private: - //! Requires: p is a node of a tree. - //! - //! Effects: Returns true if p is the header of the tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - static bool is_header(const const_node_ptr & p) - { - return tree_algorithms::is_header(p); - } - template static void rebalance_for_erasure(const node_ptr & header, const node_ptr & z, NodePtrPriorityCompare pcomp) { @@ -836,10 +547,10 @@ class treap_algorithms node_ptr z_right = NodeTraits::get_right(z); while(z_left || z_right){ if(!z_right || (z_left && pcomp(z_left, z_right))){ - tree_algorithms::rotate_right(z, header); + bstree_algorithms::rotate_right(z, header); } else{ - tree_algorithms::rotate_left(z, header); + bstree_algorithms::rotate_left(z, header); } ++n; z_left = NodeTraits::get_left(z); @@ -854,7 +565,7 @@ class treap_algorithms { rebalance_after_insertion_check(h, commit_data.node, new_node, pcomp, commit_data.rotations); //No-throw - tree_algorithms::insert_unique_commit(h, new_node, commit_data); + bstree_algorithms::insert_unique_commit(h, new_node, commit_data); rebalance_after_insertion_commit(h, new_node, commit_data.rotations); } @@ -883,10 +594,10 @@ class treap_algorithms ; p_parent = NodeTraits::get_parent(p)){ //Check if left child if(p == NodeTraits::get_left(p_parent)){ - tree_algorithms::rotate_right(p_parent, header); + bstree_algorithms::rotate_right(p_parent, header); } else{ //Right child - tree_algorithms::rotate_left(p_parent, header); + bstree_algorithms::rotate_left(p_parent, header); } } } @@ -911,6 +622,16 @@ class treap_algorithms /// @endcond }; +/// @cond + +template +struct get_algo +{ + typedef treap_algorithms type; +}; + +/// @endcond + } //namespace intrusive } //namespace boost diff --git a/include/boost/intrusive/treap_set.hpp b/include/boost/intrusive/treap_set.hpp index cd1300a..48e332f 100644 --- a/include/boost/intrusive/treap_set.hpp +++ b/include/boost/intrusive/treap_set.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 @@ -36,14 +36,15 @@ namespace intrusive { #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class treap_set_impl +#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + : public treap_impl +#endif { /// @cond - typedef treap_impl tree_type; - //! This class is - //! movable + typedef treap_impl tree_type; BOOST_MOVABLE_BUT_NOT_COPYABLE(treap_set_impl) typedef tree_type implementation_defined; @@ -72,12 +73,7 @@ class treap_set_impl typedef typename implementation_defined::const_node_ptr const_node_ptr; typedef typename implementation_defined::node_algorithms node_algorithms; - static const bool constant_time_size = Config::constant_time_size; - - /// @cond - private: - tree_type tree_; - /// @endcond + static const bool constant_time_size = implementation_defined::constant_time_size; public: //! Effects: Constructs an empty treap_set. @@ -90,7 +86,7 @@ class treap_set_impl explicit treap_set_impl( const value_compare &cmp = value_compare() , const priority_compare &pcmp = priority_compare() , const value_traits &v_traits = value_traits()) - : tree_(cmp, pcmp, v_traits) + : tree_type(cmp, pcmp, v_traits) {} //! Requires: Dereferencing iterator must yield an lvalue of type value_type. @@ -110,1255 +106,331 @@ class treap_set_impl , const value_compare &cmp = value_compare() , const priority_compare &pcmp = priority_compare() , const value_traits &v_traits = value_traits()) - : tree_(true, b, e, cmp, pcmp, v_traits) + : tree_type(true, b, e, cmp, pcmp, v_traits) {} //! Effects: to-do //! treap_set_impl(BOOST_RV_REF(treap_set_impl) x) - : tree_(::boost::move(x.tree_)) + : tree_type(::boost::move(static_cast(x))) {} //! Effects: to-do //! treap_set_impl& operator=(BOOST_RV_REF(treap_set_impl) x) - { tree_ = ::boost::move(x.tree_); return *this; } + { return static_cast(tree_type::operator=(::boost::move(static_cast(x)))); } - //! Effects: Detaches all elements from this. The objects in the treap_set - //! are not deleted (i.e. no destructors are called). - //! - //! Complexity: Linear to the number of elements on the container. - //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. - //! - //! Throws: Nothing. - ~treap_set_impl() - {} + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::treap::~treap() + ~treap_set_impl(); - //! Effects: Returns an iterator pointing to the beginning of the treap_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator begin() - { return tree_.begin(); } + //! @copydoc ::boost::intrusive::treap::begin() + iterator begin(); - //! Effects: Returns a const_iterator pointing to the beginning of the treap_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator begin() const - { return tree_.begin(); } + //! @copydoc ::boost::intrusive::treap::begin()const + const_iterator begin() const; - //! Effects: Returns a const_iterator pointing to the beginning of the treap_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator cbegin() const - { return tree_.cbegin(); } + //! @copydoc ::boost::intrusive::treap::cbegin()const + const_iterator cbegin() const; - //! Effects: Returns an iterator pointing to the end of the treap_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator end() - { return tree_.end(); } + //! @copydoc ::boost::intrusive::treap::end() + iterator end(); - //! Effects: Returns a const_iterator pointing to the end of the treap_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator end() const - { return tree_.end(); } + //! @copydoc ::boost::intrusive::treap::end()const + const_iterator end() const; - //! Effects: Returns an iterator pointing to the highest priority object of the tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator top() - { return tree_.top(); } + //! @copydoc ::boost::intrusive::treap::cend()const + const_iterator cend() const; - //! Effects: Returns a const_iterator pointing to the highest priority object of the tree.. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator top() const - { return this->ctop(); } + //! @copydoc ::boost::intrusive::treap::rbegin() + reverse_iterator rbegin(); - //! Effects: Returns a const_iterator pointing to the highest priority object of the tree.. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator ctop() const - { return tree_.ctop(); } + //! @copydoc ::boost::intrusive::treap::rbegin()const + const_reverse_iterator rbegin() const; - //! Effects: Returns a const_iterator pointing to the end of the treap_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator cend() const - { return tree_.cend(); } + //! @copydoc ::boost::intrusive::treap::crbegin()const + const_reverse_iterator crbegin() const; - //! Effects: Returns a reverse_iterator pointing to the beginning of the - //! reversed treap_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - reverse_iterator rbegin() - { return tree_.rbegin(); } + //! @copydoc ::boost::intrusive::treap::rend() + reverse_iterator rend(); - //! Effects: Returns a const_reverse_iterator pointing to the beginning - //! of the reversed treap_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator rbegin() const - { return tree_.rbegin(); } + //! @copydoc ::boost::intrusive::treap::rend()const + const_reverse_iterator rend() const; - //! Effects: Returns a const_reverse_iterator pointing to the beginning - //! of the reversed treap_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator crbegin() const - { return tree_.crbegin(); } + //! @copydoc ::boost::intrusive::treap::crend()const + const_reverse_iterator crend() const; - //! Effects: Returns a reverse_iterator pointing to the end - //! of the reversed treap_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - reverse_iterator rend() - { return tree_.rend(); } + //! @copydoc ::boost::intrusive::treap::container_from_end_iterator(iterator) + static treap_set_impl &container_from_end_iterator(iterator end_iterator); - //! Effects: Returns a const_reverse_iterator pointing to the end - //! of the reversed treap_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator rend() const - { return tree_.rend(); } + //! @copydoc ::boost::intrusive::treap::container_from_end_iterator(const_iterator) + static const treap_set_impl &container_from_end_iterator(const_iterator end_iterator); - //! Effects: Returns a const_reverse_iterator pointing to the end - //! of the reversed treap_set. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator crend() const - { return tree_.crend(); } + //! @copydoc ::boost::intrusive::treap::container_from_iterator(iterator) + static treap_set_impl &container_from_iterator(iterator it); - //! Effects: Returns a reverse_iterator pointing to the highest priority object of the - //! reversed tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - reverse_iterator rtop() - { return tree_.rtop(); } + //! @copydoc ::boost::intrusive::treap::container_from_iterator(const_iterator) + static const treap_set_impl &container_from_iterator(const_iterator it); - //! Effects: Returns a const_reverse_iterator pointing to the highest priority objec - //! of the reversed tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator rtop() const - { return tree_.crtop(); } + //! @copydoc ::boost::intrusive::treap::key_comp()const + key_compare key_comp() const; - //! Effects: Returns a const_reverse_iterator pointing to the highest priority object - //! of the reversed tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator crtop() const - { return tree_.crtop(); } + //! @copydoc ::boost::intrusive::treap::value_comp()const + value_compare value_comp() const; - //! Precondition: end_iterator must be a valid end iterator - //! of treap_set. - //! - //! Effects: Returns a const reference to the treap_set associated to the end iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - static treap_set_impl &container_from_end_iterator(iterator end_iterator) - { - return *detail::parent_from_member - ( &tree_type::container_from_end_iterator(end_iterator) - , &treap_set_impl::tree_); - } + //! @copydoc ::boost::intrusive::treap::empty()const + bool empty() const; - //! Precondition: end_iterator must be a valid end const_iterator - //! of treap_set. - //! - //! Effects: Returns a const reference to the treap_set associated to the end iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - static const treap_set_impl &container_from_end_iterator(const_iterator end_iterator) - { - return *detail::parent_from_member - ( &tree_type::container_from_end_iterator(end_iterator) - , &treap_set_impl::tree_); - } + //! @copydoc ::boost::intrusive::treap::size()const + size_type size() const; - //! Precondition: it must be a valid iterator of set. - //! - //! Effects: Returns a reference to the set associated to the iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Logarithmic. - static treap_set_impl &container_from_iterator(iterator it) - { - return *detail::parent_from_member - ( &tree_type::container_from_iterator(it) - , &treap_set_impl::tree_); - } + //! @copydoc ::boost::intrusive::treap::swap + void swap(treap_set_impl& other); - //! Precondition: it must be a valid const_iterator of set. - //! - //! Effects: Returns a const reference to the set associated to the iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Logarithmic. - static const treap_set_impl &container_from_iterator(const_iterator it) - { - return *detail::parent_from_member - ( &tree_type::container_from_iterator(it) - , &treap_set_impl::tree_); - } - - //! Effects: Returns the key_compare object used by the treap_set. - //! - //! Complexity: Constant. - //! - //! Throws: If key_compare copy-constructor throws. - key_compare key_comp() const - { return tree_.value_comp(); } - - //! Effects: Returns the value_compare object used by the treap_set. - //! - //! Complexity: Constant. - //! - //! Throws: If value_compare copy-constructor throws. - value_compare value_comp() const - { return tree_.value_comp(); } - - //! Effects: Returns the priority_compare object used by the treap_set. - //! - //! Complexity: Constant. - //! - //! Throws: If priority_compare copy-constructor throws. - priority_compare priority_comp() const - { return tree_.priority_comp(); } - - //! Effects: Returns true if the container is empty. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - bool empty() const - { return tree_.empty(); } - - //! Effects: Returns the number of elements stored in the treap_set. - //! - //! Complexity: Linear to elements contained in *this if, - //! constant-time size option is enabled. Constant-time otherwise. - //! - //! Throws: Nothing. - size_type size() const - { return tree_.size(); } - - //! Effects: Swaps the contents of two sets. - //! - //! Complexity: Constant. - //! - //! Throws: If the swap() call for the comparison functor - //! found using ADL throws. Strong guarantee. - void swap(treap_set_impl& other) - { tree_.swap(other.tree_); } - - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! Cloner should yield to nodes equivalent to the original nodes. - //! - //! Effects: Erases all the elements from *this - //! calling Disposer::operator()(pointer), clones all the - //! elements from src calling Cloner::operator()(const_reference ) - //! and inserts them on *this. Copies the predicate from the source container. - //! - //! If cloner throws, all cloned elements are unlinked and disposed - //! calling Disposer::operator()(pointer). - //! - //! Complexity: Linear to erased plus inserted elements. - //! - //! Throws: If cloner throws or predicate copy assignment throws. Basic guarantee. + //! @copydoc ::boost::intrusive::treap::clone_from template - void clone_from(const treap_set_impl &src, Cloner cloner, Disposer disposer) - { tree_.clone_from(src.tree_, cloner, disposer); } + void clone_from(const treap_set_impl &src, Cloner cloner, Disposer disposer); - //! Requires: value must be an lvalue - //! - //! Effects: Tries to inserts value into the treap_set. - //! - //! Returns: If the value - //! is not already present inserts it and returns a pair containing the - //! iterator to the new value and true. If there is an equivalent value - //! returns a pair containing an iterator to the already present value - //! and false. - //! - //! Complexity: Average complexity for insert element is at - //! most logarithmic. - //! - //! Throws: If the internal value_compare or priority_compare ordering function throw. - //! Strong guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + //! @copydoc ::boost::intrusive::treap::top() + iterator top(); + + //! @copydoc ::boost::intrusive::treap::top()const + const_iterator top() const; + + //! @copydoc ::boost::intrusive::treap::ctop()const + const_iterator ctop() const; + + //! @copydoc ::boost::intrusive::treap::rtop() + reverse_iterator rtop(); + + //! @copydoc ::boost::intrusive::treap::rtop()const + const_reverse_iterator rtop() const; + + //! @copydoc ::boost::intrusive::treap::crtop()const + const_reverse_iterator crtop() const; + + //! @copydoc ::boost::intrusive::treap::crtop() const + priority_compare priority_comp() const; + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + + //! @copydoc ::boost::intrusive::treap::insert_unique(reference) std::pair insert(reference value) - { return tree_.insert_unique(value); } + { return tree_type::insert_unique(value); } - //! Requires: value must be an lvalue - //! - //! Effects: Tries to to insert x into the treap_set, using "hint" - //! as a hint to where it will be inserted. - //! - //! Returns: An iterator that points to the position where the - //! new element was inserted into the treap_set. - //! - //! Complexity: Logarithmic in general, but it's amortized - //! constant time if t is inserted immediately before hint. - //! - //! Throws: If the internal value_compare or priority_compare ordering - //! functions throw. Strong guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + //! @copydoc ::boost::intrusive::treap::insert_unique(const_iterator,reference) iterator insert(const_iterator hint, reference value) - { return tree_.insert_unique(hint, value); } + { return tree_type::insert_unique(hint, value); } - //! Requires: key_value_comp must be a comparison function that induces - //! the same strict weak ordering as value_compare. - //! key_value_pcomp must be a comparison function that induces - //! the same strict weak ordering as priority_compare. The difference is that - //! key_value_pcomp and key_value_comp compare an arbitrary key with the contained values. - //! - //! Effects: Checks if a value can be inserted in the treap_set, using - //! a user provided key instead of the value itself. - //! - //! Returns: If there is an equivalent value - //! returns a pair containing an iterator to the already present value - //! and false. If the value can be inserted returns true in the returned - //! pair boolean and fills "commit_data" that is meant to be used with - //! the "insert_commit" function. - //! - //! Complexity: Average complexity is at most logarithmic. - //! - //! Throws: If key_value_comp or key_value_pcomp ordering function throw. - //! Strong guarantee. - //! - //! Notes: This function is used to improve performance when constructing - //! a value_type is expensive: if there is an equivalent value - //! the constructed object must be discarded. Many times, the part of the - //! node that is used to impose the order is much cheaper to construct - //! than the value_type and this function offers the possibility to use that - //! part to check if the insertion will be successful. - //! - //! If the check is successful, the user can construct the value_type and use - //! "insert_commit" to insert the object in constant-time. This gives a total - //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)). - //! - //! "commit_data" remains valid for a subsequent "insert_commit" only if no more - //! objects are inserted or erased from the treap_set. - template + //! @copydoc ::boost::intrusive::treap::insert_unique_check(const KeyType&,KeyValueCompare,KeyValuePrioCompare,insert_commit_data&) + template std::pair insert_check - ( const KeyType &key, KeyValueCompare key_value_comp, KeyValuePriorityCompare key_value_pcomp + ( const KeyType &key, KeyValueCompare key_value_comp, KeyValuePrioCompare key_value_pcomp , insert_commit_data &commit_data) - { return tree_.insert_unique_check(key, key_value_comp, key_value_pcomp, commit_data); } + { return tree_type::insert_unique_check(key, key_value_comp, key_value_pcomp, commit_data); } - //! Requires: key_value_comp must be a comparison function that induces - //! the same strict weak ordering as value_compare. - //! key_value_pcomp must be a comparison function that induces - //! the same strict weak ordering as priority_compare. The difference is that - //! key_value_pcomp and key_value_comp compare an arbitrary key with the contained values. - //! - //! Effects: Checks if a value can be inserted in the treap_set, using - //! a user provided key instead of the value itself, using "hint" - //! as a hint to where it will be inserted. - //! - //! Returns: If there is an equivalent value - //! returns a pair containing an iterator to the already present value - //! and false. If the value can be inserted returns true in the returned - //! pair boolean and fills "commit_data" that is meant to be used with - //! the "insert_commit" function. - //! - //! Complexity: Logarithmic in general, but it's amortized - //! constant time if t is inserted immediately before hint. - //! - //! Throws: If key_value_comp or key_value_pcomp ordering function throw. - //! Strong guarantee. - //! - //! Notes: This function is used to improve performance when constructing - //! a value_type is expensive: if there is an equivalent value - //! the constructed object must be discarded. Many times, the part of the - //! constructing that is used to impose the order is much cheaper to construct - //! than the value_type and this function offers the possibility to use that key - //! to check if the insertion will be successful. - //! - //! If the check is successful, the user can construct the value_type and use - //! "insert_commit" to insert the object in constant-time. This can give a total - //! constant-time complexity to the insertion: check(O(1)) + commit(O(1)). - //! - //! "commit_data" remains valid for a subsequent "insert_commit" only if no more - //! objects are inserted or erased from the treap_set. - template + //! @copydoc ::boost::intrusive::treap::insert_unique_check(const_iterator,const KeyType&,KeyValueCompare,KeyValuePrioCompare,insert_commit_data&) + template std::pair insert_check ( const_iterator hint, const KeyType &key - , KeyValueCompare key_value_comp, KeyValuePriorityCompare key_value_pcomp + , KeyValueCompare key_value_comp, KeyValuePrioCompare key_value_pcomp , insert_commit_data &commit_data) - { return tree_.insert_unique_check(hint, key, key_value_comp, key_value_pcomp, commit_data); } + { return tree_type::insert_unique_check(hint, key, key_value_comp, key_value_pcomp, commit_data); } - //! Requires: value must be an lvalue of type value_type. commit_data - //! must have been obtained from a previous call to "insert_check". - //! No objects should have been inserted or erased from the treap_set between - //! the "insert_check" that filled "commit_data" and the call to "insert_commit". - //! - //! Effects: Inserts the value in the treap_set using the information obtained - //! from the "commit_data" that a previous "insert_check" filled. - //! - //! Returns: An iterator to the newly inserted object. - //! - //! Complexity: Constant time. - //! - //! Throws: Nothing. - //! - //! Notes: This function has only sense if a "insert_check" has been - //! previously executed to fill "commit_data". No value should be inserted or - //! erased between the "insert_check" and "insert_commit" calls. - iterator insert_commit(reference value, const insert_commit_data &commit_data) - { return tree_.insert_unique_commit(value, commit_data); } - - //! Requires: Dereferencing iterator must yield an lvalue - //! of type value_type. - //! - //! Effects: Inserts a range into the treap_set. - //! - //! Complexity: Insert range is in general O(N * log(N)), where N is the - //! size of the range. However, it is linear in N if the range is already sorted - //! by value_comp(). - //! - //! Throws: If the internal value_compare or priority_compare ordering function - //! throw. Basic guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + //! @copydoc ::boost::intrusive::treap::insert_unique(Iterator,Iterator) template void insert(Iterator b, Iterator e) - { tree_.insert_unique(b, e); } + { tree_type::insert_unique(b, e); } - //! Requires: value must be an lvalue, "pos" must be - //! a valid iterator (or end) and must be the succesor of value - //! once inserted according to the predicate. "value" must not be equal to any - //! inserted key according to the predicate. - //! - //! Effects: Inserts x into the treap before "pos". - //! - //! Complexity: Constant time. - //! - //! Throws: If the internal priority_compare function throws. Strong guarantee. - //! - //! Note: This function does not check preconditions so if "pos" is not - //! the successor of "value" treap ordering invariant will be broken. - //! This is a low-level function to be used only for performance reasons - //! by advanced users. - iterator insert_before(const_iterator pos, reference value) - { return tree_.insert_before(pos, value); } + //! @copydoc ::boost::intrusive::treap::insert_unique_commit + iterator insert_commit(reference value, const insert_commit_data &commit_data) + { return tree_type::insert_unique_commit(value, commit_data); } - //! Requires: value must be an lvalue, and it must be greater than - //! any inserted key according to the predicate. - //! - //! Effects: Inserts x into the treap in the last position. - //! - //! Complexity: Constant time. - //! - //! Throws: If the internal priority_compare function throws. Strong guarantee. - //! - //! Note: This function does not check preconditions so if value is - //! less than the greatest inserted key treap ordering invariant will be broken. - //! This function is slightly more efficient than using "insert_before". - //! This is a low-level function to be used only for performance reasons - //! by advanced users. - void push_back(reference value) - { tree_.push_back(value); } + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::treap::insert_before + iterator insert_before(const_iterator pos, reference value); - //! Requires: value must be an lvalue, and it must be less - //! than any inserted key according to the predicate. - //! - //! Effects: Inserts x into the treap in the first position. - //! - //! Complexity: Constant time. - //! - //! Throws: If the internal priority_compare function throws. Strong guarantee. - //! - //! Note: This function does not check preconditions so if value is - //! greater than the minimum inserted key treap ordering invariant will be broken. - //! This function is slightly more efficient than using "insert_before". - //! This is a low-level function to be used only for performance reasons - //! by advanced users. - void push_front(reference value) - { tree_.push_front(value); } + //! @copydoc ::boost::intrusive::treap::push_back + void push_back(reference value); - //! Effects: Erases the element pointed to by pos. - //! - //! Complexity: Average complexity is constant time. - //! - //! Returns: An iterator to the element after the erased element. - //! - //! Throws: If the internal priority_compare function throws. Strong guarantee. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - iterator erase(const_iterator i) - { return tree_.erase(i); } + //! @copydoc ::boost::intrusive::treap::push_front + void push_front(reference value); - //! Effects: Erases the range pointed to by b end e. - //! - //! Complexity: Average complexity for erase range is at most - //! O(log(size() + N)), where N is the number of elements in the range. - //! - //! Returns: An iterator to the element after the erased elements. - //! - //! Throws: If the internal priority_compare function throws. Basic guarantee. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - iterator erase(const_iterator b, const_iterator e) - { return tree_.erase(b, e); } + //! @copydoc ::boost::intrusive::treap::erase(const_iterator) + iterator erase(const_iterator i); - //! Effects: Erases all the elements with the given value. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: O(log(size()) + this->count(value)). - //! - //! Throws: If internal value_compare or priority_compare - //! ordering functions throw. Basic guarantee. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - size_type erase(const_reference value) - { return tree_.erase(value); } + //! @copydoc ::boost::intrusive::treap::erase(const_iterator,const_iterator) + iterator erase(const_iterator b, const_iterator e); - //! Effects: Erases all the elements that compare equal with - //! the given key and the given comparison functor. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: O(log(size() + this->count(key, comp)). - //! - //! Throws: If comp or internal priority_compare - //! ordering functions throw. Basic guarantee. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. + //! @copydoc ::boost::intrusive::treap::erase(const_reference) + size_type erase(const_reference value); + + //! @copydoc ::boost::intrusive::treap::erase(const KeyType&,KeyValueCompare) template - size_type erase(const KeyType& key, KeyValueCompare comp - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) - { return tree_.erase(key, comp); } + size_type erase(const KeyType& key, KeyValueCompare comp); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases the element pointed to by pos. - //! Disposer::operator()(pointer) is called for the removed element. - //! - //! Complexity: Average complexity for erase element is constant time. - //! - //! Returns: An iterator to the element after the erased element. - //! - //! Throws: If the internal priority_compare function throws. Strong guarantee. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::treap::erase_and_dispose(const_iterator,Disposer) template - iterator erase_and_dispose(const_iterator i, Disposer disposer) - { return tree_.erase_and_dispose(i, disposer); } + iterator erase_and_dispose(const_iterator i, Disposer disposer); - #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + //! @copydoc ::boost::intrusive::treap::erase_and_dispose(const_iterator,const_iterator,Disposer) template - iterator erase_and_dispose(iterator i, Disposer disposer) - { return this->erase_and_dispose(const_iterator(i), disposer); } - #endif + iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases the range pointed to by b end e. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Complexity: Average complexity for erase range is at most - //! O(log(size() + N)), where N is the number of elements in the range. - //! - //! Returns: An iterator to the element after the erased elements. - //! - //! Throws: If the internal priority_compare function throws. Basic guarantee. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::treap::erase_and_dispose(const_reference, Disposer) template - iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer) - { return tree_.erase_and_dispose(b, e, disposer); } + size_type erase_and_dispose(const_reference value, Disposer disposer); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements with the given value. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Throws: If the internal value_compare ordering function throws. - //! - //! Complexity: O(log(size() + this->count(value)). Basic guarantee. - //! - //! Throws: If the internal priority_compare function throws. Strong guarantee. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - template - size_type erase_and_dispose(const_reference value, Disposer disposer) - { return tree_.erase_and_dispose(value, disposer); } - - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements with the given key. - //! according to the comparison functor "comp". - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: O(log(size() + this->count(key, comp)). - //! - //! Throws: If comp or internal priority_compare ordering functions throw. - //! Basic guarantee. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::treap::erase_and_dispose(const KeyType&,KeyValueCompare,Disposer) template - size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) - { return tree_.erase_and_dispose(key, comp, disposer); } + size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer); - //! Effects: Erases all the elements of the container. - //! - //! Complexity: Linear to the number of elements on the container. - //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - void clear() - { return tree_.clear(); } + //! @copydoc ::boost::intrusive::treap::clear + void clear(); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements of the container. - //! - //! Complexity: Linear to the number of elements on the container. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. + //! @copydoc ::boost::intrusive::treap::clear_and_dispose template - void clear_and_dispose(Disposer disposer) - { return tree_.clear_and_dispose(disposer); } + void clear_and_dispose(Disposer disposer); - //! Effects: Returns the number of contained elements with the given key - //! - //! Complexity: Logarithmic to the number of elements contained plus lineal - //! to number of objects with the given key. - //! - //! Throws: If the internal value_compare ordering function throws. - size_type count(const_reference value) const - { return tree_.find(value) != end(); } + //! @copydoc ::boost::intrusive::treap::count(const_reference)const + size_type count(const_reference value) const; - //! Effects: Returns the number of contained elements with the same key - //! compared with the given comparison functor. - //! - //! Complexity: Logarithmic to the number of elements contained plus lineal - //! to number of objects with the given key. - //! - //! Throws: If comp ordering function throws. + //! @copydoc ::boost::intrusive::treap::count(const KeyType&,KeyValueCompare)const template - size_type count(const KeyType& key, KeyValueCompare comp) const - { return tree_.find(key, comp) != end(); } - - //! Effects: Returns an iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - iterator lower_bound(const_reference value) - { return tree_.lower_bound(value); } - - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Returns an iterator to the first element whose - //! key according to the comparison functor is not less than k or - //! end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + size_type count(const KeyType& key, KeyValueCompare comp) const; + + //! @copydoc ::boost::intrusive::treap::lower_bound(const_reference) + iterator lower_bound(const_reference value); + + //! @copydoc ::boost::intrusive::treap::lower_bound(const KeyType&,KeyValueCompare) template - iterator lower_bound(const KeyType& key, KeyValueCompare comp) - { return tree_.lower_bound(key, comp); } + iterator lower_bound(const KeyType& key, KeyValueCompare comp); - //! Effects: Returns a const iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - const_iterator lower_bound(const_reference value) const - { return tree_.lower_bound(value); } + //! @copydoc ::boost::intrusive::treap::lower_bound(const_reference)const + const_iterator lower_bound(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Returns a const_iterator to the first element whose - //! key according to the comparison functor is not less than k or - //! end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::treap::lower_bound(const KeyType&,KeyValueCompare)const template - const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const - { return tree_.lower_bound(key, comp); } + const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Returns an iterator to the first element whose - //! key is greater than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - iterator upper_bound(const_reference value) - { return tree_.upper_bound(value); } + //! @copydoc ::boost::intrusive::treap::upper_bound(const_reference) + iterator upper_bound(const_reference value); - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Returns an iterator to the first element whose - //! key according to the comparison functor is greater than key or - //! end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::treap::upper_bound(const KeyType&,KeyValueCompare) template - iterator upper_bound(const KeyType& key, KeyValueCompare comp) - { return tree_.upper_bound(key, comp); } + iterator upper_bound(const KeyType& key, KeyValueCompare comp); - //! Effects: Returns an iterator to the first element whose - //! key is greater than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - const_iterator upper_bound(const_reference value) const - { return tree_.upper_bound(value); } + //! @copydoc ::boost::intrusive::treap::upper_bound(const_reference)const + const_iterator upper_bound(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Returns a const_iterator to the first element whose - //! key according to the comparison functor is greater than key or - //! end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::treap::upper_bound(const KeyType&,KeyValueCompare)const template - const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const - { return tree_.upper_bound(key, comp); } + const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Finds an iterator to the first element whose value is - //! "value" or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - iterator find(const_reference value) - { return tree_.find(value); } + //! @copydoc ::boost::intrusive::treap::find(const_reference) + iterator find(const_reference value); - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Finds an iterator to the first element whose key is - //! "key" according to the comparison functor or end() if that element - //! does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::treap::find(const KeyType&,KeyValueCompare) template - iterator find(const KeyType& key, KeyValueCompare comp) - { return tree_.find(key, comp); } + iterator find(const KeyType& key, KeyValueCompare comp); - //! Effects: Finds a const_iterator to the first element whose value is - //! "value" or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - const_iterator find(const_reference value) const - { return tree_.find(value); } + //! @copydoc ::boost::intrusive::treap::find(const_reference)const + const_iterator find(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Finds a const_iterator to the first element whose key is - //! "key" according to the comparison functor or end() if that element - //! does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::treap::find(const KeyType&,KeyValueCompare)const template - const_iterator find(const KeyType& key, KeyValueCompare comp) const - { return tree_.find(key, comp); } + const_iterator find(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - std::pair equal_range(const_reference value) - { return tree_.equal_range(value); } + //! @copydoc ::boost::intrusive::treap::equal_range(const_reference) + std::pair equal_range(const_reference value); - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Finds a range containing all elements whose key is k - //! according to the comparison functor or an empty range - //! that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::treap::equal_range(const KeyType&,KeyValueCompare) template - std::pair equal_range(const KeyType& key, KeyValueCompare comp) - { return tree_.equal_range(key, comp); } + std::pair equal_range(const KeyType& key, KeyValueCompare comp); - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. + //! @copydoc ::boost::intrusive::treap::equal_range(const_reference)const std::pair - equal_range(const_reference value) const - { return tree_.equal_range(value); } + equal_range(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Finds a range containing all elements whose key is k - //! according to the comparison functor or an empty range - //! that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::treap::equal_range(const KeyType&,KeyValueCompare)const template std::pair - equal_range(const KeyType& key, KeyValueCompare comp) const - { return tree_.equal_range(key, comp); } + equal_range(const KeyType& key, KeyValueCompare comp) const; - //! Requires: 'lower_value' must not be greater than 'upper_value'. If - //! 'lower_value' == 'upper_value', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise - //! - //! second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the predicate throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_value and upper_value. + //! @copydoc ::boost::intrusive::treap::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) - { return tree_.bounded_range(lower_value, upper_value, left_closed, right_closed); } + (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); - //! Requires: KeyValueCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. - //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If - //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key, comp) if left_closed, upper_bound(lower_key, comp) otherwise - //! - //! second = upper_bound(upper_key, comp) if right_closed, lower_bound(upper_key, comp) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_key and upper_key. + //! @copydoc ::boost::intrusive::treap::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool) template std::pair bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) - { return tree_.bounded_range(lower_key, upper_key, comp, left_closed, right_closed); } + (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed); - //! Requires: 'lower_value' must not be greater than 'upper_value'. If - //! 'lower_value' == 'upper_value', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise - //! - //! second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the predicate throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_value and upper_value. + //! @copydoc ::boost::intrusive::treap::bounded_range(const_reference,const_reference,bool,bool)const std::pair - bounded_range(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const - { return tree_.bounded_range(lower_value, upper_value, left_closed, right_closed); } + bounded_range(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; - //! Requires: KeyValueCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. - //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If - //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key, comp) if left_closed, upper_bound(lower_key, comp) otherwise - //! - //! second = upper_bound(upper_key, comp) if right_closed, lower_bound(upper_key, comp) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_key and upper_key. + //! @copydoc ::boost::intrusive::treap::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const template - std::pair - bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const - { return tree_.bounded_range(lower_key, upper_key, comp, left_closed, right_closed); } + std::pair bounded_range + (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; - //! Requires: value must be an lvalue and shall be in a treap_set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid iterator i belonging to the treap_set - //! that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This static function is available only if the value traits - //! is stateless. - static iterator s_iterator_to(reference value) - { return tree_type::s_iterator_to(value); } + //! @copydoc ::boost::intrusive::treap::s_iterator_to(reference) + static iterator s_iterator_to(reference value); - //! Requires: value must be an lvalue and shall be in a treap_set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid const_iterator i belonging to the - //! treap_set that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This static function is available only if the value traits - //! is stateless. - static const_iterator s_iterator_to(const_reference value) - { return tree_type::s_iterator_to(value); } + //! @copydoc ::boost::intrusive::treap::s_iterator_to(const_reference) + static const_iterator s_iterator_to(const_reference value); - //! Requires: value must be an lvalue and shall be in a treap_set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid iterator i belonging to the treap_set - //! that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator iterator_to(reference value) - { return tree_.iterator_to(value); } + //! @copydoc ::boost::intrusive::treap::iterator_to(reference) + iterator iterator_to(reference value); - //! Requires: value must be an lvalue and shall be in a treap_set of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid const_iterator i belonging to the - //! treap_set that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator iterator_to(const_reference value) const - { return tree_.iterator_to(value); } + //! @copydoc ::boost::intrusive::treap::iterator_to(const_reference)const + const_iterator iterator_to(const_reference value) const; - //! Requires: value shall not be in a treap_set/treap_multiset. - //! - //! Effects: init_node puts the hook of a value in a well-known default - //! state. - //! - //! Throws: Nothing. - //! - //! Complexity: Constant time. - //! - //! Note: This function puts the hook in the well-known default state - //! used by auto_unlink and safe hooks. - static void init_node(reference value) - { tree_type::init_node(value); } + //! @copydoc ::boost::intrusive::treap::init_node(reference) + static void init_node(reference value); - //! Effects: Unlinks the leftmost node from the tree. - //! - //! Complexity: Average complexity is constant time. - //! - //! Throws: Nothing. - //! - //! Notes: This function breaks the tree and the tree can - //! only be used for more unlink_leftmost_without_rebalance calls. - //! This function is normally used to achieve a step by step - //! controlled destruction of the tree. - pointer unlink_leftmost_without_rebalance() - { return tree_.unlink_leftmost_without_rebalance(); } + //! @copydoc ::boost::intrusive::treap::unlink_leftmost_without_rebalance + pointer unlink_leftmost_without_rebalance(); - //! Requires: replace_this must be a valid iterator of *this - //! and with_this must not be inserted in any tree. - //! - //! Effects: Replaces replace_this in its position in the - //! tree with with_this. The tree does not need to be rebalanced. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This function will break container ordering invariants if - //! with_this is not equivalent to *replace_this according to the - //! ordering rules. This function is faster than erasing and inserting - //! the node, since no rebalancing or comparison is needed. - void replace_node(iterator replace_this, reference with_this) - { tree_.replace_node(replace_this, with_this); } + //! @copydoc ::boost::intrusive::treap::replace_node + void replace_node(iterator replace_this, reference with_this); - //! Effects: Rebalances the tree. - //! - //! Throws: Nothing. - //! - //! Complexity: Linear. - void rebalance() - { tree_.rebalance(); } + //! @copydoc ::boost::intrusive::treap::remove_node + void remove_node(reference value); - //! Requires: old_root is a node of a tree. - //! - //! Effects: Rebalances the subtree rooted at old_root. - //! - //! Returns: The new root of the subtree. - //! - //! Throws: Nothing. - //! - //! Complexity: Linear to the elements in the subtree. - iterator rebalance_subtree(iterator root) - { return tree_.rebalance_subtree(root); } - - //! Returns: The balance factor (alpha) used in this tree - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - float balance_factor() const - { return tree_.balance_factor(); } - - //! Requires: new_alpha must be a value between 0.5 and 1.0 - //! - //! Effects: Establishes a new balance factor (alpha) and rebalances - //! the tree if the new balance factor is stricter (less) than the old factor. - //! - //! Throws: Nothing. - //! - //! Complexity: Linear to the elements in the subtree. - void balance_factor(float new_alpha) - { tree_.balance_factor(new_alpha); } - - /// @cond - friend bool operator==(const treap_set_impl &x, const treap_set_impl &y) - { return x.tree_ == y.tree_; } - - friend bool operator<(const treap_set_impl &x, const treap_set_impl &y) - { return x.tree_ < y.tree_; } - /// @endcond + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED }; -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator!= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const treap_set_impl &x, const treap_set_impl &y) -#else -(const treap_set_impl &x, const treap_set_impl &y) -#endif -{ return !(x == y); } - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator> -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const treap_set_impl &x, const treap_set_impl &y) -#else -(const treap_set_impl &x, const treap_set_impl &y) -#endif -{ return y < x; } - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator<= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const treap_set_impl &x, const treap_set_impl &y) -#else -(const treap_set_impl &x, const treap_set_impl &y) -#endif -{ return !(y < x); } - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator>= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const treap_set_impl &x, const treap_set_impl &y) -#else -(const treap_set_impl &x, const treap_set_impl &y) -#endif -{ return !(x < y); } - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline void swap -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(treap_set_impl &x, treap_set_impl &y) -#else -(treap_set_impl &x, treap_set_impl &y) -#endif -{ x.swap(y); } //! Helper metafunction to define a \c treap_set that yields to the same type when the //! same options (either explicitly or implicitly) are used. #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else -template +template #endif struct make_treap_set { - /// @cond - typedef treap_set_impl - < typename make_treap_opt::type - > implementation_defined; + >::type packed_options; + + typedef typename detail::get_value_traits + ::type value_traits; + + typedef treap_set_impl + < value_traits + , typename packed_options::compare + , typename packed_options::priority + , typename packed_options::size_type + , packed_options::constant_time_size + > implementation_defined; /// @endcond typedef implementation_defined type; }; @@ -1418,7 +490,7 @@ class treap_set {} treap_set& operator=(BOOST_RV_REF(treap_set) x) - { this->Base::operator=(::boost::move(static_cast(x))); return *this; } + { return static_cast(this->Base::operator=(::boost::move(static_cast(x)))); } static treap_set &container_from_end_iterator(iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } @@ -1449,14 +521,17 @@ class treap_set #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class treap_multiset_impl +#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + : public treap_impl +#endif { /// @cond - typedef treap_impl tree_type; - + typedef treap_impl tree_type; BOOST_MOVABLE_BUT_NOT_COPYABLE(treap_multiset_impl) + typedef tree_type implementation_defined; /// @endcond @@ -1483,12 +558,7 @@ class treap_multiset_impl typedef typename implementation_defined::const_node_ptr const_node_ptr; typedef typename implementation_defined::node_algorithms node_algorithms; - static const bool constant_time_size = Config::constant_time_size; - - /// @cond - private: - tree_type tree_; - /// @endcond + static const bool constant_time_size = implementation_defined::constant_time_size; public: //! Effects: Constructs an empty treap_multiset. @@ -1497,11 +567,11 @@ class treap_multiset_impl //! //! Throws: If value_traits::node_traits::node //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) - //! or the copy constructor of the value_compare/priority_compare objects throw. - explicit treap_multiset_impl( const value_compare &cmp = value_compare() - , const priority_compare &pcmp = priority_compare() - , const value_traits &v_traits = value_traits()) - : tree_(cmp, pcmp, v_traits) + //! or the copy constructor of the value_compare object throws. + explicit treap_multiset_impl( const value_compare &cmp = value_compare() + , const priority_compare &pcmp = priority_compare() + , const value_traits &v_traits = value_traits()) + : tree_type(cmp, pcmp, v_traits) {} //! Requires: Dereferencing iterator must yield an lvalue of type value_type. @@ -1511,1161 +581,322 @@ class treap_multiset_impl //! [b, e). //! //! Complexity: Linear in N if [b, e) is already sorted using - //! comp and otherwise N * log N, where N is the distance between first and last + //! comp and otherwise N * log N, where N is std::distance(last, first). //! //! Throws: If value_traits::node_traits::node //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) - //! or the copy constructor/operator() of the value_compare/priority_compare objects throw. + //! or the copy constructor/operator() of the value_compare object throws. template treap_multiset_impl( Iterator b, Iterator e - , const value_compare &cmp = value_compare() - , const priority_compare &pcmp = priority_compare() - , const value_traits &v_traits = value_traits()) - : tree_(false, b, e, cmp, pcmp, v_traits) + , const value_compare &cmp = value_compare() + , const priority_compare &pcmp = priority_compare() + , const value_traits &v_traits = value_traits()) + : tree_type(false, b, e, cmp, pcmp, v_traits) {} //! Effects: to-do //! treap_multiset_impl(BOOST_RV_REF(treap_multiset_impl) x) - : tree_(::boost::move(x.tree_)) + : tree_type(::boost::move(static_cast(x))) {} //! Effects: to-do //! treap_multiset_impl& operator=(BOOST_RV_REF(treap_multiset_impl) x) - { tree_ = ::boost::move(x.tree_); return *this; } + { return static_cast(tree_type::operator=(::boost::move(static_cast(x)))); } - //! Effects: Detaches all elements from this. The objects in the treap_multiset - //! are not deleted (i.e. no destructors are called). - //! - //! Complexity: Linear to the number of elements on the container. - //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. - //! - //! Throws: Nothing. - ~treap_multiset_impl() - {} + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::treap::~treap() + ~treap_multiset_impl(); - //! Effects: Returns an iterator pointing to the beginning of the treap_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator begin() - { return tree_.begin(); } + //! @copydoc ::boost::intrusive::treap::begin() + iterator begin(); - //! Effects: Returns a const_iterator pointing to the beginning of the treap_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator begin() const - { return tree_.begin(); } + //! @copydoc ::boost::intrusive::treap::begin()const + const_iterator begin() const; - //! Effects: Returns a const_iterator pointing to the beginning of the treap_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator cbegin() const - { return tree_.cbegin(); } + //! @copydoc ::boost::intrusive::treap::cbegin()const + const_iterator cbegin() const; - //! Effects: Returns an iterator pointing to the end of the treap_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator end() - { return tree_.end(); } + //! @copydoc ::boost::intrusive::treap::end() + iterator end(); - //! Effects: Returns a const_iterator pointing to the end of the treap_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator end() const - { return tree_.end(); } + //! @copydoc ::boost::intrusive::treap::end()const + const_iterator end() const; - //! Effects: Returns a const_iterator pointing to the end of the treap_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator cend() const - { return tree_.cend(); } + //! @copydoc ::boost::intrusive::treap::cend()const + const_iterator cend() const; - //! Effects: Returns an iterator pointing to the highest priority object of the tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator top() - { return tree_.top(); } + //! @copydoc ::boost::intrusive::treap::rbegin() + reverse_iterator rbegin(); - //! Effects: Returns a const_iterator pointing to the highest priority object of the tree.. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator top() const - { return this->ctop(); } + //! @copydoc ::boost::intrusive::treap::rbegin()const + const_reverse_iterator rbegin() const; - //! Effects: Returns a const_iterator pointing to the highest priority object of the tree.. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator ctop() const - { return tree_.ctop(); } + //! @copydoc ::boost::intrusive::treap::crbegin()const + const_reverse_iterator crbegin() const; - //! Effects: Returns a reverse_iterator pointing to the beginning of the - //! reversed treap_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - reverse_iterator rbegin() - { return tree_.rbegin(); } + //! @copydoc ::boost::intrusive::treap::rend() + reverse_iterator rend(); - //! Effects: Returns a const_reverse_iterator pointing to the beginning - //! of the reversed treap_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator rbegin() const - { return tree_.rbegin(); } + //! @copydoc ::boost::intrusive::treap::rend()const + const_reverse_iterator rend() const; - //! Effects: Returns a const_reverse_iterator pointing to the beginning - //! of the reversed treap_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator crbegin() const - { return tree_.crbegin(); } + //! @copydoc ::boost::intrusive::treap::crend()const + const_reverse_iterator crend() const; - //! Effects: Returns a reverse_iterator pointing to the end - //! of the reversed treap_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - reverse_iterator rend() - { return tree_.rend(); } + //! @copydoc ::boost::intrusive::treap::container_from_end_iterator(iterator) + static treap_multiset_impl &container_from_end_iterator(iterator end_iterator); - //! Effects: Returns a const_reverse_iterator pointing to the end - //! of the reversed treap_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator rend() const - { return tree_.rend(); } + //! @copydoc ::boost::intrusive::treap::container_from_end_iterator(const_iterator) + static const treap_multiset_impl &container_from_end_iterator(const_iterator end_iterator); - //! Effects: Returns a const_reverse_iterator pointing to the end - //! of the reversed treap_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator crend() const - { return tree_.crend(); } + //! @copydoc ::boost::intrusive::treap::container_from_iterator(iterator) + static treap_multiset_impl &container_from_iterator(iterator it); - //! Effects: Returns a reverse_iterator pointing to the highest priority object of the - //! reversed tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - reverse_iterator rtop() - { return tree_.rtop(); } + //! @copydoc ::boost::intrusive::treap::container_from_iterator(const_iterator) + static const treap_multiset_impl &container_from_iterator(const_iterator it); - //! Effects: Returns a const_reverse_iterator pointing to the highest priority objec - //! of the reversed tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator rtop() const - { return tree_.crtop(); } + //! @copydoc ::boost::intrusive::treap::key_comp()const + key_compare key_comp() const; - //! Effects: Returns a const_reverse_iterator pointing to the highest priority object - //! of the reversed tree. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_reverse_iterator crtop() const - { return tree_.crtop(); } + //! @copydoc ::boost::intrusive::treap::value_comp()const + value_compare value_comp() const; - //! Precondition: end_iterator must be a valid end iterator - //! of treap_multiset. - //! - //! Effects: Returns a const reference to the treap_multiset associated to the end iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - static treap_multiset_impl &container_from_end_iterator(iterator end_iterator) - { - return *detail::parent_from_member - ( &tree_type::container_from_end_iterator(end_iterator) - , &treap_multiset_impl::tree_); - } + //! @copydoc ::boost::intrusive::treap::empty()const + bool empty() const; - //! Precondition: end_iterator must be a valid end const_iterator - //! of treap_multiset. - //! - //! Effects: Returns a const reference to the treap_multiset associated to the end iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - static const treap_multiset_impl &container_from_end_iterator(const_iterator end_iterator) - { - return *detail::parent_from_member - ( &tree_type::container_from_end_iterator(end_iterator) - , &treap_multiset_impl::tree_); - } + //! @copydoc ::boost::intrusive::treap::size()const + size_type size() const; - //! Precondition: it must be a valid iterator of multiset. - //! - //! Effects: Returns a const reference to the multiset associated to the iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - static treap_multiset_impl &container_from_iterator(iterator it) - { - return *detail::parent_from_member - ( &tree_type::container_from_iterator(it) - , &treap_multiset_impl::tree_); - } + //! @copydoc ::boost::intrusive::treap::swap + void swap(treap_multiset_impl& other); - //! Precondition: it must be a valid const_iterator of multiset. - //! - //! Effects: Returns a const reference to the multiset associated to the iterator - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - static const treap_multiset_impl &container_from_iterator(const_iterator it) - { - return *detail::parent_from_member - ( &tree_type::container_from_iterator(it) - , &treap_multiset_impl::tree_); - } - - //! Effects: Returns the key_compare object used by the treap_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: If key_compare copy-constructor throws. - key_compare key_comp() const - { return tree_.value_comp(); } - - //! Effects: Returns the value_compare object used by the treap_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: If value_compare copy-constructor throws. - value_compare value_comp() const - { return tree_.value_comp(); } - - //! Effects: Returns the priority_compare object used by the treap_multiset. - //! - //! Complexity: Constant. - //! - //! Throws: If priority_compare copy-constructor throws. - priority_compare priority_comp() const - { return tree_.priority_comp(); } - - //! Effects: Returns true if the container is empty. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - bool empty() const - { return tree_.empty(); } - - //! Effects: Returns the number of elements stored in the treap_multiset. - //! - //! Complexity: Linear to elements contained in *this if, - //! constant-time size option is enabled. Constant-time otherwise. - //! - //! Throws: Nothing. - size_type size() const - { return tree_.size(); } - - //! Effects: Swaps the contents of two treap_multisets. - //! - //! Complexity: Constant. - //! - //! Throws: If the swap() call for the comparison functor - //! found using ADL throws. Strong guarantee. - void swap(treap_multiset_impl& other) - { tree_.swap(other.tree_); } - - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! Cloner should yield to nodes equivalent to the original nodes. - //! - //! Effects: Erases all the elements from *this - //! calling Disposer::operator()(pointer), clones all the - //! elements from src calling Cloner::operator()(const_reference ) - //! and inserts them on *this. Copies the predicate from the source container. - //! - //! If cloner throws, all cloned elements are unlinked and disposed - //! calling Disposer::operator()(pointer). - //! - //! Complexity: Linear to erased plus inserted elements. - //! - //! Throws: If cloner throws or predicate copy assignment throws. Basic guarantee. + //! @copydoc ::boost::intrusive::treap::clone_from template - void clone_from(const treap_multiset_impl &src, Cloner cloner, Disposer disposer) - { tree_.clone_from(src.tree_, cloner, disposer); } + void clone_from(const treap_multiset_impl &src, Cloner cloner, Disposer disposer); - //! Requires: value must be an lvalue - //! - //! Effects: Inserts value into the treap_multiset. - //! - //! Returns: An iterator that points to the position where the new - //! element was inserted. - //! - //! Complexity: Average complexity for insert element is at - //! most logarithmic. - //! - //! Throws: If the internal value_compare or priority_compare ordering - //! function throws. Strong guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + //! @copydoc ::boost::intrusive::treap::top() + iterator top(); + + //! @copydoc ::boost::intrusive::treap::top()const + const_iterator top() const; + + //! @copydoc ::boost::intrusive::treap::ctop()const + const_iterator ctop() const; + + //! @copydoc ::boost::intrusive::treap::rtop() + reverse_iterator rtop(); + + //! @copydoc ::boost::intrusive::treap::rtop()const + const_reverse_iterator rtop() const; + + //! @copydoc ::boost::intrusive::treap::crtop()const + const_reverse_iterator crtop() const; + + //! @copydoc ::boost::intrusive::treap::crtop() const + priority_compare priority_comp() const; + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + + //! @copydoc ::boost::intrusive::treap::insert_equal(reference) iterator insert(reference value) - { return tree_.insert_equal(value); } + { return tree_type::insert_equal(value); } - //! Requires: value must be an lvalue - //! - //! Effects: Inserts x into the treap_multiset, using pos as a hint to - //! where it will be inserted. - //! - //! Returns: An iterator that points to the position where the new - //! element was inserted. - //! - //! Complexity: Logarithmic in general, but it is amortized - //! constant time if t is inserted immediately before hint. - //! - //! Throws: If internal value_compare or priority_compare ordering functions throw. - //! Strong guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + //! @copydoc ::boost::intrusive::treap::insert_equal(const_iterator,reference) iterator insert(const_iterator hint, reference value) - { return tree_.insert_equal(hint, value); } + { return tree_type::insert_equal(hint, value); } - //! Requires: Dereferencing iterator must yield an lvalue - //! of type value_type. - //! - //! Effects: Inserts a range into the treap_multiset. - //! - //! Returns: An iterator that points to the position where the new - //! element was inserted. - //! - //! Complexity: Insert range is in general O(N * log(N)), where N is the - //! size of the range. However, it is linear in N if the range is already sorted - //! by value_comp(). - //! - //! Throws: If internal value_compare or priority_compare ordering functions throw. - //! Basic guarantee. - //! - //! Note: Does not affect the validity of iterators and references. - //! No copy-constructors are called. + //! @copydoc ::boost::intrusive::treap::insert_equal(Iterator,Iterator) template void insert(Iterator b, Iterator e) - { tree_.insert_equal(b, e); } + { tree_type::insert_equal(b, e); } - //! Requires: value must be an lvalue, "pos" must be - //! a valid iterator (or end) and must be the succesor of value - //! once inserted according to the predicate - //! - //! Effects: Inserts x into the treap before "pos". - //! - //! Complexity: Constant time. - //! - //! Throws: If the internal priority_compare function throws. Strong guarantee. - //! - //! Note: This function does not check preconditions so if "pos" is not - //! the successor of "value" treap ordering invariant will be broken. - //! This is a low-level function to be used only for performance reasons - //! by advanced users. - iterator insert_before(const_iterator pos, reference value) - { return tree_.insert_before(pos, value); } + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! @copydoc ::boost::intrusive::treap::insert_before + iterator insert_before(const_iterator pos, reference value); - //! Requires: value must be an lvalue, and it must be no less - //! than the greatest inserted key. - //! - //! Effects: Inserts x into the treap in the last position. - //! - //! Complexity: Constant time. - //! - //! Throws: If the internal priority_compare function throws. Strong guarantee. - //! - //! Note: This function does not check preconditions so if value is - //! less than the greatest inserted key treap ordering invariant will be broken. - //! This function is slightly more efficient than using "insert_before". - //! This is a low-level function to be used only for performance reasons - //! by advanced users. - void push_back(reference value) - { tree_.push_back(value); } + //! @copydoc ::boost::intrusive::treap::push_back + void push_back(reference value); - //! Requires: value must be an lvalue, and it must be no greater - //! than the minimum inserted key - //! - //! Effects: Inserts x into the treap in the first position. - //! - //! Complexity: Constant time. - //! - //! Throws: If the internal priority_compare function throws. Strong guarantee. - //! - //! Note: This function does not check preconditions so if value is - //! greater than the minimum inserted key treap ordering invariant will be broken. - //! This function is slightly more efficient than using "insert_before". - //! This is a low-level function to be used only for performance reasons - //! by advanced users. - void push_front(reference value) - { tree_.push_front(value); } + //! @copydoc ::boost::intrusive::treap::push_front + void push_front(reference value); - //! Effects: Erases the element pointed to by pos. - //! - //! Complexity: Average complexity is constant time. - //! - //! Returns: An iterator to the element after the erased element. - //! - //! Throws: If the internal priority_compare function throws. Strong guarantee. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - iterator erase(const_iterator i) - { return tree_.erase(i); } + //! @copydoc ::boost::intrusive::treap::erase(const_iterator) + iterator erase(const_iterator i); - //! Effects: Erases the range pointed to by b end e. - //! - //! Returns: An iterator to the element after the erased elements. - //! - //! Complexity: Average complexity for erase range is at most - //! O(log(size() + N)), where N is the number of elements in the range. - //! - //! Throws: If the internal priority_compare function throws. Basic guarantee. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - iterator erase(const_iterator b, const_iterator e) - { return tree_.erase(b, e); } + //! @copydoc ::boost::intrusive::treap::erase(const_iterator,const_iterator) + iterator erase(const_iterator b, const_iterator e); - //! Effects: Erases all the elements with the given value. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: O(log(size() + this->count(value)). - //! - //! Throws: If the internal value_compare or priority_compare ordering - //! functiona throw. Basic guarantee. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - size_type erase(const_reference value) - { return tree_.erase(value); } + //! @copydoc ::boost::intrusive::treap::erase(const_reference) + size_type erase(const_reference value); - //! Effects: Erases all the elements that compare equal with - //! the given key and the given comparison functor. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: O(log(size() + this->count(key, comp)). - //! - //! Throws: If comp or internal priority_compare ordering functions throw. Basic guarantee. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. + //! @copydoc ::boost::intrusive::treap::erase(const KeyType&,KeyValueCompare) template - size_type erase(const KeyType& key, KeyValueCompare comp - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) - { return tree_.erase(key, comp); } + size_type erase(const KeyType& key, KeyValueCompare comp); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Returns: An iterator to the element after the erased element. - //! - //! Effects: Erases the element pointed to by pos. - //! Disposer::operator()(pointer) is called for the removed element. - //! - //! Complexity: Average complexity for erase element is constant time. - //! - //! Throws: If the internal priority_compare function throws. Strong guarantee. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::treap::erase_and_dispose(const_iterator,Disposer) template - iterator erase_and_dispose(const_iterator i, Disposer disposer) - { return tree_.erase_and_dispose(i, disposer); } + iterator erase_and_dispose(const_iterator i, Disposer disposer); - #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + //! @copydoc ::boost::intrusive::treap::erase_and_dispose(const_iterator,const_iterator,Disposer) template - iterator erase_and_dispose(iterator i, Disposer disposer) - { return this->erase_and_dispose(const_iterator(i), disposer); } - #endif + iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Returns: An iterator to the element after the erased elements. - //! - //! Effects: Erases the range pointed to by b end e. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Complexity: Average complexity for erase range is at most - //! O(log(size() + N)), where N is the number of elements in the range. - //! - //! Throws: If the internal priority_compare function throws. Basic guarantee. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::treap::erase_and_dispose(const_reference, Disposer) template - iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer) - { return tree_.erase_and_dispose(b, e, disposer); } + size_type erase_and_dispose(const_reference value, Disposer disposer); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements with the given value. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: O(log(size() + this->count(value)). - //! - //! Throws: If the internal value_compare ordering function throws. Basic guarantee. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - template - size_type erase_and_dispose(const_reference value, Disposer disposer) - { return tree_.erase_and_dispose(value, disposer); } - - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements with the given key. - //! according to the comparison functor "comp". - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Returns: The number of erased elements. - //! - //! Complexity: O(log(size() + this->count(key, comp)). - //! - //! Throws: If comp or internal priority_compare ordering functions throw. Basic guarantee. - //! - //! Note: Invalidates the iterators - //! to the erased elements. + //! @copydoc ::boost::intrusive::treap::erase_and_dispose(const KeyType&,KeyValueCompare,Disposer) template - size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer - /// @cond - , typename detail::enable_if_c::value >::type * = 0 - /// @endcond - ) - { return tree_.erase_and_dispose(key, comp, disposer); } + size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer); - //! Effects: Erases all the elements of the container. - //! - //! Complexity: Linear to the number of elements on the container. - //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. - void clear() - { return tree_.clear(); } + //! @copydoc ::boost::intrusive::treap::clear + void clear(); - //! Requires: Disposer::operator()(pointer) shouldn't throw. - //! - //! Effects: Erases all the elements of the container. - //! - //! Complexity: Linear to the number of elements on the container. - //! Disposer::operator()(pointer) is called for the removed elements. - //! - //! Throws: Nothing. - //! - //! Note: Invalidates the iterators (but not the references) - //! to the erased elements. No destructors are called. + //! @copydoc ::boost::intrusive::treap::clear_and_dispose template - void clear_and_dispose(Disposer disposer) - { return tree_.clear_and_dispose(disposer); } + void clear_and_dispose(Disposer disposer); - //! Effects: Returns the number of contained elements with the given key - //! - //! Complexity: Logarithmic to the number of elements contained plus lineal - //! to number of objects with the given key. - //! - //! Throws: If the internal value_compare ordering function throws. - size_type count(const_reference value) const - { return tree_.count(value); } + //! @copydoc ::boost::intrusive::treap::count(const_reference)const + size_type count(const_reference value) const; - //! Effects: Returns the number of contained elements with the same key - //! compared with the given comparison functor. - //! - //! Complexity: Logarithmic to the number of elements contained plus lineal - //! to number of objects with the given key. - //! - //! Throws: If comp ordering function throws. + //! @copydoc ::boost::intrusive::treap::count(const KeyType&,KeyValueCompare)const template - size_type count(const KeyType& key, KeyValueCompare comp) const - { return tree_.count(key, comp); } - - //! Effects: Returns an iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - iterator lower_bound(const_reference value) - { return tree_.lower_bound(value); } - - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Returns an iterator to the first element whose - //! key according to the comparison functor is not less than k or - //! end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + size_type count(const KeyType& key, KeyValueCompare comp) const; + + //! @copydoc ::boost::intrusive::treap::lower_bound(const_reference) + iterator lower_bound(const_reference value); + + //! @copydoc ::boost::intrusive::treap::lower_bound(const KeyType&,KeyValueCompare) template - iterator lower_bound(const KeyType& key, KeyValueCompare comp) - { return tree_.lower_bound(key, comp); } + iterator lower_bound(const KeyType& key, KeyValueCompare comp); - //! Effects: Returns a const iterator to the first element whose - //! key is not less than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - const_iterator lower_bound(const_reference value) const - { return tree_.lower_bound(value); } + //! @copydoc ::boost::intrusive::treap::lower_bound(const_reference)const + const_iterator lower_bound(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Returns a const_iterator to the first element whose - //! key according to the comparison functor is not less than k or - //! end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::treap::lower_bound(const KeyType&,KeyValueCompare)const template - const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const - { return tree_.lower_bound(key, comp); } + const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Returns an iterator to the first element whose - //! key is greater than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - iterator upper_bound(const_reference value) - { return tree_.upper_bound(value); } + //! @copydoc ::boost::intrusive::treap::upper_bound(const_reference) + iterator upper_bound(const_reference value); - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Returns an iterator to the first element whose - //! key according to the comparison functor is greater than key or - //! end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::treap::upper_bound(const KeyType&,KeyValueCompare) template - iterator upper_bound(const KeyType& key, KeyValueCompare comp) - { return tree_.upper_bound(key, comp); } + iterator upper_bound(const KeyType& key, KeyValueCompare comp); - //! Effects: Returns an iterator to the first element whose - //! key is greater than k or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - const_iterator upper_bound(const_reference value) const - { return tree_.upper_bound(value); } + //! @copydoc ::boost::intrusive::treap::upper_bound(const_reference)const + const_iterator upper_bound(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Returns a const_iterator to the first element whose - //! key according to the comparison functor is greater than key or - //! end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::treap::upper_bound(const KeyType&,KeyValueCompare)const template - const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const - { return tree_.upper_bound(key, comp); } + const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Finds an iterator to the first element whose value is - //! "value" or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - iterator find(const_reference value) - { return tree_.find(value); } + //! @copydoc ::boost::intrusive::treap::find(const_reference) + iterator find(const_reference value); - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Finds an iterator to the first element whose key is - //! "key" according to the comparison functor or end() if that element - //! does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::treap::find(const KeyType&,KeyValueCompare) template - iterator find(const KeyType& key, KeyValueCompare comp) - { return tree_.find(key, comp); } + iterator find(const KeyType& key, KeyValueCompare comp); - //! Effects: Finds a const_iterator to the first element whose value is - //! "value" or end() if that element does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - const_iterator find(const_reference value) const - { return tree_.find(value); } + //! @copydoc ::boost::intrusive::treap::find(const_reference)const + const_iterator find(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Finds a const_iterator to the first element whose key is - //! "key" according to the comparison functor or end() if that element - //! does not exist. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::treap::find(const KeyType&,KeyValueCompare)const template - const_iterator find(const KeyType& key, KeyValueCompare comp) const - { return tree_.find(key, comp); } + const_iterator find(const KeyType& key, KeyValueCompare comp) const; - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. - std::pair equal_range(const_reference value) - { return tree_.equal_range(value); } + //! @copydoc ::boost::intrusive::treap::equal_range(const_reference) + std::pair equal_range(const_reference value); - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Finds a range containing all elements whose key is k - //! according to the comparison functor or an empty range - //! that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::treap::equal_range(const KeyType&,KeyValueCompare) template - std::pair equal_range(const KeyType& key, KeyValueCompare comp) - { return tree_.equal_range(key, comp); } + std::pair equal_range(const KeyType& key, KeyValueCompare comp); - //! Effects: Finds a range containing all elements whose key is k or - //! an empty range that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the internal value_compare ordering function throws. + //! @copydoc ::boost::intrusive::treap::equal_range(const_reference)const std::pair - equal_range(const_reference value) const - { return tree_.equal_range(value); } + equal_range(const_reference value) const; - //! Requires: comp must imply the same element order as - //! value_compare. Usually key is the part of the value_type - //! that is used in the ordering functor. - //! - //! Effects: Finds a range containing all elements whose key is k - //! according to the comparison functor or an empty range - //! that indicates the position where those elements would be - //! if they there is no elements with key k. - //! - //! Complexity: Logarithmic. - //! - //! Throws: If comp ordering function throws. - //! - //! Note: This function is used when constructing a value_type - //! is expensive and the value_type can be compared with a cheaper - //! key type. Usually this key is part of the value_type. + //! @copydoc ::boost::intrusive::treap::equal_range(const KeyType&,KeyValueCompare)const template std::pair - equal_range(const KeyType& key, KeyValueCompare comp) const - { return tree_.equal_range(key, comp); } + equal_range(const KeyType& key, KeyValueCompare comp) const; - //! Requires: 'lower_value' must not be greater than 'upper_value'. If - //! 'lower_value' == 'upper_value', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise - //! - //! second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the predicate throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_value and upper_value. + //! @copydoc ::boost::intrusive::treap::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) - { return tree_.bounded_range(lower_value, upper_value, left_closed, right_closed); } + (const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed); - //! Requires: KeyValueCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. - //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If - //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key, comp) if left_closed, upper_bound(lower_key, comp) otherwise - //! - //! second = upper_bound(upper_key, comp) if right_closed, lower_bound(upper_key, comp) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_key and upper_key. + //! @copydoc ::boost::intrusive::treap::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool) template std::pair bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) - { return tree_.bounded_range(lower_key, upper_key, comp, left_closed, right_closed); } + (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed); - //! Requires: 'lower_value' must not be greater than 'upper_value'. If - //! 'lower_value' == 'upper_value', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key) if left_closed, upper_bound(lower_key) otherwise - //! - //! second = upper_bound(upper_key) if right_closed, lower_bound(upper_key) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If the predicate throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_value and upper_value. + //! @copydoc ::boost::intrusive::treap::bounded_range(const_reference,const_reference,bool,bool)const std::pair - bounded_range(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const - { return tree_.bounded_range(lower_value, upper_value, left_closed, right_closed); } + bounded_range(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const; - //! Requires: KeyValueCompare is a function object that induces a strict weak - //! ordering compatible with the strict weak ordering used to create the - //! the tree. - //! 'lower_key' must not be greater than 'upper_key' according to 'comp'. If - //! 'lower_key' == 'upper_key', ('left_closed' || 'right_closed') must be false. - //! - //! Effects: Returns an a pair with the following criteria: - //! - //! first = lower_bound(lower_key, comp) if left_closed, upper_bound(lower_key, comp) otherwise - //! - //! second = upper_bound(upper_key, comp) if right_closed, lower_bound(upper_key, comp) otherwise - //! - //! Complexity: Logarithmic. - //! - //! Throws: If "comp" throws. - //! - //! Note: This function can be more efficient than calling upper_bound - //! and lower_bound for lower_key and upper_key. + //! @copydoc ::boost::intrusive::treap::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const template - std::pair - bounded_range - (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const - { return tree_.bounded_range(lower_key, upper_key, comp, left_closed, right_closed); } + std::pair bounded_range + (const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const; - //! Requires: value must be an lvalue and shall be in a treap_multiset of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid iterator i belonging to the treap_multiset - //! that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This static function is available only if the value traits - //! is stateless. - static iterator s_iterator_to(reference value) - { return tree_type::s_iterator_to(value); } + //! @copydoc ::boost::intrusive::treap::s_iterator_to(reference) + static iterator s_iterator_to(reference value); - //! Requires: value must be an lvalue and shall be in a treap_multiset of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid const_iterator i belonging to the - //! treap_multiset that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This static function is available only if the value traits - //! is stateless. - static const_iterator s_iterator_to(const_reference value) - { return tree_type::s_iterator_to(value); } + //! @copydoc ::boost::intrusive::treap::s_iterator_to(const_reference) + static const_iterator s_iterator_to(const_reference value); - //! Requires: value must be an lvalue and shall be in a treap_multiset of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid iterator i belonging to the treap_multiset - //! that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - iterator iterator_to(reference value) - { return tree_.iterator_to(value); } + //! @copydoc ::boost::intrusive::treap::iterator_to(reference) + iterator iterator_to(reference value); - //! Requires: value must be an lvalue and shall be in a treap_multiset of - //! appropriate type. Otherwise the behavior is undefined. - //! - //! Effects: Returns: a valid const_iterator i belonging to the - //! treap_multiset that points to the value - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - const_iterator iterator_to(const_reference value) const - { return tree_.iterator_to(value); } + //! @copydoc ::boost::intrusive::treap::iterator_to(const_reference)const + const_iterator iterator_to(const_reference value) const; - //! Requires: value shall not be in a treap_multiset/treap_multiset. - //! - //! Effects: init_node puts the hook of a value in a well-known default - //! state. - //! - //! Throws: Nothing. - //! - //! Complexity: Constant time. - //! - //! Note: This function puts the hook in the well-known default state - //! used by auto_unlink and safe hooks. - static void init_node(reference value) - { tree_type::init_node(value); } + //! @copydoc ::boost::intrusive::treap::init_node(reference) + static void init_node(reference value); - //! Effects: Unlinks the leftmost node from the tree. - //! - //! Complexity: Average complexity is constant time. - //! - //! Throws: Nothing. - //! - //! Notes: This function breaks the tree and the tree can - //! only be used for more unlink_leftmost_without_rebalance calls. - //! This function is normally used to achieve a step by step - //! controlled destruction of the tree. - pointer unlink_leftmost_without_rebalance() - { return tree_.unlink_leftmost_without_rebalance(); } + //! @copydoc ::boost::intrusive::treap::unlink_leftmost_without_rebalance + pointer unlink_leftmost_without_rebalance(); - //! Requires: replace_this must be a valid iterator of *this - //! and with_this must not be inserted in any tree. - //! - //! Effects: Replaces replace_this in its position in the - //! tree with with_this. The tree does not need to be rebalanced. - //! - //! Complexity: Constant. - //! - //! Throws: Nothing. - //! - //! Note: This function will break container ordering invariants if - //! with_this is not equivalent to *replace_this according to the - //! ordering rules. This function is faster than erasing and inserting - //! the node, since no rebalancing or comparison is needed. - void replace_node(iterator replace_this, reference with_this) - { tree_.replace_node(replace_this, with_this); } + //! @copydoc ::boost::intrusive::treap::replace_node + void replace_node(iterator replace_this, reference with_this); - //! Effects: Rebalances the tree. - //! - //! Throws: Nothing. - //! - //! Complexity: Linear. - void rebalance() - { tree_.rebalance(); } + //! @copydoc ::boost::intrusive::treap::remove_node + void remove_node(reference value); - //! Requires: old_root is a node of a tree. - //! - //! Effects: Rebalances the subtree rooted at old_root. - //! - //! Returns: The new root of the subtree. - //! - //! Throws: Nothing. - //! - //! Complexity: Linear to the elements in the subtree. - iterator rebalance_subtree(iterator root) - { return tree_.rebalance_subtree(root); } - - //! Returns: The balance factor (alpha) used in this tree - //! - //! Throws: Nothing. - //! - //! Complexity: Constant. - float balance_factor() const - { return tree_.balance_factor(); } - - //! Requires: new_alpha must be a value between 0.5 and 1.0 - //! - //! Effects: Establishes a new balance factor (alpha) and rebalances - //! the tree if the new balance factor is stricter (less) than the old factor. - //! - //! Throws: Nothing. - //! - //! Complexity: Linear to the elements in the subtree. - void balance_factor(float new_alpha) - { tree_.balance_factor(new_alpha); } - - /// @cond - friend bool operator==(const treap_multiset_impl &x, const treap_multiset_impl &y) - { return x.tree_ == y.tree_; } - - friend bool operator<(const treap_multiset_impl &x, const treap_multiset_impl &y) - { return x.tree_ < y.tree_; } - /// @endcond + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED }; -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator!= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const treap_multiset_impl &x, const treap_multiset_impl &y) -#else -(const treap_multiset_impl &x, const treap_multiset_impl &y) -#endif -{ return !(x == y); } - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator> -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const treap_multiset_impl &x, const treap_multiset_impl &y) -#else -(const treap_multiset_impl &x, const treap_multiset_impl &y) -#endif -{ return y < x; } - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator<= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const treap_multiset_impl &x, const treap_multiset_impl &y) -#else -(const treap_multiset_impl &x, const treap_multiset_impl &y) -#endif -{ return !(y < x); } - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline bool operator>= -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(const treap_multiset_impl &x, const treap_multiset_impl &y) -#else -(const treap_multiset_impl &x, const treap_multiset_impl &y) -#endif -{ return !(x < y); } - -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -template -#else -template -#endif -inline void swap -#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) -(treap_multiset_impl &x, treap_multiset_impl &y) -#else -(treap_multiset_impl &x, treap_multiset_impl &y) -#endif -{ x.swap(y); } //! Helper metafunction to define a \c treap_multiset that yields to the same type when the //! same options (either explicitly or implicitly) are used. #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else -template +template #endif struct make_treap_multiset { - /// @cond + typedef typename pack_options + < treap_defaults, + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3, O4 + #else + Options... + #endif + >::type packed_options; + + typedef typename detail::get_value_traits + ::type value_traits; + typedef treap_multiset_impl - < typename make_treap_opt::type - > implementation_defined; + < value_traits + , typename packed_options::compare + , typename packed_options::priority + , typename packed_options::size_type + , packed_options::constant_time_size + > implementation_defined; /// @endcond typedef implementation_defined type; }; @@ -2694,7 +925,6 @@ class treap_multiset Options... #endif >::type Base; - //Movable BOOST_MOVABLE_BUT_NOT_COPYABLE(treap_multiset) public: @@ -2707,17 +937,17 @@ class treap_multiset //Assert if passed value traits are compatible with the type BOOST_STATIC_ASSERT((detail::is_same::value)); - treap_multiset( const value_compare &cmp = value_compare() - , const priority_compare &pcmp = priority_compare() - , const value_traits &v_traits = value_traits()) + treap_multiset( const value_compare &cmp = value_compare() + , const priority_compare &pcmp = priority_compare() + , const value_traits &v_traits = value_traits()) : Base(cmp, pcmp, v_traits) {} template treap_multiset( Iterator b, Iterator e - , const value_compare &cmp = value_compare() - , const priority_compare &pcmp = priority_compare() - , const value_traits &v_traits = value_traits()) + , const value_compare &cmp = value_compare() + , const priority_compare &pcmp = priority_compare() + , const value_traits &v_traits = value_traits()) : Base(b, e, cmp, pcmp, v_traits) {} @@ -2726,7 +956,7 @@ class treap_multiset {} treap_multiset& operator=(BOOST_RV_REF(treap_multiset) x) - { this->Base::operator=(::boost::move(static_cast(x))); return *this; } + { return static_cast(this->Base::operator=(::boost::move(static_cast(x)))); } static treap_multiset &container_from_end_iterator(iterator end_iterator) { return static_cast(Base::container_from_end_iterator(end_iterator)); } diff --git a/include/boost/intrusive/trivial_value_traits.hpp b/include/boost/intrusive/trivial_value_traits.hpp index 5c166fd..0ea306d 100644 --- a/include/boost/intrusive/trivial_value_traits.hpp +++ b/include/boost/intrusive/trivial_value_traits.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 diff --git a/include/boost/intrusive/unordered_set.hpp b/include/boost/intrusive/unordered_set.hpp index d957f4a..4ba9d4e 100644 --- a/include/boost/intrusive/unordered_set.hpp +++ b/include/boost/intrusive/unordered_set.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 @@ -61,13 +61,14 @@ namespace intrusive { #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class unordered_set_impl + : public hashtable_impl { /// @cond private: - typedef hashtable_impl table_type; + typedef hashtable_impl table_type; //! This class is //! movable @@ -102,11 +103,6 @@ class unordered_set_impl typedef typename implementation_defined::const_node_ptr const_node_ptr; typedef typename implementation_defined::node_algorithms node_algorithms; - /// @cond - private: - table_type table_; - /// @endcond - public: //! Requires: buckets must not be being used by any other resource. @@ -126,7 +122,7 @@ class unordered_set_impl , const hasher & hash_func = hasher() , const key_equal &equal_func = key_equal() , const value_traits &v_traits = value_traits()) - : table_(b_traits, hash_func, equal_func, v_traits) + : table_type(b_traits, hash_func, equal_func, v_traits) {} //! Requires: buckets must not be being used by any other resource @@ -151,19 +147,19 @@ class unordered_set_impl , const hasher & hash_func = hasher() , const key_equal &equal_func = key_equal() , const value_traits &v_traits = value_traits()) - : table_(b_traits, hash_func, equal_func, v_traits) - { table_.insert_unique(b, e); } + : table_type(b_traits, hash_func, equal_func, v_traits) + { table_type::insert_unique(b, e); } //! Effects: to-do //! unordered_set_impl(BOOST_RV_REF(unordered_set_impl) x) - : table_(::boost::move(x.table_)) + : table_type(::boost::move(static_cast(x))) {} //! Effects: to-do //! unordered_set_impl& operator=(BOOST_RV_REF(unordered_set_impl) x) - { table_ = ::boost::move(x.table_); return *this; } + { return static_cast(table_type::operator=(::boost::move(static_cast(x)))); } //! Effects: Detaches all elements from this. The objects in the unordered_set //! are not deleted (i.e. no destructors are called). @@ -175,6 +171,7 @@ class unordered_set_impl ~unordered_set_impl() {} + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! Effects: Returns an iterator pointing to the beginning of the unordered_set. //! //! Complexity: Constant time if `cache_begin<>` is true. Amortized @@ -182,7 +179,7 @@ class unordered_set_impl //! //! Throws: Nothing. iterator begin() - { return table_.begin(); } + { return table_type::begin(); } //! Effects: Returns a const_iterator pointing to the beginning //! of the unordered_set. @@ -192,7 +189,7 @@ class unordered_set_impl //! //! Throws: Nothing. const_iterator begin() const - { return table_.begin(); } + { return table_type::begin(); } //! Effects: Returns a const_iterator pointing to the beginning //! of the unordered_set. @@ -202,7 +199,7 @@ class unordered_set_impl //! //! Throws: Nothing. const_iterator cbegin() const - { return table_.cbegin(); } + { return table_type::cbegin(); } //! Effects: Returns an iterator pointing to the end of the unordered_set. //! @@ -210,7 +207,7 @@ class unordered_set_impl //! //! Throws: Nothing. iterator end() - { return table_.end(); } + { return table_type::end(); } //! Effects: Returns a const_iterator pointing to the end of the unordered_set. //! @@ -218,7 +215,7 @@ class unordered_set_impl //! //! Throws: Nothing. const_iterator end() const - { return table_.end(); } + { return table_type::end(); } //! Effects: Returns a const_iterator pointing to the end of the unordered_set. //! @@ -226,7 +223,7 @@ class unordered_set_impl //! //! Throws: Nothing. const_iterator cend() const - { return table_.cend(); } + { return table_type::cend(); } //! Effects: Returns the hasher object used by the unordered_set. //! @@ -234,7 +231,7 @@ class unordered_set_impl //! //! Throws: If hasher copy-constructor throws. hasher hash_function() const - { return table_.hash_function(); } + { return table_type::hash_function(); } //! Effects: Returns the key_equal object used by the unordered_set. //! @@ -242,7 +239,7 @@ class unordered_set_impl //! //! Throws: If key_equal copy-constructor throws. key_equal key_eq() const - { return table_.key_eq(); } + { return table_type::key_eq(); } //! Effects: Returns true if the container is empty. //! @@ -252,7 +249,7 @@ class unordered_set_impl //! //! Throws: Nothing. bool empty() const - { return table_.empty(); } + { return table_type::empty(); } //! Effects: Returns the number of elements stored in the unordered_set. //! @@ -261,7 +258,7 @@ class unordered_set_impl //! //! Throws: Nothing. size_type size() const - { return table_.size(); } + { return table_type::size(); } //! Requires: the hasher and the equality function unqualified swap //! call should not throw. @@ -274,7 +271,7 @@ class unordered_set_impl //! Throws: If the swap() call for the comparison or hash functors //! found using ADL throw. Basic guarantee. void swap(unordered_set_impl& other) - { table_.swap(other.table_); } + { table_type::swap(other.table_); } //! Requires: Disposer::operator()(pointer) shouldn't throw. //! Cloner should yield to nodes that compare equal and produce the same @@ -297,7 +294,9 @@ class unordered_set_impl //! throws. Basic guarantee. template void clone_from(const unordered_set_impl &src, Cloner cloner, Disposer disposer) - { table_.clone_from(src.table_, cloner, disposer); } + { table_type::clone_from(src.table_, cloner, disposer); } + + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! Requires: value must be an lvalue //! @@ -316,7 +315,7 @@ class unordered_set_impl //! Note: Does not affect the validity of iterators and references. //! No copy-constructors are called. std::pair insert(reference value) - { return table_.insert_unique(value); } + { return table_type::insert_unique(value); } //! Requires: Dereferencing iterator must yield an lvalue //! of type value_type. @@ -332,7 +331,7 @@ class unordered_set_impl //! No copy-constructors are called. template void insert(Iterator b, Iterator e) - { table_.insert_unique(b, e); } + { table_type::insert_unique(b, e); } //! Requires: "hasher" must be a hash function that induces //! the same hash values as the stored hasher. The difference is that @@ -372,7 +371,7 @@ class unordered_set_impl template std::pair insert_check (const KeyType &key, KeyHasher hasher, KeyValueEqual key_value_equal, insert_commit_data &commit_data) - { return table_.insert_unique_check(key, hasher, key_value_equal, commit_data); } + { return table_type::insert_unique_check(key, hasher, key_value_equal, commit_data); } //! Requires: value must be an lvalue of type value_type. commit_data //! must have been obtained from a previous call to "insert_check". @@ -394,7 +393,9 @@ class unordered_set_impl //! //! After a successful rehashing insert_commit_data remains valid. iterator insert_commit(reference value, const insert_commit_data &commit_data) - { return table_.insert_unique_commit(value, commit_data); } + { return table_type::insert_unique_commit(value, commit_data); } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! Effects: Erases the element pointed to by i. //! @@ -405,7 +406,7 @@ class unordered_set_impl //! Note: Invalidates the iterators (but not the references) //! to the erased element. No destructors are called. void erase(const_iterator i) - { table_.erase(i); } + { table_type::erase(i); } //! Effects: Erases the range pointed to by b end e. //! @@ -417,7 +418,7 @@ class unordered_set_impl //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. void erase(const_iterator b, const_iterator e) - { table_.erase(b, e); } + { table_type::erase(b, e); } //! Effects: Erases all the elements with the given value. //! @@ -431,7 +432,7 @@ class unordered_set_impl //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. size_type erase(const_reference value) - { return table_.erase(value); } + { return table_type::erase(value); } //! Requires: "hasher" must be a hash function that induces //! the same hash values as the stored hasher. The difference is that @@ -455,7 +456,7 @@ class unordered_set_impl //! to the erased elements. No destructors are called. template size_type erase(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) - { return table_.erase(key, hash_func, equal_func); } + { return table_type::erase(key, hash_func, equal_func); } //! Requires: Disposer::operator()(pointer) shouldn't throw. //! @@ -474,7 +475,7 @@ class unordered_set_impl , typename detail::enable_if_c::value >::type * = 0 /// @endcond ) - { table_.erase_and_dispose(i, disposer); } + { table_type::erase_and_dispose(i, disposer); } //! Requires: Disposer::operator()(pointer) shouldn't throw. //! @@ -490,7 +491,7 @@ class unordered_set_impl //! to the erased elements. template void erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer) - { table_.erase_and_dispose(b, e, disposer); } + { table_type::erase_and_dispose(b, e, disposer); } //! Requires: Disposer::operator()(pointer) shouldn't throw. //! @@ -508,7 +509,7 @@ class unordered_set_impl //! to the erased elements. No destructors are called. template size_type erase_and_dispose(const_reference value, Disposer disposer) - { return table_.erase_and_dispose(value, disposer); } + { return table_type::erase_and_dispose(value, disposer); } //! Requires: Disposer::operator()(pointer) shouldn't throw. //! @@ -527,7 +528,7 @@ class unordered_set_impl //! to the erased elements. template size_type erase_and_dispose(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func, Disposer disposer) - { return table_.erase_and_dispose(key, hash_func, equal_func, disposer); } + { return table_type::erase_and_dispose(key, hash_func, equal_func, disposer); } //! Effects: Erases all of the elements. //! @@ -539,7 +540,7 @@ class unordered_set_impl //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. void clear() - { return table_.clear(); } + { return table_type::clear(); } //! Requires: Disposer::operator()(pointer) shouldn't throw. //! @@ -554,7 +555,7 @@ class unordered_set_impl //! to the erased elements. No destructors are called. template void clear_and_dispose(Disposer disposer) - { return table_.clear_and_dispose(disposer); } + { return table_type::clear_and_dispose(disposer); } //! Effects: Returns the number of contained elements with the given value //! @@ -562,7 +563,7 @@ class unordered_set_impl //! //! Throws: If the internal hasher or the equality functor throws. size_type count(const_reference value) const - { return table_.find(value) != end(); } + { return table_type::find(value) != end(); } //! Requires: "hash_func" must be a hash function that induces //! the same hash values as the stored hasher. The difference is that @@ -579,7 +580,7 @@ class unordered_set_impl //! Throws: If hash_func or equal_func throw. template size_type count(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) const - { return table_.find(key, hash_func, equal_func) != end(); } + { return table_type::find(key, hash_func, equal_func) != end(); } //! Effects: Finds an iterator to the first element is equal to //! "value" or end() if that element does not exist. @@ -588,7 +589,7 @@ class unordered_set_impl //! //! Throws: If the internal hasher or the equality functor throws. iterator find(const_reference value) - { return table_.find(value); } + { return table_type::find(value); } //! Requires: "hash_func" must be a hash function that induces //! the same hash values as the stored hasher. The difference is that @@ -611,7 +612,7 @@ class unordered_set_impl //! key type. Usually this key is part of the value_type. template iterator find(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) - { return table_.find(key, hash_func, equal_func); } + { return table_type::find(key, hash_func, equal_func); } //! Effects: Finds a const_iterator to the first element whose key is //! "key" or end() if that element does not exist. @@ -620,7 +621,7 @@ class unordered_set_impl //! //! Throws: If the internal hasher or the equality functor throws. const_iterator find(const_reference value) const - { return table_.find(value); } + { return table_type::find(value); } //! Requires: "hash_func" must be a hash function that induces //! the same hash values as the stored hasher. The difference is that @@ -643,7 +644,7 @@ class unordered_set_impl //! key type. Usually this key is part of the value_type. template const_iterator find(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) const - { return table_.find(key, hash_func, equal_func); } + { return table_type::find(key, hash_func, equal_func); } //! Effects: Returns a range containing all elements with values equivalent //! to value. Returns std::make_pair(this->end(), this->end()) if no such @@ -653,7 +654,7 @@ class unordered_set_impl //! //! Throws: If the internal hasher or the equality functor throws. std::pair equal_range(const_reference value) - { return table_.equal_range(value); } + { return table_type::equal_range(value); } //! Requires: "hash_func" must be a hash function that induces //! the same hash values as the stored hasher. The difference is that @@ -677,7 +678,7 @@ class unordered_set_impl //! key type. Usually this key is part of the value_type. template std::pair equal_range(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) - { return table_.equal_range(key, hash_func, equal_func); } + { return table_type::equal_range(key, hash_func, equal_func); } //! Effects: Returns a range containing all elements with values equivalent //! to value. Returns std::make_pair(this->end(), this->end()) if no such @@ -688,7 +689,7 @@ class unordered_set_impl //! Throws: If the internal hasher or the equality functor throws. std::pair equal_range(const_reference value) const - { return table_.equal_range(value); } + { return table_type::equal_range(value); } //! Requires: "hash_func" must be a hash function that induces //! the same hash values as the stored hasher. The difference is that @@ -713,7 +714,7 @@ class unordered_set_impl template std::pair equal_range(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) const - { return table_.equal_range(key, hash_func, equal_func); } + { return table_type::equal_range(key, hash_func, equal_func); } //! Requires: value must be an lvalue and shall be in a unordered_set of //! appropriate type. Otherwise the behavior is undefined. @@ -725,7 +726,7 @@ class unordered_set_impl //! //! Throws: If the internal hash function throws. iterator iterator_to(reference value) - { return table_.iterator_to(value); } + { return table_type::iterator_to(value); } //! Requires: value must be an lvalue and shall be in a unordered_set of //! appropriate type. Otherwise the behavior is undefined. @@ -737,7 +738,7 @@ class unordered_set_impl //! //! Throws: If the internal hash function throws. const_iterator iterator_to(const_reference value) const - { return table_.iterator_to(value); } + { return table_type::iterator_to(value); } //! Requires: value must be an lvalue and shall be in a unordered_set of //! appropriate type. Otherwise the behavior is undefined. @@ -779,7 +780,7 @@ class unordered_set_impl //! //! Throws: Nothing. local_iterator local_iterator_to(reference value) - { return table_.local_iterator_to(value); } + { return table_type::local_iterator_to(value); } //! Requires: value must be an lvalue and shall be in a unordered_set of //! appropriate type. Otherwise the behavior is undefined. @@ -791,7 +792,7 @@ class unordered_set_impl //! //! Throws: Nothing. const_local_iterator local_iterator_to(const_reference value) const - { return table_.local_iterator_to(value); } + { return table_type::local_iterator_to(value); } //! Effects: Returns the number of buckets passed in the constructor //! or the last rehash function. @@ -800,7 +801,7 @@ class unordered_set_impl //! //! Throws: Nothing. size_type bucket_count() const - { return table_.bucket_count(); } + { return table_type::bucket_count(); } //! Requires: n is in the range [0, this->bucket_count()). //! @@ -810,7 +811,7 @@ class unordered_set_impl //! //! Throws: Nothing. size_type bucket_size(size_type n) const - { return table_.bucket_size(n); } + { return table_type::bucket_size(n); } //! Effects: Returns the index of the bucket in which elements //! with keys equivalent to k would be found, if any such element existed. @@ -821,7 +822,7 @@ class unordered_set_impl //! //! Note: the return value is in the range [0, this->bucket_count()). size_type bucket(const value_type& k) const - { return table_.bucket(k); } + { return table_type::bucket(k); } //! Requires: "hash_func" must be a hash function that induces //! the same hash values as the stored hasher. The difference is that @@ -837,7 +838,7 @@ class unordered_set_impl //! Note: the return value is in the range [0, this->bucket_count()). template size_type bucket(const KeyType& k, KeyHasher hash_func) const - { return table_.bucket(k, hash_func); } + { return table_type::bucket(k, hash_func); } //! Effects: Returns the bucket array pointer passed in the constructor //! or the last rehash function. @@ -846,7 +847,7 @@ class unordered_set_impl //! //! Throws: Nothing. bucket_ptr bucket_pointer() const - { return table_.bucket_pointer(); } + { return table_type::bucket_pointer(); } //! Requires: n is in the range [0, this->bucket_count()). //! @@ -860,7 +861,7 @@ class unordered_set_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 table_.begin(n); } + { return table_type::begin(n); } //! Requires: n is in the range [0, this->bucket_count()). //! @@ -874,7 +875,7 @@ class unordered_set_impl //! Note: [this->begin(n), this->end(n)) is a valid range //! containing all of the elements in the nth bucket. const_local_iterator begin(size_type n) const - { return table_.begin(n); } + { return table_type::begin(n); } //! Requires: n is in the range [0, this->bucket_count()). //! @@ -888,7 +889,7 @@ class unordered_set_impl //! Note: [this->begin(n), this->end(n)) is a valid range //! containing all of the elements in the nth bucket. const_local_iterator cbegin(size_type n) const - { return table_.cbegin(n); } + { return table_type::cbegin(n); } //! Requires: n is in the range [0, this->bucket_count()). //! @@ -902,7 +903,7 @@ class unordered_set_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 table_.end(n); } + { return table_type::end(n); } //! Requires: n is in the range [0, this->bucket_count()). //! @@ -916,7 +917,7 @@ class unordered_set_impl //! Note: [this->begin(n), this->end(n)) is a valid range //! containing all of the elements in the nth bucket. const_local_iterator end(size_type n) const - { return table_.end(n); } + { return table_type::end(n); } //! Requires: n is in the range [0, this->bucket_count()). //! @@ -930,7 +931,7 @@ class unordered_set_impl //! Note: [this->begin(n), this->end(n)) is a valid range //! containing all of the elements in the nth bucket. const_local_iterator cend(size_type n) const - { return table_.cend(n); } + { return table_type::cend(n); } //! Requires: new_buckets must be a pointer to a new bucket array //! or the same as the old bucket array. new_size is the length of the @@ -946,7 +947,7 @@ class unordered_set_impl //! //! Throws: If the hasher functor throws. Basic guarantee. void rehash(const bucket_traits &new_bucket_traits) - { table_.rehash(new_bucket_traits); } + { table_type::rehash(new_bucket_traits); } //! Requires: //! @@ -958,11 +959,11 @@ class unordered_set_impl //! //! Note: this method is only available if incremental option is activated. bool incremental_rehash(bool grow = true) - { return table_.incremental_rehash(grow); } + { return table_type::incremental_rehash(grow); } //! Note: this method is only available if incremental option is activated. bool incremental_rehash(const bucket_traits &new_bucket_traits) - { return table_.incremental_rehash(new_bucket_traits); } + { return table_type::incremental_rehash(new_bucket_traits); } //! Requires: //! @@ -972,7 +973,7 @@ class unordered_set_impl //! //! Throws: size_type split_count() const - { return table_.split_count(); } + { return table_type::split_count(); } //! Effects: Returns the nearest new bucket count optimized for //! the container that is bigger than n. This suggestion can be used @@ -997,6 +998,8 @@ class unordered_set_impl //! Throws: Nothing. static size_type suggested_lower_bucket_count(size_type n) { return table_type::suggested_lower_bucket_count(n); } + + #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED }; //! Helper metafunction to define an \c unordered_set that yields to the same type when the @@ -1004,26 +1007,45 @@ class unordered_set_impl #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else -template #endif struct make_unordered_set { /// @cond + typedef typename pack_options + < hashtable_defaults, + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3, O4, O5, O6, O7, O8, O9, O10 + #else + Options... + #endif + >::type packed_options; + + typedef typename detail::get_value_traits + ::type value_traits; + + typedef typename make_real_bucket_traits + ::type real_bucket_traits; + typedef unordered_set_impl - < typename make_hashtable_opt - ::type + < value_traits + , typename packed_options::hash + , typename packed_options::equal + , typename packed_options::size_type + , real_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) + | (std::size_t(packed_options::cache_begin)*hash_bool_flags::cache_begin_pos) + | (std::size_t(packed_options::compare_hash)*hash_bool_flags::compare_hash_pos) + | (std::size_t(packed_options::incremental)*hash_bool_flags::incremental_pos) > implementation_defined; + /// @endcond typedef implementation_defined type; }; @@ -1089,7 +1111,7 @@ class unordered_set {} unordered_set& operator=(BOOST_RV_REF(unordered_set) x) - { this->Base::operator=(::boost::move(static_cast(x))); return *this; } + { return static_cast(this->Base::operator=(::boost::move(static_cast(x)))); } }; #endif @@ -1133,13 +1155,14 @@ class unordered_set #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template #else -template +template #endif class unordered_multiset_impl + : public hashtable_impl { /// @cond private: - typedef hashtable_impl table_type; + typedef hashtable_impl table_type; /// @endcond //Movable @@ -1173,11 +1196,6 @@ class unordered_multiset_impl typedef typename implementation_defined::const_node_ptr const_node_ptr; typedef typename implementation_defined::node_algorithms node_algorithms; - /// @cond - private: - table_type table_; - /// @endcond - public: //! Requires: buckets must not be being used by any other resource. @@ -1197,7 +1215,7 @@ class unordered_multiset_impl , const hasher & hash_func = hasher() , const key_equal &equal_func = key_equal() , const value_traits &v_traits = value_traits()) - : table_(b_traits, hash_func, equal_func, v_traits) + : table_type(b_traits, hash_func, equal_func, v_traits) {} //! Requires: buckets must not be being used by any other resource @@ -1222,19 +1240,19 @@ class unordered_multiset_impl , const hasher & hash_func = hasher() , const key_equal &equal_func = key_equal() , const value_traits &v_traits = value_traits()) - : table_(b_traits, hash_func, equal_func, v_traits) - { table_.insert_equal(b, e); } + : table_type(b_traits, hash_func, equal_func, v_traits) + { table_type::insert_equal(b, e); } //! Effects: to-do //! unordered_multiset_impl(BOOST_RV_REF(unordered_multiset_impl) x) - : table_(::boost::move(x.table_)) + : table_type(::boost::move(static_cast(x))) {} //! Effects: to-do //! unordered_multiset_impl& operator=(BOOST_RV_REF(unordered_multiset_impl) x) - { table_ = ::boost::move(x.table_); return *this; } + { return static_cast(table_type::operator=(::boost::move(static_cast(x)))); } //! Effects: Detaches all elements from this. The objects in the unordered_multiset //! are not deleted (i.e. no destructors are called). @@ -1246,6 +1264,8 @@ class unordered_multiset_impl ~unordered_multiset_impl() {} + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! Effects: Returns an iterator pointing to the beginning of the unordered_multiset. //! //! Complexity: Constant time if `cache_begin<>` is true. Amortized @@ -1253,7 +1273,7 @@ class unordered_multiset_impl //! //! Throws: Nothing. iterator begin() - { return table_.begin(); } + { return table_type::begin(); } //! Effects: Returns a const_iterator pointing to the beginning //! of the unordered_multiset. @@ -1263,7 +1283,7 @@ class unordered_multiset_impl //! //! Throws: Nothing. const_iterator begin() const - { return table_.begin(); } + { return table_type::begin(); } //! Effects: Returns a const_iterator pointing to the beginning //! of the unordered_multiset. @@ -1273,7 +1293,7 @@ class unordered_multiset_impl //! //! Throws: Nothing. const_iterator cbegin() const - { return table_.cbegin(); } + { return table_type::cbegin(); } //! Effects: Returns an iterator pointing to the end of the unordered_multiset. //! @@ -1281,7 +1301,7 @@ class unordered_multiset_impl //! //! Throws: Nothing. iterator end() - { return table_.end(); } + { return table_type::end(); } //! Effects: Returns a const_iterator pointing to the end of the unordered_multiset. //! @@ -1289,7 +1309,7 @@ class unordered_multiset_impl //! //! Throws: Nothing. const_iterator end() const - { return table_.end(); } + { return table_type::end(); } //! Effects: Returns a const_iterator pointing to the end of the unordered_multiset. //! @@ -1297,7 +1317,7 @@ class unordered_multiset_impl //! //! Throws: Nothing. const_iterator cend() const - { return table_.cend(); } + { return table_type::cend(); } //! Effects: Returns the hasher object used by the unordered_set. //! @@ -1305,7 +1325,7 @@ class unordered_multiset_impl //! //! Throws: If hasher copy-constructor throws. hasher hash_function() const - { return table_.hash_function(); } + { return table_type::hash_function(); } //! Effects: Returns the key_equal object used by the unordered_multiset. //! @@ -1313,7 +1333,7 @@ class unordered_multiset_impl //! //! Throws: If key_equal copy-constructor throws. key_equal key_eq() const - { return table_.key_eq(); } + { return table_type::key_eq(); } //! Effects: Returns true if the container is empty. //! @@ -1323,7 +1343,7 @@ class unordered_multiset_impl //! //! Throws: Nothing. bool empty() const - { return table_.empty(); } + { return table_type::empty(); } //! Effects: Returns the number of elements stored in the unordered_multiset. //! @@ -1332,7 +1352,7 @@ class unordered_multiset_impl //! //! Throws: Nothing. size_type size() const - { return table_.size(); } + { return table_type::size(); } //! Requires: the hasher and the equality function unqualified swap //! call should not throw. @@ -1346,7 +1366,7 @@ class unordered_multiset_impl //! Throws: If the swap() call for the comparison or hash functors //! found using ADL throw. Basic guarantee. void swap(unordered_multiset_impl& other) - { table_.swap(other.table_); } + { table_type::swap(other.table_); } //! Requires: Disposer::operator()(pointer) shouldn't throw. //! Cloner should yield to nodes that compare equal and produce the same @@ -1369,7 +1389,9 @@ class unordered_multiset_impl //! throws. Basic guarantee. template void clone_from(const unordered_multiset_impl &src, Cloner cloner, Disposer disposer) - { table_.clone_from(src.table_, cloner, disposer); } + { table_type::clone_from(src.table_, cloner, disposer); } + + #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! Requires: value must be an lvalue //! @@ -1384,7 +1406,7 @@ class unordered_multiset_impl //! Note: Does not affect the validity of iterators and references. //! No copy-constructors are called. iterator insert(reference value) - { return table_.insert_equal(value); } + { return table_type::insert_equal(value); } //! Requires: Dereferencing iterator must yield an lvalue //! of type value_type. @@ -1400,7 +1422,9 @@ class unordered_multiset_impl //! No copy-constructors are called. template void insert(Iterator b, Iterator e) - { table_.insert_equal(b, e); } + { table_type::insert_equal(b, e); } + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED //! Effects: Erases the element pointed to by i. //! @@ -1411,7 +1435,7 @@ class unordered_multiset_impl //! Note: Invalidates the iterators (but not the references) //! to the erased element. No destructors are called. void erase(const_iterator i) - { table_.erase(i); } + { table_type::erase(i); } //! Effects: Erases the range pointed to by b end e. //! @@ -1423,7 +1447,7 @@ class unordered_multiset_impl //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. void erase(const_iterator b, const_iterator e) - { table_.erase(b, e); } + { table_type::erase(b, e); } //! Effects: Erases all the elements with the given value. //! @@ -1437,7 +1461,7 @@ class unordered_multiset_impl //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. size_type erase(const_reference value) - { return table_.erase(value); } + { return table_type::erase(value); } //! Requires: "hash_func" must be a hash function that induces //! the same hash values as the stored hasher. The difference is that @@ -1462,7 +1486,7 @@ class unordered_multiset_impl //! to the erased elements. No destructors are called. template size_type erase(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) - { return table_.erase(key, hash_func, equal_func); } + { return table_type::erase(key, hash_func, equal_func); } //! Requires: Disposer::operator()(pointer) shouldn't throw. //! @@ -1481,7 +1505,7 @@ class unordered_multiset_impl , typename detail::enable_if_c::value >::type * = 0 /// @endcond ) - { table_.erase_and_dispose(i, disposer); } + { table_type::erase_and_dispose(i, disposer); } #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template @@ -1503,7 +1527,7 @@ class unordered_multiset_impl //! to the erased elements. template void erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer) - { table_.erase_and_dispose(b, e, disposer); } + { table_type::erase_and_dispose(b, e, disposer); } //! Requires: Disposer::operator()(pointer) shouldn't throw. //! @@ -1521,7 +1545,7 @@ class unordered_multiset_impl //! to the erased elements. No destructors are called. template size_type erase_and_dispose(const_reference value, Disposer disposer) - { return table_.erase_and_dispose(value, disposer); } + { return table_type::erase_and_dispose(value, disposer); } //! Requires: Disposer::operator()(pointer) shouldn't throw. //! @@ -1540,7 +1564,7 @@ class unordered_multiset_impl //! to the erased elements. template size_type erase_and_dispose(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func, Disposer disposer) - { return table_.erase_and_dispose(key, hash_func, equal_func, disposer); } + { return table_type::erase_and_dispose(key, hash_func, equal_func, disposer); } //! Effects: Erases all the elements of the container. //! @@ -1552,7 +1576,7 @@ class unordered_multiset_impl //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. void clear() - { return table_.clear(); } + { return table_type::clear(); } //! Requires: Disposer::operator()(pointer) shouldn't throw. //! @@ -1567,7 +1591,7 @@ class unordered_multiset_impl //! to the erased elements. No destructors are called. template void clear_and_dispose(Disposer disposer) - { return table_.clear_and_dispose(disposer); } + { return table_type::clear_and_dispose(disposer); } //! Effects: Returns the number of contained elements with the given key //! @@ -1575,7 +1599,7 @@ class unordered_multiset_impl //! //! Throws: If the internal hasher or the equality functor throws. size_type count(const_reference value) const - { return table_.count(value); } + { return table_type::count(value); } //! Requires: "hash_func" must be a hash function that induces //! the same hash values as the stored hasher. The difference is that @@ -1592,7 +1616,7 @@ class unordered_multiset_impl //! Throws: If the internal hasher or the equality functor throws. template size_type count(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) const - { return table_.count(key, hash_func, equal_func); } + { return table_type::count(key, hash_func, equal_func); } //! Effects: Finds an iterator to the first element whose value is //! "value" or end() if that element does not exist. @@ -1601,7 +1625,7 @@ class unordered_multiset_impl //! //! Throws: If the internal hasher or the equality functor throws. iterator find(const_reference value) - { return table_.find(value); } + { return table_type::find(value); } //! Requires: "hash_func" must be a hash function that induces //! the same hash values as the stored hasher. The difference is that @@ -1624,7 +1648,7 @@ class unordered_multiset_impl //! key type. Usually this key is part of the value_type. template iterator find(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) - { return table_.find(key, hash_func, equal_func); } + { return table_type::find(key, hash_func, equal_func); } //! Effects: Finds a const_iterator to the first element whose key is //! "key" or end() if that element does not exist. @@ -1633,7 +1657,7 @@ class unordered_multiset_impl //! //! Throws: If the internal hasher or the equality functor throws. const_iterator find(const_reference value) const - { return table_.find(value); } + { return table_type::find(value); } //! Requires: "hash_func" must be a hash function that induces //! the same hash values as the stored hasher. The difference is that @@ -1656,7 +1680,7 @@ class unordered_multiset_impl //! key type. Usually this key is part of the value_type. template const_iterator find(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) const - { return table_.find(key, hash_func, equal_func); } + { return table_type::find(key, hash_func, equal_func); } //! Effects: Returns a range containing all elements with values equivalent //! to value. Returns std::make_pair(this->end(), this->end()) if no such @@ -1666,7 +1690,7 @@ class unordered_multiset_impl //! //! Throws: If the internal hasher or the equality functor throws. std::pair equal_range(const_reference value) - { return table_.equal_range(value); } + { return table_type::equal_range(value); } //! Requires: "hash_func" must be a hash function that induces //! the same hash values as the stored hasher. The difference is that @@ -1691,7 +1715,7 @@ class unordered_multiset_impl template std::pair equal_range (const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) - { return table_.equal_range(key, hash_func, equal_func); } + { return table_type::equal_range(key, hash_func, equal_func); } //! Effects: Returns a range containing all elements with values equivalent //! to value. Returns std::make_pair(this->end(), this->end()) if no such @@ -1702,7 +1726,7 @@ class unordered_multiset_impl //! Throws: If the internal hasher or the equality functor throws. std::pair equal_range(const_reference value) const - { return table_.equal_range(value); } + { return table_type::equal_range(value); } //! Requires: "hash_func" must be a hash function that induces //! the same hash values as the stored hasher. The difference is that @@ -1727,7 +1751,7 @@ class unordered_multiset_impl template std::pair equal_range(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) const - { return table_.equal_range(key, hash_func, equal_func); } + { return table_type::equal_range(key, hash_func, equal_func); } //! Requires: value must be an lvalue and shall be in a unordered_multiset of //! appropriate type. Otherwise the behavior is undefined. @@ -1739,7 +1763,7 @@ class unordered_multiset_impl //! //! Throws: If the hash function throws. iterator iterator_to(reference value) - { return table_.iterator_to(value); } + { return table_type::iterator_to(value); } //! Requires: value must be an lvalue and shall be in a unordered_multiset of //! appropriate type. Otherwise the behavior is undefined. @@ -1751,7 +1775,7 @@ class unordered_multiset_impl //! //! Throws: If the hash function throws. const_iterator iterator_to(const_reference value) const - { return table_.iterator_to(value); } + { return table_type::iterator_to(value); } //! Requires: value must be an lvalue and shall be in a unordered_set of //! appropriate type. Otherwise the behavior is undefined. @@ -1793,7 +1817,7 @@ class unordered_multiset_impl //! //! Throws: Nothing. local_iterator local_iterator_to(reference value) - { return table_.local_iterator_to(value); } + { return table_type::local_iterator_to(value); } //! Requires: value must be an lvalue and shall be in a unordered_set of //! appropriate type. Otherwise the behavior is undefined. @@ -1805,7 +1829,7 @@ class unordered_multiset_impl //! //! Throws: Nothing. const_local_iterator local_iterator_to(const_reference value) const - { return table_.local_iterator_to(value); } + { return table_type::local_iterator_to(value); } //! Effects: Returns the number of buckets passed in the constructor //! or the last rehash function. @@ -1814,7 +1838,7 @@ class unordered_multiset_impl //! //! Throws: Nothing. size_type bucket_count() const - { return table_.bucket_count(); } + { return table_type::bucket_count(); } //! Requires: n is in the range [0, this->bucket_count()). //! @@ -1824,7 +1848,7 @@ class unordered_multiset_impl //! //! Throws: Nothing. size_type bucket_size(size_type n) const - { return table_.bucket_size(n); } + { return table_type::bucket_size(n); } //! Effects: Returns the index of the bucket in which elements //! with keys equivalent to k would be found, if any such element existed. @@ -1835,7 +1859,7 @@ class unordered_multiset_impl //! //! Note: the return value is in the range [0, this->bucket_count()). size_type bucket(const value_type& k) const - { return table_.bucket(k); } + { return table_type::bucket(k); } //! Requires: "hash_func" must be a hash function that induces //! the same hash values as the stored hasher. The difference is that @@ -1851,7 +1875,7 @@ class unordered_multiset_impl //! Note: the return value is in the range [0, this->bucket_count()). template size_type bucket(const KeyType& k, const KeyHasher &hash_func) const - { return table_.bucket(k, hash_func); } + { return table_type::bucket(k, hash_func); } //! Effects: Returns the bucket array pointer passed in the constructor //! or the last rehash function. @@ -1860,7 +1884,7 @@ class unordered_multiset_impl //! //! Throws: Nothing. bucket_ptr bucket_pointer() const - { return table_.bucket_pointer(); } + { return table_type::bucket_pointer(); } //! Requires: n is in the range [0, this->bucket_count()). //! @@ -1874,7 +1898,7 @@ class unordered_multiset_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 table_.begin(n); } + { return table_type::begin(n); } //! Requires: n is in the range [0, this->bucket_count()). //! @@ -1888,7 +1912,7 @@ class unordered_multiset_impl //! Note: [this->begin(n), this->end(n)) is a valid range //! containing all of the elements in the nth bucket. const_local_iterator begin(size_type n) const - { return table_.begin(n); } + { return table_type::begin(n); } //! Requires: n is in the range [0, this->bucket_count()). //! @@ -1902,7 +1926,7 @@ class unordered_multiset_impl //! Note: [this->begin(n), this->end(n)) is a valid range //! containing all of the elements in the nth bucket. const_local_iterator cbegin(size_type n) const - { return table_.cbegin(n); } + { return table_type::cbegin(n); } //! Requires: n is in the range [0, this->bucket_count()). //! @@ -1916,7 +1940,7 @@ class unordered_multiset_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 table_.end(n); } + { return table_type::end(n); } //! Requires: n is in the range [0, this->bucket_count()). //! @@ -1930,7 +1954,7 @@ class unordered_multiset_impl //! Note: [this->begin(n), this->end(n)) is a valid range //! containing all of the elements in the nth bucket. const_local_iterator end(size_type n) const - { return table_.end(n); } + { return table_type::end(n); } //! Requires: n is in the range [0, this->bucket_count()). //! @@ -1944,7 +1968,7 @@ class unordered_multiset_impl //! Note: [this->begin(n), this->end(n)) is a valid range //! containing all of the elements in the nth bucket. const_local_iterator cend(size_type n) const - { return table_.cend(n); } + { return table_type::cend(n); } //! Requires: new_buckets must be a pointer to a new bucket array //! or the same as the old bucket array. new_size is the length of the @@ -1960,7 +1984,7 @@ class unordered_multiset_impl //! //! Throws: If the hasher functor throws. void rehash(const bucket_traits &new_bucket_traits) - { table_.rehash(new_bucket_traits); } + { table_type::rehash(new_bucket_traits); } //! Requires: //! @@ -1972,11 +1996,11 @@ class unordered_multiset_impl //! //! Note: this method is only available if incremental option is activated. bool incremental_rehash(bool grow = true) - { return table_.incremental_rehash(grow); } + { return table_type::incremental_rehash(grow); } //! Note: this method is only available if incremental option is activated. bool incremental_rehash(const bucket_traits &new_bucket_traits) - { return table_.incremental_rehash(new_bucket_traits); } + { return table_type::incremental_rehash(new_bucket_traits); } //! Requires: //! @@ -1986,7 +2010,7 @@ class unordered_multiset_impl //! //! Throws: size_type split_count() const - { return table_.split_count(); } + { return table_type::split_count(); } //! Effects: Returns the nearest new bucket count optimized for //! the container that is bigger than n. This suggestion can be used @@ -2011,6 +2035,8 @@ class unordered_multiset_impl //! Throws: Nothing. static size_type suggested_lower_bucket_count(size_type n) { return table_type::suggested_lower_bucket_count(n); } + + #endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED }; //! Helper metafunction to define an \c unordered_multiset that yields to the same type when the @@ -2018,26 +2044,45 @@ class unordered_multiset_impl #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else -template #endif struct make_unordered_multiset { /// @cond + typedef typename pack_options + < hashtable_defaults, + #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + O1, O2, O3, O4, O5, O6, O7, O8, O9, O10 + #else + Options... + #endif + >::type packed_options; + + typedef typename detail::get_value_traits + ::type value_traits; + + typedef typename make_real_bucket_traits + ::type real_bucket_traits; + typedef unordered_multiset_impl - < typename make_hashtable_opt - ::type + < value_traits + , typename packed_options::hash + , typename packed_options::equal + , typename packed_options::size_type + , real_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) + | (std::size_t(packed_options::cache_begin)*hash_bool_flags::cache_begin_pos) + | (std::size_t(packed_options::compare_hash)*hash_bool_flags::compare_hash_pos) + | (std::size_t(packed_options::incremental)*hash_bool_flags::incremental_pos) > implementation_defined; + /// @endcond typedef implementation_defined type; }; @@ -2102,7 +2147,7 @@ class unordered_multiset {} unordered_multiset& operator=(BOOST_RV_REF(unordered_multiset) x) - { this->Base::operator=(::boost::move(static_cast(x))); return *this; } + { return static_cast(this->Base::operator=(::boost::move(static_cast(x)))); } }; #endif diff --git a/include/boost/intrusive/unordered_set_hook.hpp b/include/boost/intrusive/unordered_set_hook.hpp index c7e95b2..64797e9 100644 --- a/include/boost/intrusive/unordered_set_hook.hpp +++ b/include/boost/intrusive/unordered_set_hook.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 @@ -120,8 +120,12 @@ struct unordered_algorithms : public circular_slist_algorithms { typedef circular_slist_algorithms base_type; - typedef unordered_group_adapter group_traits; + typedef unordered_group_adapter group_traits; typedef circular_slist_algorithms group_algorithms; + typedef NodeTraits node_traits; + typedef typename NodeTraits::node node; + typedef typename NodeTraits::node_ptr node_ptr; + typedef typename NodeTraits::const_node_ptr const_node_ptr; static void init(typename base_type::node_ptr n) { @@ -163,7 +167,7 @@ struct get_uset_node_algo #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else -template +template #endif struct make_unordered_set_base_hook { @@ -177,14 +181,14 @@ struct make_unordered_set_base_hook #endif >::type packed_options; - typedef detail::generic_hook + typedef generic_hook < get_uset_node_algo , typename packed_options::tag , packed_options::link_mode - , detail::UsetBaseHook + , HashBaseHookId > implementation_defined; /// @endcond typedef implementation_defined type; @@ -302,7 +306,7 @@ class unordered_set_base_hook #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else -template +template #endif struct make_unordered_set_member_hook { @@ -316,14 +320,14 @@ struct make_unordered_set_member_hook #endif >::type packed_options; - typedef detail::generic_hook + typedef generic_hook < get_uset_node_algo< typename packed_options::void_pointer , packed_options::store_hash , packed_options::optimize_multikey > , member_tag , packed_options::link_mode - , detail::NoBaseHook + , NoBaseHookId > implementation_defined; /// @endcond typedef implementation_defined type; diff --git a/perf/Jamfile.v2 b/perf/Jamfile.v2 index b36a81b..8c35ee8 100644 --- a/perf/Jamfile.v2 +++ b/perf/Jamfile.v2 @@ -1,6 +1,6 @@ # Boost Intrusive Library Performance test Jamfile -# (C) Copyright Ion Gaztanaga 2006-2012. +# (C) Copyright Ion Gaztanaga 2006-2013. # Use, modification and distribution are subject to 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) diff --git a/perf/perf_list.cpp b/perf/perf_list.cpp index 6a4769c..751dcc8 100644 --- a/perf/perf_list.cpp +++ b/perf/perf_list.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 diff --git a/perf/tree_perf_test.cpp b/perf/tree_perf_test.cpp new file mode 100644 index 0000000..5215ea0 --- /dev/null +++ b/perf/tree_perf_test.cpp @@ -0,0 +1,214 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (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. +// +///////////////////////////////////////////////////////////////////////////// + +//Includes for tests +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace boost::posix_time; +using namespace boost::intrusive; + +template struct filler { int dummy[10]; }; +template <> struct filler {}; + +template //The object for non-intrusive containers +struct test_class : private filler +{ + std::size_t i_; + friend bool operator <(const test_class &l, const test_class &r) { return l.i_ < r.i_; } + friend bool operator >(const test_class &l, const test_class &r) { return l.i_ > r.i_; } +}; + +template +struct itest_class //The object for intrusive containers + : public HookType, public test_class +{ +}; + +#ifdef NDEBUG +const std::size_t NumElem = 1000000; +#else +const std::size_t NumElem = 10000; +#endif +const std::size_t NumRepeat = 4; + +enum InsertionType +{ + Monotonic, + Random +}; + +template +void fill_vector(Container &values, InsertionType insertion_type) +{ + switch(insertion_type){ + case Monotonic:{ + for( typename Container::size_type i = 0, max = values.size() + ; i != max + ; ++i){ + values[i].i_ = i; + } + } + break; + case Random:{ + std::srand(0); + for( typename Container::size_type i = 0, max = values.size() + ; i != max + ; ++i){ + values[i].i_ = i; + } + std::random_shuffle(values.begin(), values.end()); + } + break; + default:{ + std::abort(); + } + } +} + +template +void test_insertion(Container &c, const char *ContainerName, InsertionType insertion_type) +{ + std::cout << "Container " << ContainerName << std::endl; + //Prepare + typedef typename Container::size_type size_type; + typedef typename Container::value_type value_type; + ptime tini, tend; + std::vector values(NumElem); + { + fill_vector(values, insertion_type); + //Insert + tini = microsec_clock::universal_time(); + for( size_type repeat = 0, repeat_max = NumRepeat + ; repeat != repeat_max + ; ++repeat){ + c.clear(); + for( size_type i = 0, max = values.size() + ; i != max + ; ++i){ + c.insert(values[i]); + } + if(c.size() != values.size()){ + std::cout << " ERROR: size not consistent" << std::endl; + } + } + tend = microsec_clock::universal_time(); + std::cout << " Insert ns/iter: " << double((tend-tini).total_nanoseconds())/double(NumElem*NumRepeat) << std::endl; + } + //Search + { + value_type v; + tini = microsec_clock::universal_time(); + for( size_type repeat = 0, repeat_max = NumRepeat + ; repeat != repeat_max + ; ++repeat){ + size_type found = 0; + for( size_type i = 0, max = values.size() + ; i != max + ; ++i){ + v.i_ = i; + found += static_cast(c.end() != c.find(v)); + } + if(found != NumElem){ + std::cout << " ERROR: all not found (" << found << ") vs. (" << NumElem << ")" << std::endl; + } + } + tend = microsec_clock::universal_time(); + std::cout << " Search ns/iter: " << double((tend-tini).total_nanoseconds())/double(NumElem*NumRepeat) << std::endl; + } +} + + +void test_insert_search(InsertionType insertion_type) +{ + { + typedef set_base_hook< link_mode > SetHook; + typedef set< itest_class > Set; + Set c; + test_insertion(c, "Set", insertion_type); + } + { + typedef avl_set_base_hook< link_mode > AvlSetHook; + typedef avl_set< itest_class > AvlSet; + AvlSet c; + test_insertion(c, "AvlSet", insertion_type); + } + { + typedef bs_set_base_hook< link_mode > BsSetHook; + typedef sg_set< itest_class > SgSet; + SgSet c; + c.balance_factor(0.55f); + test_insertion(c, "SgSet(alpha 0.55)", insertion_type); + } + { + typedef bs_set_base_hook< link_mode > BsSetHook; + typedef sg_set< itest_class > SgSet; + SgSet c; + c.balance_factor(0.60f); + test_insertion(c, "SgSet(alpha 0.60)", insertion_type); + } + { + typedef bs_set_base_hook< link_mode > BsSetHook; + typedef sg_set< itest_class > SgSet; + SgSet c; + c.balance_factor(0.65f); + test_insertion(c, "SgSet(alpha 0.65)", insertion_type); + } + { + typedef bs_set_base_hook< link_mode > BsSetHook; + typedef sg_set< itest_class > SgSet; + SgSet c; + test_insertion(c, "SgSet(alpha 0.7)", insertion_type); + } + { + typedef bs_set_base_hook< link_mode > BsSetHook; + typedef sg_set< itest_class > SgSet; + SgSet c; + c.balance_factor(0.75f); + test_insertion(c, "SgSet(alpha 0.75)", insertion_type); + } + { + typedef bs_set_base_hook< link_mode > BsSetHook; + typedef sg_set< itest_class > SgSet; + SgSet c; + c.balance_factor(0.80f); + test_insertion(c, "SgSet(alpha 0.80)", insertion_type); + } + { + typedef bs_set_base_hook< link_mode > BsSetHook; + typedef sg_set< itest_class, floating_point > SgSet; + SgSet c; + test_insertion(c, "SgSet(no float, alpha 1/sqrt(2)~0,7071)", insertion_type); + } +} + +int main() +{ + std::cout << "MONOTONIC INPUTS\n"; + std::cout << "----------------\n\n"; + test_insert_search(Monotonic); + std::cout << "----------------\n\n"; + std::cout << "RANDOM INPUTS\n"; + std::cout << "----------------\n\n"; + test_insert_search(Random); + std::cout << "----------------\n\n"; + return 0; +} + +#include diff --git a/proj/vc7ide/Intrusive.sln b/proj/vc7ide/Intrusive.sln index b6ca829..54fcb68 100644 --- a/proj/vc7ide/Intrusive.sln +++ b/proj/vc7ide/Intrusive.sln @@ -107,6 +107,14 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "has_member_function_callabl ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tree_perf_test", "tree_perf_test\tree_perf_test.vcproj", "{90E721E6-12C9-AD67-F4BC-A74C309949C7}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "scary_iterators", "scary_iterators\scary_iterators.vcproj", "{7679B41B-C1C5-FA34-9614-3547B3140346}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject Global GlobalSection(SolutionConfiguration) = preSolution Debug = Debug @@ -223,6 +231,14 @@ Global {3579B1A4-02AB-5489-CB81-957B14032465}.Debug.Build.0 = Debug|Win32 {3579B1A4-02AB-5489-CB81-957B14032465}.Release.ActiveCfg = Release|Win32 {3579B1A4-02AB-5489-CB81-957B14032465}.Release.Build.0 = Release|Win32 + {90E721E6-12C9-AD67-F4BC-A74C309949C7}.Debug.ActiveCfg = Debug|Win32 + {90E721E6-12C9-AD67-F4BC-A74C309949C7}.Debug.Build.0 = Debug|Win32 + {90E721E6-12C9-AD67-F4BC-A74C309949C7}.Release.ActiveCfg = Release|Win32 + {90E721E6-12C9-AD67-F4BC-A74C309949C7}.Release.Build.0 = Release|Win32 + {7679B41B-C1C5-FA34-9614-3547B3140346}.Debug.ActiveCfg = Debug|Win32 + {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 EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution EndGlobalSection diff --git a/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj b/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj index ef954f4..31c88f3 100644 --- a/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj +++ b/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj @@ -112,9 +112,18 @@ + + + + + + @@ -187,9 +196,6 @@ - - @@ -223,9 +229,6 @@ - - @@ -280,9 +283,6 @@ - - @@ -318,18 +318,12 @@ - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/to-do.txt b/proj/vc7ide/to-do.txt index c4eafc6..8007a68 100644 --- a/proj/vc7ide/to-do.txt +++ b/proj/vc7ide/to-do.txt @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 @@ -19,6 +19,9 @@ -> Return pointers by const reference if node traits return them by const reference to optimize shared memory pointers -> Detect call signatures by has_member_function_callable_with instead of exact match to allow taking by const reference -> Optimize operations taking const_node_pointer using template parameters and SFINAE to allow node_ptr +-> Add explicit constructors when needed +-> Add all containers to external_value_traits +-> Add test to check sizes (EBO) diff --git a/proj/vc7ide/tree_perf_test/tree_perf_test.vcproj b/proj/vc7ide/tree_perf_test/tree_perf_test.vcproj new file mode 100644 index 0000000..b0b6a3e --- /dev/null +++ b/proj/vc7ide/tree_perf_test/tree_perf_test.vcproj @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/any_test.cpp b/test/any_test.cpp index f173264..b130cf6 100644 --- a/test/any_test.cpp +++ b/test/any_test.cpp @@ -1,7 +1,8 @@ + ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2012. +// (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 diff --git a/test/avl_multiset_test.cpp b/test/avl_multiset_test.cpp index 149c2d0..ecad395 100644 --- a/test/avl_multiset_test.cpp +++ b/test/avl_multiset_test.cpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2012. +// (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 @@ -58,9 +58,9 @@ struct hooks }; template< class ValueType - , class Option1 = boost::intrusive::none - , class Option2 = boost::intrusive::none - , class Option3 = boost::intrusive::none + , class Option1 =void + , class Option2 =void + , class Option3 =void > struct GetContainer { diff --git a/test/avl_set_test.cpp b/test/avl_set_test.cpp index 78590a4..8c04e46 100644 --- a/test/avl_set_test.cpp +++ b/test/avl_set_test.cpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2012. +// (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 @@ -58,9 +58,9 @@ struct hooks }; template< class ValueType - , class Option1 = boost::intrusive::none - , class Option2 = boost::intrusive::none - , class Option3 = boost::intrusive::none + , class Option1 =void + , class Option2 =void + , class Option3 =void > struct GetContainer { diff --git a/test/common_functors.hpp b/test/common_functors.hpp index 0cc9d96..03fbc65 100644 --- a/test/common_functors.hpp +++ b/test/common_functors.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 diff --git a/test/custom_bucket_traits_test.cpp b/test/custom_bucket_traits_test.cpp index 6e710a5..3fe850f 100644 --- a/test/custom_bucket_traits_test.cpp +++ b/test/custom_bucket_traits_test.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 diff --git a/test/default_hook_test.cpp b/test/default_hook_test.cpp index 728c7fb..c7ef908 100644 --- a/test/default_hook_test.cpp +++ b/test/default_hook_test.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 @@ -16,6 +16,8 @@ #include #include #include +#include +#include #include #include "smart_ptr.hpp" #include @@ -25,19 +27,17 @@ using namespace boost::intrusive; class MyClass : public list_base_hook - < void_pointer >, link_mode > + < void_pointer >, link_mode > , public slist_base_hook - < void_pointer >, link_mode > + < void_pointer >, link_mode > , public set_base_hook - < void_pointer >, link_mode > + < void_pointer >, link_mode > , public unordered_set_base_hook - < void_pointer >, link_mode > + < void_pointer >, link_mode > , public avl_set_base_hook - < void_pointer >, link_mode > -, public splay_set_base_hook - < void_pointer >, link_mode > + < void_pointer >, link_mode > , public bs_set_base_hook - < void_pointer >, link_mode > + < void_pointer >, link_mode > { int int_; @@ -54,6 +54,9 @@ class MyClass friend std::size_t hash_value(const MyClass &v) { return boost::hash_value(v.int_); } + + friend bool priority_order(const MyClass &l, const MyClass &r) + { return l.int_ < r.int_; } }; //Define a list that will store MyClass using the public base hook @@ -63,7 +66,9 @@ typedef set Set; typedef unordered_set USet; typedef avl_set AvlSet; typedef splay_set SplaySet; +typedef treap_set TreapSet; typedef sg_set SgSet; +typedef bs_set BsSet; int main() { @@ -73,56 +78,89 @@ int main() //Create several MyClass objects, each one with a different value std::vector values; for(int i = 0; i < 100; ++i) values.push_back(MyClass(i)); - - USet::bucket_type buckets[100]; - - List my_list; - Slist my_slist; - Set my_set; - USet my_uset(USet::bucket_traits(pointer_traits::pointer_to(*buckets), 100)); - - AvlSet my_avlset; - SplaySet my_splayset; - SgSet my_sgset; - - //Now insert them in the reverse order - //in the base hook intrusive list - for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it){ - my_list.push_front(*it); - my_slist.push_front(*it); - my_set.insert(*it); - my_uset.insert(*it); - my_avlset.insert(*it); - my_splayset.insert(*it); - my_sgset.insert(*it); - } - - //Now test lists + { - List::const_iterator list_it(my_list.cbegin()); - Slist::const_iterator slist_it(my_slist.cbegin()); - Set::const_reverse_iterator set_rit(my_set.crbegin()); - AvlSet::const_reverse_iterator avl_set_rit(my_avlset.crbegin()); - SplaySet::const_reverse_iterator splay_set_rit(my_splayset.crbegin()); - SgSet::const_reverse_iterator sg_set_rit(my_sgset.crbegin()); + List my_list; + Slist my_slist; + Set my_set; + USet::bucket_type buckets[100]; + USet my_uset(USet::bucket_traits(pointer_traits::pointer_to(*buckets), 100)); + AvlSet my_avlset; + SplaySet my_splayset; - VectRit vect_it(values.rbegin()), vect_itend(values.rend()); + //Now insert them in the reverse order + //in the base hook intrusive list + for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it){ + my_list.push_front(*it); + my_slist.push_front(*it); + my_set.insert(*it); + my_uset.insert(*it); + my_avlset.insert(*it); + my_splayset.insert(*it); + } - //Test the objects inserted in the base hook list - for(; vect_it != vect_itend - ; ++vect_it, ++list_it - , ++slist_it, ++set_rit - , ++avl_set_rit, ++splay_set_rit - , ++sg_set_rit){ - if(&*list_it != &*vect_it) return 1; - if(&*slist_it != &*vect_it) return 1; - if(&*set_rit != &*vect_it) return 1; - if(&*avl_set_rit != &*vect_it) return 1; - if(&*splay_set_rit != &*vect_it)return 1; - if(&*sg_set_rit != &*vect_it) return 1; - if(my_uset.find(*set_rit) == my_uset.cend()) return 1; + //Now test lists + { + List::const_iterator list_it(my_list.cbegin()); + Slist::const_iterator slist_it(my_slist.cbegin()); + Set::const_reverse_iterator set_rit(my_set.crbegin()); + AvlSet::const_reverse_iterator avl_set_rit(my_avlset.crbegin()); + SplaySet::const_reverse_iterator splay_set_rit(my_splayset.crbegin()); + + VectRit vect_it(values.rbegin()), vect_itend(values.rend()); + + //Test the objects inserted in the base hook list + for(; vect_it != vect_itend + ; ++vect_it, ++list_it + , ++slist_it, ++set_rit + , ++avl_set_rit + , ++splay_set_rit + ){ + if(&*list_it != &*vect_it) return 1; + if(&*slist_it != &*vect_it) return 1; + if(&*set_rit != &*vect_it) return 1; + if(&*avl_set_rit != &*vect_it) return 1; + if(&*splay_set_rit != &*vect_it)return 1; + if(my_uset.find(*set_rit) == my_uset.cend()) return 1; + } } } + //Since treap_set, sg_set & bs_set reuse the hook, treat them apart + { + TreapSet my_treapset; + for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it){ + my_treapset.insert(*it); + } + TreapSet::const_reverse_iterator treap_set_rit(my_treapset.crbegin()); + VectRit vect_it(values.rbegin()), vect_itend(values.rend()); + for(; vect_it != vect_itend; ++vect_it, ++treap_set_rit){ + if(&*treap_set_rit != &*vect_it) return 1; + } + } + { + SgSet my_sgset; + for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it){ + my_sgset.insert(*it); + } + + SgSet::const_reverse_iterator sg_set_rit(my_sgset.crbegin()); + VectRit vect_it(values.rbegin()), vect_itend(values.rend()); + for(; vect_it != vect_itend; ++vect_it, ++sg_set_rit){ + if(&*sg_set_rit != &*vect_it) return 1; + } + } + { + BsSet my_bsset; + for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it){ + my_bsset.insert(*it); + } + + BsSet::const_reverse_iterator bs_set_rit(my_bsset.crbegin()); + VectRit vect_it(values.rbegin()), vect_itend(values.rend()); + for(; vect_it != vect_itend; ++vect_it, ++bs_set_rit){ + if(&*bs_set_rit != &*vect_it) return 1; + } + } return 0; } diff --git a/test/external_value_traits_test.cpp b/test/external_value_traits_test.cpp index b53b972..60efc9d 100644 --- a/test/external_value_traits_test.cpp +++ b/test/external_value_traits_test.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 @@ -130,6 +130,7 @@ 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 diff --git a/test/function_hook_test.cpp b/test/function_hook_test.cpp index bbb0774..708983e 100644 --- a/test/function_hook_test.cpp +++ b/test/function_hook_test.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2010-2012 +// (C) Copyright Ion Gaztanaga 2010-2013 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/test/generic_assoc_test.hpp b/test/generic_assoc_test.hpp index a1422c4..2d08304 100644 --- a/test/generic_assoc_test.hpp +++ b/test/generic_assoc_test.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2012. +// (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 @@ -71,7 +71,7 @@ struct search_const_container typedef T type; }; -template class ContainerDefiner> +template class ContainerDefiner> struct test_generic_assoc { typedef typename ValueTraits::value_type value_type; @@ -94,7 +94,7 @@ struct test_generic_assoc static void test_container_from_iterator(std::vector& values); }; -template class ContainerDefiner> +template class ContainerDefiner> void test_generic_assoc:: test_container_from_iterator(std::vector& values) { @@ -122,7 +122,7 @@ void test_generic_assoc:: } } -template class ContainerDefiner> +template class ContainerDefiner> void test_generic_assoc::test_insert_erase_burst() { typedef typename ValueTraits::value_type value_type; @@ -181,7 +181,7 @@ void test_generic_assoc::test_insert_erase_burst( } } -template class ContainerDefiner> +template class ContainerDefiner> void test_generic_assoc::test_all(std::vector& values) { typedef typename ValueTraits::value_type value_type; @@ -195,7 +195,7 @@ void test_generic_assoc::test_all(std::vector class ContainerDefiner> +template class ContainerDefiner> void test_generic_assoc ::test_clone(std::vector& values) { @@ -215,7 +215,7 @@ void test_generic_assoc BOOST_TEST (testset2.empty()); } -template class ContainerDefiner> +template class ContainerDefiner> void test_generic_assoc ::test_container_from_end(std::vector& values) { @@ -230,7 +230,7 @@ void test_generic_assoc BOOST_TEST (testset == assoc_type::container_from_end_iterator(testset.cend())); } -template class ContainerDefiner> +template class ContainerDefiner> void test_generic_assoc::test_splay_up (std::vector& values, boost::intrusive::detail::true_type) { @@ -268,12 +268,12 @@ void test_generic_assoc::test_splay_up } } -template class ContainerDefiner> +template class ContainerDefiner> void test_generic_assoc::test_splay_up (std::vector&, boost::intrusive::detail::false_type) {} -template class ContainerDefiner> +template class ContainerDefiner> void test_generic_assoc::test_splay_up (std::vector& values) { @@ -287,7 +287,7 @@ void test_generic_assoc::test_splay_up test_splay_up(values, enabler()); } -template class ContainerDefiner> +template class ContainerDefiner> void test_generic_assoc::test_splay_down (std::vector& values, boost::intrusive::detail::true_type) { @@ -326,12 +326,12 @@ void test_generic_assoc::test_splay_down } } -template class ContainerDefiner> +template class ContainerDefiner> void test_generic_assoc::test_splay_down (std::vector&, boost::intrusive::detail::false_type) {} -template class ContainerDefiner> +template class ContainerDefiner> void test_generic_assoc::test_splay_down (std::vector& values) { @@ -345,7 +345,7 @@ void test_generic_assoc::test_splay_down test_splay_down(values, enabler()); } -template class ContainerDefiner> +template class ContainerDefiner> void test_generic_assoc::test_rebalance (std::vector& values, boost::intrusive::detail::true_type) { @@ -385,12 +385,12 @@ void test_generic_assoc::test_rebalance } } -template class ContainerDefiner> +template class ContainerDefiner> void test_generic_assoc::test_rebalance (std::vector&, boost::intrusive::detail::false_type) {} -template class ContainerDefiner> +template class ContainerDefiner> void test_generic_assoc::test_rebalance (std::vector& values) { @@ -404,7 +404,7 @@ void test_generic_assoc::test_rebalance test_rebalance(values, enabler()); } -template class ContainerDefiner> +template class ContainerDefiner> void test_generic_assoc::test_insert_before (std::vector& values, boost::intrusive::detail::true_type) { @@ -454,12 +454,12 @@ void test_generic_assoc::test_insert_before } } -template class ContainerDefiner> +template class ContainerDefiner> void test_generic_assoc::test_insert_before (std::vector&, boost::intrusive::detail::false_type) {} -template class ContainerDefiner> +template class ContainerDefiner> void test_generic_assoc::test_insert_before (std::vector& values) { diff --git a/test/generic_multiset_test.hpp b/test/generic_multiset_test.hpp index 5d7774a..2224d09 100644 --- a/test/generic_multiset_test.hpp +++ b/test/generic_multiset_test.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2012. +// (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 @@ -23,7 +23,7 @@ namespace boost{ namespace intrusive{ namespace test{ -template class ContainerDefiner> +template class ContainerDefiner> struct test_generic_multiset { typedef typename ValueTraits::value_type value_type; @@ -35,7 +35,7 @@ struct test_generic_multiset static void test_impl(); }; -template class ContainerDefiner> +template class ContainerDefiner> void test_generic_multiset::test_all () { typedef typename ValueTraits::value_type value_type; @@ -71,7 +71,7 @@ void test_generic_multiset::test_all () } //test case due to an error in tree implementation: -template class ContainerDefiner> +template class ContainerDefiner> void test_generic_multiset::test_impl() { typedef typename ValueTraits::value_type value_type; @@ -98,7 +98,7 @@ void test_generic_multiset::test_impl() } //test: constructor, iterator, clear, reverse_iterator, front, back, size: -template class ContainerDefiner> +template class ContainerDefiner> void test_generic_multiset::test_sort(std::vector& values) { typedef typename ValueTraits::value_type value_type; @@ -130,7 +130,7 @@ void test_generic_multiset::test_sort(std::vector } //test: insert, const_iterator, const_reverse_iterator, erase, iterator_to: -template class ContainerDefiner> +template class ContainerDefiner> void test_generic_multiset::test_insert(std::vector& values) { typedef typename ValueTraits::value_type value_type; @@ -168,7 +168,7 @@ void test_generic_multiset::test_insert(std::vect } //test: insert (seq-version), swap, erase (seq-version), size: -template class ContainerDefiner> +template class ContainerDefiner> void test_generic_multiset::test_swap(std::vector& values) { typedef typename ValueTraits::value_type value_type; @@ -194,7 +194,7 @@ void test_generic_multiset::test_swap(std::vector } //test: find, equal_range (lower_bound, upper_bound): -template class ContainerDefiner> +template class ContainerDefiner> void test_generic_multiset::test_find(std::vector& values) { typedef typename ValueTraits::value_type value_type; diff --git a/test/generic_set_test.hpp b/test/generic_set_test.hpp index e57fbb7..eae5954 100644 --- a/test/generic_set_test.hpp +++ b/test/generic_set_test.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2012. +// (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 @@ -29,7 +29,7 @@ struct is_treap static const bool value = false; }; -template class ContainerDefiner> +template class ContainerDefiner> struct test_generic_set { typedef typename ValueTraits::value_type value_type; @@ -45,7 +45,7 @@ struct test_generic_set }; -template class ContainerDefiner> +template class ContainerDefiner> void test_generic_set::test_all() { typedef typename ValueTraits::value_type value_type; @@ -82,7 +82,7 @@ void test_generic_set::test_all() } //test case due to an error in tree implementation: -template class ContainerDefiner> +template class ContainerDefiner> void test_generic_set::test_impl() { typedef typename ValueTraits::value_type value_type; @@ -109,7 +109,7 @@ void test_generic_set::test_impl() } //test: constructor, iterator, clear, reverse_iterator, front, back, size: -template class ContainerDefiner> +template class ContainerDefiner> void test_generic_set::test_sort(std::vector& values) { typedef typename ValueTraits::value_type value_type; @@ -140,7 +140,7 @@ void test_generic_set::test_sort(std::vector class ContainerDefiner> +template class ContainerDefiner> void test_generic_set::test_insert(std::vector& values) { typedef typename ValueTraits::value_type value_type; @@ -178,7 +178,7 @@ void test_generic_set::test_insert(std::vector class ContainerDefiner> +template class ContainerDefiner> void test_generic_set::test_insert_advanced (std::vector& values, boost::intrusive::detail::true_type) { @@ -199,7 +199,7 @@ void test_generic_set::test_insert_advanced } -template class ContainerDefiner> +template class ContainerDefiner> void test_generic_set::test_insert_advanced (std::vector& values) { @@ -216,7 +216,7 @@ void test_generic_set::test_insert_advanced //test: insert, const_iterator, const_reverse_iterator, erase, s_iterator_to: -template class ContainerDefiner> +template class ContainerDefiner> void test_generic_set::test_insert_advanced ( std::vector& values , boost::intrusive::detail::false_type) @@ -239,7 +239,7 @@ void test_generic_set::test_insert_advanced //test: insert (seq-version), swap, erase (seq-version), size: -template class ContainerDefiner> +template class ContainerDefiner> void test_generic_set::test_swap(std::vector& values) { typedef typename ValueTraits::value_type value_type; @@ -266,7 +266,7 @@ void test_generic_set::test_swap(std::vector class ContainerDefiner> +template class ContainerDefiner> void test_generic_set::test_find(std::vector& values) { typedef typename ValueTraits::value_type value_type; diff --git a/test/has_member_function_callable_with.cpp b/test/has_member_function_callable_with.cpp index 5904ec0..96b822e 100644 --- a/test/has_member_function_callable_with.cpp +++ b/test/has_member_function_callable_with.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2011-2012. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2011-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) // diff --git a/test/itestvalue.hpp b/test/itestvalue.hpp index 0470e8a..37059ac 100644 --- a/test/itestvalue.hpp +++ b/test/itestvalue.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2012. +// (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 diff --git a/test/list_test.cpp b/test/list_test.cpp index 4857a2f..94521c5 100644 --- a/test/list_test.cpp +++ b/test/list_test.cpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2012. +// (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 diff --git a/test/make_functions_test.cpp b/test/make_functions_test.cpp index 1b98f24..89de0e9 100644 --- a/test/make_functions_test.cpp +++ b/test/make_functions_test.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 @@ -25,10 +25,14 @@ using namespace boost::intrusive; struct my_tag; +struct my_tag2; typedef make_bs_set_base_hook < void_pointer >, link_mode , tag >::type TreapHook; +typedef make_bs_set_base_hook + < void_pointer >, link_mode + , tag >::type SplayHook; class MyClass : public make_list_base_hook @@ -41,11 +45,10 @@ class MyClass < void_pointer >, link_mode >::type , public make_avl_set_base_hook < void_pointer >, link_mode >::type -, public make_splay_set_base_hook - < void_pointer >, link_mode >::type , public make_bs_set_base_hook < void_pointer >, link_mode >::type , public TreapHook +, public SplayHook { int int_; @@ -74,10 +77,11 @@ typedef make_set::type Set; typedef make_unordered_set::type USet; typedef make_avl_set::type AvlSet; -typedef make_splay_set::type SplaySet; typedef make_sg_set::type SgSet; typedef make_treap_set >::type TreapSet; +typedef make_splay_set >::type SplaySet; int main() { diff --git a/test/multiset_test.cpp b/test/multiset_test.cpp index 74bb18e..ba503a2 100644 --- a/test/multiset_test.cpp +++ b/test/multiset_test.cpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2012. +// (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 @@ -57,9 +57,9 @@ struct hooks }; template< class ValueType - , class Option1 = boost::intrusive::none - , class Option2 = boost::intrusive::none - , class Option3 = boost::intrusive::none + , class Option1 =void + , class Option2 =void + , class Option3 =void > struct GetContainer { diff --git a/test/pointer_traits_test.cpp b/test/pointer_traits_test.cpp index 93a2421..1deda45 100644 --- a/test/pointer_traits_test.cpp +++ b/test/pointer_traits_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2011-2012. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2011-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) // diff --git a/test/recursive_test.cpp b/test/recursive_test.cpp index 619206a..a6fe73a 100644 --- a/test/recursive_test.cpp +++ b/test/recursive_test.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 diff --git a/test/scary_iterators_test.cpp b/test/scary_iterators_test.cpp new file mode 100644 index 0000000..6c4b426 --- /dev/null +++ b/test/scary_iterators_test.cpp @@ -0,0 +1,314 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2013-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 +#include +#include +#include +#include +#include "smart_ptr.hpp" +#include //std::greater/std::less + +using namespace boost::intrusive; +struct my_tag; + +template +class MyClass +: public make_list_base_hook + < void_pointer, link_mode >::type +, public make_slist_base_hook + < void_pointer, link_mode >::type +, public make_set_base_hook + < void_pointer, link_mode >::type +, public make_unordered_set_base_hook + < void_pointer, link_mode >::type +, public make_avl_set_base_hook + < void_pointer, link_mode >::type +, public make_bs_set_base_hook + < void_pointer, link_mode >::type +{ + int int_; + + public: + MyClass(int i) + : 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_); } + + friend bool priority_order(const MyClass &l, const MyClass &r) + { return l.int_ < r.int_; } +}; + +template +struct inverse_priority +{ + bool operator()(const T &l, const T &r) + { return l.int_ > r.int_; } +}; + +template +struct inverse_hash +{ + bool operator()(const T &l) + { return hash_value(l); } +}; + +template +struct alternative_equal +{ + bool operator()(const T &l, const T &r) + { return l.int_ == r.int_; } +}; + +int main() +{ + //////////// + // list + //////////// + BOOST_STATIC_ASSERT((!detail::is_same< list >::iterator + , list >::const_iterator + >::value)); + //constant_time_size does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< list, constant_time_size >::iterator + , list, constant_time_size >::iterator + >::value)); + //void_pointer does change iterator + BOOST_STATIC_ASSERT((!detail::is_same< list >::iterator + , list > >::iterator + >::value)); + //size_type does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< list, size_type >::iterator + , list, size_type >::iterator + >::value)); + //////////// + // slist + //////////// + BOOST_STATIC_ASSERT((!detail::is_same< slist >::iterator + , slist >::const_iterator + >::value)); + //constant_time_size does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< slist, constant_time_size >::iterator + , slist, constant_time_size >::iterator + >::value)); + //void_pointer does change iterator + BOOST_STATIC_ASSERT((!detail::is_same< slist >::iterator + , slist > >::iterator + >::value)); + //size_type does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< slist, size_type >::iterator + , slist, size_type >::iterator + >::value)); + //cache_last does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< slist, cache_last >::iterator + , slist, cache_last >::iterator + >::value)); + //linear does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< slist, linear >::iterator + , slist, linear >::iterator + >::value)); + //////////// + // set + //////////// + BOOST_STATIC_ASSERT((!detail::is_same< set >::iterator + , set >::const_iterator + >::value)); + //constant_time_size does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< set, constant_time_size >::iterator + , set, constant_time_size >::iterator + >::value)); + //void_pointer does change iterator + BOOST_STATIC_ASSERT((!detail::is_same< set >::iterator + , set > >::iterator + >::value)); + //size_type does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< set, size_type >::iterator + , set, size_type >::iterator + >::value)); + //compare does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< set, compare< std::greater > > >::iterator + , set, compare< std::less > > >::iterator + >::value)); + //////////// + // avl_set + //////////// + BOOST_STATIC_ASSERT((!detail::is_same< avl_set >::iterator + , avl_set >::const_iterator + >::value)); + //constant_time_size does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< avl_set, constant_time_size >::iterator + , avl_set, constant_time_size >::iterator + >::value)); + //void_pointer does change iterator + BOOST_STATIC_ASSERT((!detail::is_same< avl_set >::iterator + , avl_set > >::iterator + >::value)); + //size_type does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< avl_set, size_type >::iterator + , avl_set, size_type >::iterator + >::value)); + //compare does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< avl_set, compare< std::greater > > >::iterator + , avl_set, compare< std::less > > >::iterator + >::value)); + //////////// + // sg_set + //////////// + BOOST_STATIC_ASSERT((!detail::is_same< sg_set >::iterator + , sg_set >::const_iterator + >::value)); + //void_pointer does change iterator + BOOST_STATIC_ASSERT((!detail::is_same< sg_set >::iterator + , sg_set > >::iterator + >::value)); + //size_type does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< sg_set, size_type >::iterator + , sg_set, size_type >::iterator + >::value)); + //compare does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< sg_set, compare< std::greater > > >::iterator + , sg_set, compare< std::less > > >::iterator + >::value)); + //floating_point does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< sg_set, floating_point >::iterator + , sg_set, floating_point >::iterator + >::value)); + //////////// + // bs_set + //////////// + BOOST_STATIC_ASSERT((!detail::is_same< bs_set >::iterator + , bs_set >::const_iterator + >::value)); + //constant_time_size does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< bs_set, constant_time_size >::iterator + , bs_set, constant_time_size >::iterator + >::value)); + //void_pointer does change iterator + BOOST_STATIC_ASSERT((!detail::is_same< bs_set >::iterator + , bs_set > >::iterator + >::value)); + //size_type does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< bs_set, size_type >::iterator + , bs_set, size_type >::iterator + >::value)); + //compare does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< bs_set, compare< std::greater > > >::iterator + , bs_set, compare< std::less > > >::iterator + >::value)); + //////////// + // splay_set + //////////// + BOOST_STATIC_ASSERT((!detail::is_same< splay_set >::iterator + , splay_set >::const_iterator + >::value)); + //constant_time_size does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< splay_set, constant_time_size >::iterator + , splay_set, constant_time_size >::iterator + >::value)); + //void_pointer does change iterator + BOOST_STATIC_ASSERT((!detail::is_same< splay_set >::iterator + , splay_set > >::iterator + >::value)); + //size_type does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< splay_set, size_type >::iterator + , splay_set, size_type >::iterator + >::value)); + //compare does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< splay_set, compare< std::greater > > >::iterator + , splay_set, compare< std::less > > >::iterator + >::value)); + //////////// + // treap_set + //////////// + BOOST_STATIC_ASSERT((!detail::is_same< treap_set >::iterator + , treap_set >::const_iterator + >::value)); + //constant_time_size does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< treap_set, constant_time_size >::iterator + , treap_set, constant_time_size >::iterator + >::value)); + //void_pointer does change iterator + BOOST_STATIC_ASSERT((!detail::is_same< treap_set >::iterator + , treap_set > >::iterator + >::value)); + //size_type does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< treap_set, size_type >::iterator + , treap_set, size_type >::iterator + >::value)); + //compare does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< treap_set, compare< std::greater > > >::iterator + , treap_set, compare< std::less > > >::iterator + >::value)); + //priority does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< treap_set >::iterator + , treap_set, priority< inverse_priority > > >::iterator + >::value)); + ////////////// + // common tree + ////////////// + BOOST_STATIC_ASSERT((detail::is_same< bs_set >::iterator + , sg_set >::iterator + >::value)); + BOOST_STATIC_ASSERT((detail::is_same< bs_set >::iterator + , treap_set >::iterator + >::value)); + BOOST_STATIC_ASSERT((detail::is_same< bs_set >::iterator + , splay_set >::iterator + >::value)); + //////////// + // unordered_set + //////////// + BOOST_STATIC_ASSERT((!detail::is_same< unordered_set >::iterator + , unordered_set >::const_iterator + >::value)); + //constant_time_size does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< unordered_set, constant_time_size >::iterator + , unordered_set, constant_time_size >::iterator + >::value)); + //void_pointer does change iterator + BOOST_STATIC_ASSERT((!detail::is_same< unordered_set >::iterator + , unordered_set > >::iterator + >::value)); + //size_type does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< unordered_set, size_type >::iterator + , unordered_set, size_type >::iterator + >::value)); + //hash does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< unordered_set >::iterator + , unordered_set, hash< inverse_hash > > >::iterator + >::value)); + //equal does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< unordered_set >::iterator + , unordered_set, equal< alternative_equal > > >::iterator + >::value)); + //power_2_buckets does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< unordered_set >::iterator + , unordered_set, power_2_buckets >::iterator + >::value)); + //cache_begin does not change iterator + BOOST_STATIC_ASSERT((detail::is_same< unordered_set >::iterator + , unordered_set, cache_begin >::iterator + >::value)); + return 0; +} diff --git a/test/set_test.cpp b/test/set_test.cpp index 1570dcd..4e4e91d 100644 --- a/test/set_test.cpp +++ b/test/set_test.cpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2012. +// (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 @@ -58,9 +58,9 @@ struct hooks }; template< class ValueType - , class Option1 = boost::intrusive::none - , class Option2 = boost::intrusive::none - , class Option3 = boost::intrusive::none + , class Option1 =void + , class Option2 =void + , class Option3 =void > struct GetContainer { diff --git a/test/sg_multiset_test.cpp b/test/sg_multiset_test.cpp index 0230a9d..5accea7 100644 --- a/test/sg_multiset_test.cpp +++ b/test/sg_multiset_test.cpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2012. +// (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 @@ -70,9 +70,9 @@ struct hooks template< class ValueType - , class Option1 = boost::intrusive::none - , class Option2 = boost::intrusive::none - , class Option3 = boost::intrusive::none + , class Option1 =void + , class Option2 =void + , class Option3 =void > struct GetContainer { @@ -85,9 +85,9 @@ struct GetContainer }; template< class ValueType - , class Option1 = boost::intrusive::none - , class Option2 = boost::intrusive::none - , class Option3 = boost::intrusive::none + , class Option1 =void + , class Option2 =void + , class Option3 =void > struct GetContainerFixedAlpha { diff --git a/test/sg_set_test.cpp b/test/sg_set_test.cpp index f19d55e..f447425 100644 --- a/test/sg_set_test.cpp +++ b/test/sg_set_test.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 @@ -68,9 +68,9 @@ struct hooks }; template< class ValueType - , class Option1 = boost::intrusive::none - , class Option2 = boost::intrusive::none - , class Option3 = boost::intrusive::none + , class Option1 =void + , class Option2 =void + , class Option3 =void > struct GetContainer { @@ -83,9 +83,9 @@ struct GetContainer }; template< class ValueType - , class Option1 = boost::intrusive::none - , class Option2 = boost::intrusive::none - , class Option3 = boost::intrusive::none + , class Option1 =void + , class Option2 =void + , class Option3 =void > struct GetContainerFixedAlpha { diff --git a/test/slist_test.cpp b/test/slist_test.cpp index 32c1d12..de04865 100644 --- a/test/slist_test.cpp +++ b/test/slist_test.cpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2012. +// (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 @@ -730,3 +730,207 @@ int main(int, char* []) return boost::report_errors(); } #include + +/* +#include +#include +#include +#include +#include + +namespace intrusive = boost::intrusive; + +class object : public boost::noncopyable +{ +public: + int o; + object() + { + } + virtual ~object() + { + } +}; + + +class signal : virtual public object +{ +public: + signal() + { + } + virtual ~signal() + { + } +}; + + +class set_item : public signal +{ +public: + set_item() + { + } + virtual ~set_item() + { + } + +public: + virtual const std::string& get_buffer() const + { + return m_buffer; + } + + typedef intrusive::set_member_hook< + intrusive::link_mode + > hook; + hook m_hook; + + std::string m_buffer; +}; + + +template +struct member_comparator +{ + bool operator()(const T& t1, const T& t2) const + { + return (t1.*V) < (t2.*V); + } + bool operator()(const M& m, const T& t) const + { + return m < (t.*V); + } + bool operator()(const T& t, const M& m) const + { + return (t.*V) < m; + } +}; + +class kk{ int a; float f; }; + +class list_item : public kk, virtual public object +{ +public: + list_item() + { + } + virtual ~list_item() + { + } + + virtual void f() + { + } + + typedef intrusive::list_member_hook< + intrusive::link_mode + > hook; + hook m_hook; +}; + +set_item srec; +list_item lrec; + +const set_item::hook set_item::* sptr_to_member = &set_item::m_hook; +const list_item::hook list_item::* lptr_to_member = &list_item::m_hook; + +int main(int argc, char** argv) +{ + int a = sizeof(sptr_to_member); + int b = sizeof(lptr_to_member); + const std::type_info &ta = typeid(set_item); + const std::type_info &tb = typeid(list_item); + + const set_item::hook &sh = srec.*sptr_to_member; + const list_item::hook &l2 = lrec.*lptr_to_member; + + { + typedef member_comparator< + set_item, + std::string, + &set_item::m_buffer + > set_item_comparator; + + typedef intrusive::set< + set_item, + intrusive::compare, + intrusive::member_hook< + set_item, + set_item::hook, + &set_item::m_hook + >, + intrusive::constant_time_size + > set_items + ; + + union + { + int as_int[2]; + const set_item::hook set_item::* ptr_to_member; + } + sss; + sss.ptr_to_member = &set_item::m_hook; + + std::cout << "set offsets: " << sss.as_int[0] << ":" << sss.as_int[1] << " and " << offsetof(set_item,m_hook) << std::endl; + + set_items rr; + + std::string key = "123"; + set_items::insert_commit_data icd; + std::pair ir = rr.insert_check( + key, + set_item_comparator(), + icd + ); + + if ( !ir.second ) + { + throw std::exception(); + } + + set_item rec; + rec.m_buffer = key; + set_items::iterator i = rr.insert_commit( rec, icd ); + + set_item* rrr = &(*i); + + std::cout << "set pointers: " << ((void*)rrr) << " and " << ((void*)&rec) << std::endl; + } + + { + typedef intrusive::list< + list_item, + intrusive::member_hook< + list_item, + list_item::hook, + &list_item::m_hook + >, + intrusive::constant_time_size + > list_items + ; + + union + { + int as_int[2]; + const list_item::hook list_item::* ptr_to_member; + } + sss; + sss.ptr_to_member = &list_item::m_hook; + + std::cout << "list offsets: " << sss.as_int[0] << ":" << sss.as_int[1] << " and " << offsetof(list_item,m_hook) << std::endl; + + list_items rr; + + list_item rec; + const list_item::hook &h = rec.*sss.ptr_to_member; + rr.push_back( rec ); + + list_item* rrr = &rr.front(); + + std::cout << "list pointers: " << ((void*)rrr) << " and " << ((void*)&rec) << std::endl; + } + + return 0; +} +*/ \ No newline at end of file diff --git a/test/splay_multiset_test.cpp b/test/splay_multiset_test.cpp index b6d6760..bf8cb8e 100644 --- a/test/splay_multiset_test.cpp +++ b/test/splay_multiset_test.cpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2012. +// (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 @@ -19,23 +19,6 @@ namespace boost { namespace intrusive { namespace test { -#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES) -template -#else -template -#endif -struct has_const_overloads -> -{ - static const bool value = false; -}; - #if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else @@ -81,7 +64,7 @@ struct has_const_searches > { - static const bool value = false; + static const bool value = true; }; @@ -106,9 +89,9 @@ struct hooks }; template< class ValueType - , class Option1 = boost::intrusive::none - , class Option2 = boost::intrusive::none - , class Option3 = boost::intrusive::none + , class Option1 =void + , class Option2 =void + , class Option3 =void > struct GetContainer { diff --git a/test/splay_set_test.cpp b/test/splay_set_test.cpp index 62c0bae..a22accd 100644 --- a/test/splay_set_test.cpp +++ b/test/splay_set_test.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 @@ -17,22 +17,6 @@ namespace boost { namespace intrusive { namespace test { -#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES) -template -#else -template -#endif -struct has_const_overloads > -{ - static const bool value = false; -}; - #if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template #else @@ -102,9 +86,9 @@ struct hooks }; template< class ValueType - , class Option1 = boost::intrusive::none - , class Option2 = boost::intrusive::none - , class Option3 = boost::intrusive::none + , class Option1 =void + , class Option2 =void + , class Option3 =void > struct GetContainer { diff --git a/test/stateful_value_traits_test.cpp b/test/stateful_value_traits_test.cpp index d721bb7..c5b43ba 100644 --- a/test/stateful_value_traits_test.cpp +++ b/test/stateful_value_traits_test.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 diff --git a/test/test_container.hpp b/test/test_container.hpp index e46083a..522d93e 100644 --- a/test/test_container.hpp +++ b/test/test_container.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 @@ -27,12 +27,6 @@ struct is_unordered static const bool value = false; }; -template -struct has_const_overloads -{ - static const bool value = true; -}; - template< class Container > void test_container( Container & c ) { @@ -290,7 +284,7 @@ void test_common_unordered_and_associative_container(Container & c, Data & d) } template< class Container, class Data > -void test_associative_container_invariants(Container & c, Data & d, boost::intrusive::detail::true_type) +void test_associative_container_invariants(Container & c, Data & d) { typedef typename Container::const_iterator const_iterator; for( typename Data::const_iterator di = d.begin(), de = d.end(); @@ -316,19 +310,6 @@ void test_associative_container_invariants(Container & c, Data & d, boost::intru } } -template< class Container, class Data > -void test_associative_container_invariants(Container &, Data &, boost::intrusive::detail::false_type) -{} - -template< class Container, class Data > -void test_associative_container_invariants(Container & c, Data & d) -{ - using namespace boost::intrusive; - typedef typename detail::remove_const::type Type; - typedef detail::bool_::value> enabler; - test_associative_container_invariants(c, d, enabler()); -} - template< class Container, class Data > void test_associative_container(Container & c, Data & d) { @@ -346,7 +327,7 @@ void test_associative_container(Container & c, Data & d) } template< class Container, class Data > -void test_unordered_associative_container_invariants(Container & c, Data & d, boost::intrusive::detail::true_type) +void test_unordered_associative_container_invariants(Container & c, Data & d) { typedef typename Container::size_type size_type; typedef typename Container::const_iterator const_iterator; @@ -380,19 +361,6 @@ void test_unordered_associative_container_invariants(Container & c, Data & d, bo BOOST_TEST( total_objects == c.size() ); } -template< class Container, class Data > -void test_unordered_associative_container_invariants(Container &, Data &, boost::intrusive::detail::false_type) -{} - -template< class Container, class Data > -void test_unordered_associative_container_invariants(Container & c, Data & d) -{ - using namespace boost::intrusive; - typedef typename detail::remove_const::type Type; - typedef detail::bool_::value> enabler; - test_unordered_associative_container_invariants(c, d, enabler()); -} - template< class Container, class Data > void test_unordered_associative_container(Container & c, Data & d) { diff --git a/test/test_macros.hpp b/test/test_macros.hpp index 92b4ddc..09aae3e 100644 --- a/test/test_macros.hpp +++ b/test/test_macros.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012 +// (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 diff --git a/test/treap_multiset_test.cpp b/test/treap_multiset_test.cpp index 7f555e4..1982397 100644 --- a/test/treap_multiset_test.cpp +++ b/test/treap_multiset_test.cpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2012. +// (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 @@ -55,9 +55,9 @@ struct hooks }; template< class ValueType - , class Option1 = boost::intrusive::none - , class Option2 = boost::intrusive::none - , class Option3 = boost::intrusive::none + , class Option1 =void + , class Option2 =void + , class Option3 =void > struct GetContainer { diff --git a/test/treap_set_test.cpp b/test/treap_set_test.cpp index 98a9a53..f0deb47 100644 --- a/test/treap_set_test.cpp +++ b/test/treap_set_test.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2012. +// (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 @@ -70,9 +70,9 @@ struct hooks }; template< class ValueType - , class Option1 = boost::intrusive::none - , class Option2 = boost::intrusive::none - , class Option3 = boost::intrusive::none + , class Option1 =void + , class Option2 =void + , class Option3 =void > struct GetContainer { diff --git a/test/unordered_multiset_test.cpp b/test/unordered_multiset_test.cpp index 0ca6e78..a4da129 100644 --- a/test/unordered_multiset_test.cpp +++ b/test/unordered_multiset_test.cpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2012. +// (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 diff --git a/test/unordered_set_test.cpp b/test/unordered_set_test.cpp index 5cba389..4555405 100644 --- a/test/unordered_set_test.cpp +++ b/test/unordered_set_test.cpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2012. +// (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 diff --git a/test/virtual_base_test.cpp b/test/virtual_base_test.cpp index 1b3c8fa..b673c1a 100644 --- a/test/virtual_base_test.cpp +++ b/test/virtual_base_test.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2012 +// (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 @@ -57,6 +57,7 @@ typedef list List; int main() { + #ifndef _MSC_VER typedef std::vector::iterator VectIt; typedef std::vector::reverse_iterator VectRit; @@ -81,6 +82,6 @@ int main() if(&*list_it != &*vect_it) return 1; } - + #endif return 0; }