mirror of
https://github.com/boostorg/intrusive.git
synced 2025-05-09 23:03:56 +00:00
Reverted git mess.
This commit is contained in:
parent
27e5ad9183
commit
68fa82e5e8
@ -33,10 +33,12 @@ doxygen autodoc
|
||||
\"BOOST_RV_REF_END=&&\" \\
|
||||
\"list_impl=list\" \\
|
||||
\"slist_impl=slist\" \\
|
||||
\"bstree_impl=bstree\" \\
|
||||
\"bs_set_impl=bs_set\" \\
|
||||
\"bs_multiset_impl=bs_multiset\" \\
|
||||
\"rbtree_impl=rbtree\" \\
|
||||
\"set_impl=set\" \\
|
||||
\"multiset_impl=multiset\" \\
|
||||
\"bstree_impl=bstree\" \\
|
||||
\"rbtree_impl=rbtree\" \\
|
||||
\"unordered_set_impl=unordered_set\" \\
|
||||
\"unordered_multiset_impl=unordered_multiset\" \\
|
||||
\"hashtable_impl=hashtable\" \\
|
||||
@ -51,7 +53,9 @@ doxygen autodoc
|
||||
\"avltree_impl=avltree\" \\
|
||||
\"treap_set_impl=treap_set\" \\
|
||||
\"treap_multiset_impl=treap_multiset\" \\
|
||||
\"treap_impl=treap\""
|
||||
\"treap_impl=treap\" \\
|
||||
\"BOOST_INTRUSIVE_OPTION_CONSTANT(OPTION_NAME, TYPE, VALUE, CONSTANT_NAME) = template<TYPE VALUE> struct OPTION_NAME{};\" \\
|
||||
\"BOOST_INTRUSIVE_OPTION_TYPE(OPTION_NAME, TYPE, TYPEDEF_EXPR, TYPEDEF_NAME) = template<class TYPE> struct OPTION_NAME{};\" "
|
||||
;
|
||||
|
||||
xml intrusive : intrusive.qbk
|
||||
|
@ -871,11 +871,11 @@ the section [link intrusive.usage How to use Boost.Intrusive]:
|
||||
* [*`linear<bool Enable>`]: the singly linked list is implemented as a
|
||||
null-terminated list instead of a circular list. This allows `O(1)` swap,
|
||||
but losses some operations like `container_from_end_iterator`.
|
||||
* [*`cache_last<bool Enable>`]: the singly linked also stores a pointer to the
|
||||
* [*`cache_last<bool Enable>`]: `slist` also stores a pointer to the
|
||||
last element of the singly linked list. This allows `O(1)` swap,
|
||||
`splice_after(iterator, slist &)` and makes the list offer new functions
|
||||
like `push_back(reference)` and `back()`. Logically, the size an empty list is
|
||||
increased in `sizeof(void_pointer)` and the the cached last node pointer must
|
||||
increased in `sizeof(void_pointer)` and the cached last node pointer must
|
||||
be updated in every operation, and that might incur in a slight performance impact.
|
||||
|
||||
`auto_unlink` hooks are not usable if `linear<true>` and/or `cache_last<true>` options are
|
||||
@ -1364,163 +1364,6 @@ the unordered container:
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:splay_set_multiset Intrusive splay tree based associative containers: splay_set, splay_multiset and , splay_tree]
|
||||
|
||||
C++ associative containers are usually based on red-black tree implementations (e.g.: STL,
|
||||
Boost.Intrusive associative containers). However, there are other interesting data
|
||||
structures that offer some advantages (and also disadvantages).
|
||||
|
||||
Splay trees are self-adjusting binary search trees used typically in caches, memory
|
||||
allocators and other applications, because splay trees have a "caching effect": recently
|
||||
accessed elements have better access times than elements accessed less frequently.
|
||||
For more information on splay trees see [@http://en.wikipedia.org/wiki/Splay_tree Wikipedia entry].
|
||||
|
||||
[*Boost.Intrusive] offers 3 containers based on splay trees:
|
||||
[classref boost::intrusive::splay_set splay_set],
|
||||
[classref boost::intrusive::splay_multiset splay_multiset] and
|
||||
[classref boost::intrusive::splaytree splaytree]. The first two are similar to
|
||||
[classref boost::intrusive::set set] or
|
||||
[classref boost::intrusive::multiset multiset] and the latter is a generalization
|
||||
that offers functions both to insert unique and multiple keys.
|
||||
|
||||
The memory overhead of these containers with Boost.Intrusive hooks is usually 3 pointers.
|
||||
An empty, non constant-time size splay container has also a size of 3 pointers.
|
||||
|
||||
[section:splay_set_multiset_disadvantages Advantages and disadvantages of splay tree based containers]
|
||||
|
||||
Splay tree based intrusive containers have logarithmic complexity in many
|
||||
operations like searches, insertions, erasures, etc., but if some elements are
|
||||
more frequently accessed than others, splay trees perform faster searches than equivalent
|
||||
balanced binary trees (such as red-black trees).
|
||||
|
||||
The caching effect offered by splay trees comes with a cost: the tree must be
|
||||
rebalanced when an element is searched. This disallows const versions of search
|
||||
functions like `find()`, `lower_bound()`, `upper_bound()`, `equal_range()`,
|
||||
`count()`, etc.
|
||||
|
||||
Because of this, splay-tree based associative containers are not drop-in
|
||||
replacements of [classref boost::intrusive::set set]/
|
||||
[classref boost::intrusive::multiset multiset].
|
||||
|
||||
Apart from this, if element searches are randomized, the tree will be rebalanced
|
||||
without taking advantage of the cache effect, so splay trees can offer worse
|
||||
performance than other balanced trees for some search patterns.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:splay_set_multiset_hooks splay_set, splay_multiset and splaytree hooks]
|
||||
|
||||
[classref boost::intrusive::splay_set splay_set],
|
||||
[classref boost::intrusive::splay_multiset splay_multiset] and
|
||||
[classref boost::intrusive::splaytree splaytree]
|
||||
share the same hooks.
|
||||
|
||||
[c++]
|
||||
|
||||
template <class ...Options>
|
||||
class splay_set_base_hook;
|
||||
|
||||
* [classref boost::intrusive::splay_set_base_hook splay_set_base_hook]:
|
||||
the user class derives publicly from this class to make
|
||||
it compatible with splay tree based containers.
|
||||
|
||||
[c++]
|
||||
|
||||
template <class ...Options>
|
||||
class splay_set_member_hook;
|
||||
|
||||
* [classref boost::intrusive::set_member_hook set_member_hook]:
|
||||
the user class contains a public member of this class to make
|
||||
it compatible with splay tree based containers.
|
||||
|
||||
[classref boost::intrusive::splay_set_base_hook splay_set_base_hook] and
|
||||
[classref boost::intrusive::splay_set_member_hook splay_set_member_hook] receive
|
||||
the same options explained in the section
|
||||
[link intrusive.usage How to use Boost.Intrusive]:
|
||||
|
||||
* [*`tag<class Tag>`] (for base hooks only): This argument serves as a tag,
|
||||
so you can derive from more than one base hook.
|
||||
Default: `tag<default_tag>`.
|
||||
|
||||
* [*`link_mode<link_mode_type LinkMode>`]: The linking policy.
|
||||
Default: `link_mode<safe_link>`.
|
||||
|
||||
* [*`void_pointer<class VoidPointer>`]: The pointer type to be used
|
||||
internally in the hook and propagated to the container.
|
||||
Default: `void_pointer<void*>`.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:set_multiset_containers splay_set, splay_multiset and splaytree containers]
|
||||
|
||||
[c++]
|
||||
|
||||
template <class T, class ...Options>
|
||||
class splay_set;
|
||||
|
||||
template <class T, class ...Options>
|
||||
class splay_multiset;
|
||||
|
||||
template <class T, class ...Options>
|
||||
class splaytree;
|
||||
|
||||
These containers receive the same options explained in the section
|
||||
[link intrusive.usage How to use Boost.Intrusive]:
|
||||
|
||||
* [*`base_hook<class Hook>`] / [*`member_hook<class T, class Hook, Hook T::* PtrToMember>`] /
|
||||
[*`value_traits<class ValueTraits>`]: To specify the hook type or value traits used
|
||||
to configure the container. (To learn about value traits go to the section
|
||||
[link intrusive.value_traits Containers with custom ValueTraits].)
|
||||
|
||||
* [*`constant_time_size<bool Enabled>`]: To activate the constant-time `size()` operation.
|
||||
Default: `constant_time_size<true>`
|
||||
|
||||
* [*`size_type<bool Enabled>`]: To specify the type that will be used to store the size
|
||||
of the container. Default: `size_type<std::size_t>`
|
||||
|
||||
And they also can receive an additional option:
|
||||
|
||||
* [*`compare<class Compare>`]: Comparison function for the objects to be inserted
|
||||
in containers. The comparison functor must induce a strict weak ordering.
|
||||
Default: `compare< std::less<T> >`
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:splay_set_bst_hook Splay trees with BST hooks]
|
||||
|
||||
Intrusive splay containers can also use plain binary search tree hooks
|
||||
[classref boost::intrusive::bs_set_base_hook bs_set_base_hook] and
|
||||
[classref boost::intrusive::bs_set_base_hook bs_set_base_hook].
|
||||
These hooks can be used by other intrusive containers like
|
||||
intrusive scapegoat containers
|
||||
[classref boost::intrusive::sg_set sg_set] and
|
||||
[classref boost::intrusive::sg_multiset sg_multiset]. A programmer
|
||||
might prefer using a binary search tree hook so that the same type
|
||||
can be inserted in some situations in a splay container but
|
||||
also inserted in other compatible containers when
|
||||
the hook is not being used in a splay container.
|
||||
|
||||
[classref boost::intrusive::bs_set_base_hook bs_set_base_hook] and
|
||||
[classref boost::intrusive::bs_set_base_hook bs_set_member_hook] admit
|
||||
the same options as [classref boost::intrusive::splay_set_base_hook splay_set_base_hook].
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:splay_set_multiset_example Example]
|
||||
|
||||
Now let's see a small example using both splay hooks,
|
||||
binary search tree hooks and
|
||||
[classref boost::intrusive::splay_set splay_set]/
|
||||
[classref boost::intrusive::splay_multiset splay_multiset]
|
||||
containers:
|
||||
|
||||
[import ../example/doc_splay_set.cpp]
|
||||
[doc_splay_set_code]
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:avl_set_multiset Intrusive avl tree based associative containers: avl_set, avl_multiset and avltree]
|
||||
|
||||
Similar to red-black trees, AVL trees are balanced binary trees.
|
||||
@ -1649,6 +1492,103 @@ containers:
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:splay_set_multiset Intrusive splay tree based associative containers: splay_set, splay_multiset and , splay_tree]
|
||||
|
||||
C++ associative containers are usually based on red-black tree implementations (e.g.: STL,
|
||||
Boost.Intrusive associative containers). However, there are other interesting data
|
||||
structures that offer some advantages (and also disadvantages).
|
||||
|
||||
Splay trees are self-adjusting binary search trees used typically in caches, memory
|
||||
allocators and other applications, because splay trees have a "caching effect": recently
|
||||
accessed elements have better access times than elements accessed less frequently.
|
||||
For more information on splay trees see [@http://en.wikipedia.org/wiki/Splay_tree the corresponding Wikipedia entry].
|
||||
|
||||
[*Boost.Intrusive] offers 3 containers based on splay trees:
|
||||
[classref boost::intrusive::splay_set splay_set],
|
||||
[classref boost::intrusive::splay_multiset splay_multiset] and
|
||||
[classref boost::intrusive::splaytree splaytree]. The first two are similar to
|
||||
[classref boost::intrusive::set set] or
|
||||
[classref boost::intrusive::multiset multiset] and the latter is a generalization
|
||||
that offers functions both to insert unique and multiple keys.
|
||||
|
||||
The memory overhead of these containers with Boost.Intrusive hooks is usually 3 pointers.
|
||||
An empty, non constant-time size splay container has also a size of 3 pointers.
|
||||
|
||||
[section:splay_set_multiset_disadvantages Advantages and disadvantages of splay tree based containers]
|
||||
|
||||
Splay tree based intrusive containers have logarithmic complexity in many
|
||||
operations like searches, insertions, erasures, etc., but if some elements are
|
||||
more frequently accessed than others, splay trees perform faster searches than equivalent
|
||||
balanced binary trees (such as red-black trees).
|
||||
|
||||
The caching effect offered by splay trees comes with a cost: the tree must be
|
||||
rebalanced when an element is searched. To maintain const-correctness and thread-safety
|
||||
guarantees, this caching effect is not updated when const versions of
|
||||
search functions like `find()`, `lower_bound()`, `upper_bound()`, `equal_range()`,
|
||||
`count()`... are called. This means that using splay-tree based associative containers as drop-in
|
||||
replacements of [classref boost::intrusive::set set]/
|
||||
[classref boost::intrusive::multiset multiset], specially for const search functions,
|
||||
might not result in desired performance improvements.
|
||||
|
||||
If element searches are randomized, the tree will be continuously srebalanced
|
||||
without taking advantage of the cache effect, so splay trees can offer worse
|
||||
performance than other balanced trees for several search patterns.
|
||||
|
||||
[*Boost.Intrusive] splay associative containers don't use their own hook types but plain Binary search tree hooks.
|
||||
See [link intrusive.bst_hooks Binary search tree hooks: bs_set_base_hook and bs_set_member_hook] section for more
|
||||
information about these hooks.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:set_multiset_containers splay_set, splay_multiset and splaytree containers]
|
||||
|
||||
[c++]
|
||||
|
||||
template <class T, class ...Options>
|
||||
class splay_set;
|
||||
|
||||
template <class T, class ...Options>
|
||||
class splay_multiset;
|
||||
|
||||
template <class T, class ...Options>
|
||||
class splaytree;
|
||||
|
||||
These containers receive the same options explained in the section
|
||||
[link intrusive.usage How to use Boost.Intrusive]:
|
||||
|
||||
* [*`base_hook<class Hook>`] / [*`member_hook<class T, class Hook, Hook T::* PtrToMember>`] /
|
||||
[*`value_traits<class ValueTraits>`]: To specify the hook type or value traits used
|
||||
to configure the container. (To learn about value traits go to the section
|
||||
[link intrusive.value_traits Containers with custom ValueTraits].)
|
||||
|
||||
* [*`constant_time_size<bool Enabled>`]: To activate the constant-time `size()` operation.
|
||||
Default: `constant_time_size<true>`
|
||||
|
||||
* [*`size_type<bool Enabled>`]: To specify the type that will be used to store the size
|
||||
of the container. Default: `size_type<std::size_t>`
|
||||
|
||||
And they also can receive an additional option:
|
||||
|
||||
* [*`compare<class Compare>`]: Comparison function for the objects to be inserted
|
||||
in containers. The comparison functor must induce a strict weak ordering.
|
||||
Default: `compare< std::less<T> >`
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:splay_set_multiset_example Example]
|
||||
|
||||
Now let's see a small example using
|
||||
[classref boost::intrusive::splay_set splay_set]/
|
||||
[classref boost::intrusive::splay_multiset splay_multiset]
|
||||
containers:
|
||||
|
||||
[import ../example/doc_splay_set.cpp]
|
||||
[doc_splay_set_code]
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[section:sg_set_multiset Intrusive scapegoat tree based associative containers: sg_set, sg_multiset and sgtree]
|
||||
|
||||
@ -1705,50 +1645,9 @@ An empty, [classref boost::intrusive::sg_set sg_set],
|
||||
has also the size of 3 pointers, two integers and two floating point values
|
||||
(equivalent to the size of 7 pointers on most systems).
|
||||
|
||||
[section:sg_set_multiset_hooks Using binary search tree hooks: bs_set_base_hook and bs_set_member_hook]
|
||||
|
||||
[classref boost::intrusive::sg_set sg_set],
|
||||
[classref boost::intrusive::sg_multiset sg_multiset] and
|
||||
[classref boost::intrusive::sgtree sgtree] don't use their
|
||||
own hooks but plain binary search tree hooks. This has many advantages
|
||||
since binary search tree hooks can also be used to insert values in
|
||||
splay and treap containers.
|
||||
|
||||
[c++]
|
||||
|
||||
template <class ...Options>
|
||||
class bs_set_base_hook;
|
||||
|
||||
* [classref boost::intrusive::bs_set_base_hook bs_set_base_hook]:
|
||||
the user class derives publicly from this class to make
|
||||
it compatible with scapegoat tree based containers.
|
||||
|
||||
[c++]
|
||||
|
||||
template <class ...Options>
|
||||
class bs_set_member_hook;
|
||||
|
||||
* [classref boost::intrusive::set_member_hook set_member_hook]:
|
||||
the user class contains a public member of this class to make
|
||||
it compatible with scapegoat tree based containers.
|
||||
|
||||
[classref boost::intrusive::bs_set_base_hook bs_set_base_hook] and
|
||||
[classref boost::intrusive::bs_set_member_hook bs_set_member_hook] receive
|
||||
the same options explained in the section
|
||||
[link intrusive.usage How to use Boost.Intrusive]:
|
||||
|
||||
* [*`tag<class Tag>`] (for base hooks only): This argument serves as a tag,
|
||||
so you can derive from more than one base hook.
|
||||
Default: `tag<default_tag>`.
|
||||
|
||||
* [*`link_mode<link_mode_type LinkMode>`]: The linking policy.
|
||||
Default: `link_mode<safe_link>`.
|
||||
|
||||
* [*`void_pointer<class VoidPointer>`]: The pointer type to be used
|
||||
internally in the hook and propagated to the container.
|
||||
Default: `void_pointer<void*>`.
|
||||
|
||||
[endsect]
|
||||
[*Boost.Intrusive] scapegoat associative containers don't use their own hook types but plain Binary search tree hooks.
|
||||
See [link intrusive.bst_hooks Binary search tree hooks: bs_set_base_hook and bs_set_member_hook] section for more
|
||||
information about these hooks.
|
||||
|
||||
[section:sg_set_multiset_containers sg_set, sg_multiset and sgtree containers]
|
||||
|
||||
@ -1791,7 +1690,7 @@ And they also can receive additional options:
|
||||
|
||||
[section:sg_set_multiset_example Example]
|
||||
|
||||
Now let's see a small example using both hooks and
|
||||
Now let's see a small example using binary search tree hooks and
|
||||
[classref boost::intrusive::sg_set sg_set]/
|
||||
[classref boost::intrusive::sg_multiset sg_multiset]
|
||||
containers:
|
||||
@ -1841,50 +1740,9 @@ An empty, [classref boost::intrusive::treap_set treap_set],
|
||||
has also the size of 3 pointers and an integer (supposing empty function objects for key and priority
|
||||
comparison and constant-time size).
|
||||
|
||||
[section:treap_set_multiset_hooks Using binary search tree hooks: bs_set_base_hook and bs_set_member_hook]
|
||||
|
||||
[classref boost::intrusive::treap_set treap_set],
|
||||
[classref boost::intrusive::treap_multiset treap_multiset] and
|
||||
[classref boost::intrusive::treap treap] don't use their
|
||||
own hooks but plain binary search tree hooks. This has many advantages
|
||||
since binary search tree hooks can also be used to insert values in
|
||||
splay containers and scapegoat trees.
|
||||
|
||||
[c++]
|
||||
|
||||
template <class ...Options>
|
||||
class bs_set_base_hook;
|
||||
|
||||
* [classref boost::intrusive::bs_set_base_hook bs_set_base_hook]:
|
||||
the user class derives publicly from this class to make
|
||||
it compatible with scapegoat tree based containers.
|
||||
|
||||
[c++]
|
||||
|
||||
template <class ...Options>
|
||||
class bs_set_member_hook;
|
||||
|
||||
* [classref boost::intrusive::set_member_hook set_member_hook]:
|
||||
the user class contains a public member of this class to make
|
||||
it compatible with scapegoat tree based containers.
|
||||
|
||||
[classref boost::intrusive::bs_set_base_hook bs_set_base_hook] and
|
||||
[classref boost::intrusive::bs_set_member_hook bs_set_member_hook] receive
|
||||
the same options explained in the section
|
||||
[link intrusive.usage How to use Boost.Intrusive]:
|
||||
|
||||
* [*`tag<class Tag>`] (for base hooks only): This argument serves as a tag,
|
||||
so you can derive from more than one base hook.
|
||||
Default: `tag<default_tag>`.
|
||||
|
||||
* [*`link_mode<link_mode_type LinkMode>`]: The linking policy.
|
||||
Default: `link_mode<safe_link>`.
|
||||
|
||||
* [*`void_pointer<class VoidPointer>`]: The pointer type to be used
|
||||
internally in the hook and propagated to the container.
|
||||
Default: `void_pointer<void*>`.
|
||||
|
||||
[endsect]
|
||||
[*Boost.Intrusive] treap associative containers don't use their own hook types but plain Binary search tree hooks.
|
||||
See [link intrusive.bst_hooks Binary search tree hooks: bs_set_base_hook and bs_set_member_hook] section for more
|
||||
information about these hooks.
|
||||
|
||||
[section:treap_set_multiset_containers treap_set, treap_multiset and treap containers]
|
||||
|
||||
@ -1967,7 +1825,7 @@ the strongest possible behaviour in these situations. In summary:
|
||||
|
||||
[section:treap_set_multiset_example Example]
|
||||
|
||||
Now let's see a small example using both hooks and
|
||||
Now let's see a small example using binary search tree hooks and
|
||||
[classref boost::intrusive::treap_set treap_set]/
|
||||
[classref boost::intrusive::treap_multiset treap_multiset]
|
||||
containers:
|
||||
@ -1979,6 +1837,48 @@ containers:
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:bst_hooks Binary search tree hooks: bs_set_base_hook and bs_set_member_hook]
|
||||
|
||||
Binary search tree hooks can be used with several tree-like containers that don't
|
||||
need any additional metadata for rebalancing operations. This has many advantages
|
||||
since binary search tree hooks can also be used to insert values in
|
||||
plain binary search tree, splay tree, scapegoat tree, and treap containers.
|
||||
|
||||
[c++]
|
||||
|
||||
template <class ...Options>
|
||||
class bs_set_base_hook;
|
||||
|
||||
* [classref boost::intrusive::bs_set_base_hook bs_set_base_hook]:
|
||||
the user class derives publicly from this class to make
|
||||
it compatible with the mentioned tree based containers.
|
||||
|
||||
[c++]
|
||||
|
||||
template <class ...Options>
|
||||
class bs_set_member_hook;
|
||||
|
||||
* [classref boost::intrusive::bs_set_member_hook bs_set_member_hook]:
|
||||
the user class contains a public member of this class to make
|
||||
it compatible with the mentioned tree based containers.
|
||||
|
||||
[classref boost::intrusive::bs_set_base_hook bs_set_base_hook] and
|
||||
[classref boost::intrusive::bs_set_member_hook bs_set_member_hook] receive
|
||||
the same options explained in the section
|
||||
[link intrusive.usage How to use Boost.Intrusive]:
|
||||
|
||||
* [*`tag<class Tag>`] (for base hooks only): This argument serves as a tag,
|
||||
so you can derive from more than one base hook.
|
||||
Default: `tag<default_tag>`.
|
||||
|
||||
* [*`link_mode<link_mode_type LinkMode>`]: The linking policy.
|
||||
Default: `link_mode<safe_link>`.
|
||||
|
||||
* [*`void_pointer<class VoidPointer>`]: The pointer type to be used
|
||||
internally in the hook and propagated to the container.
|
||||
Default: `void_pointer<void*>`.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:advanced_lookups_insertions Advanced lookup and insertion functions for associative containers]
|
||||
|
||||
@ -3582,7 +3482,7 @@ and also derives from `test_class`.
|
||||
`func_ptr_adaptor` is just a functor adaptor to convert function objects taking
|
||||
`test_list` objects to function objects taking pointers to them.
|
||||
|
||||
You can find the full test code code in the
|
||||
You can find the full test code in the
|
||||
[@../../libs/intrusive/perf/perf_list.cpp perf_list.cpp] source file.
|
||||
|
||||
[section:performance_results_push_back Back insertion and destruction]
|
||||
@ -3884,10 +3784,28 @@ to be inserted in intrusive containers are allocated using `std::vector` or `std
|
||||
|
||||
[section:release_notes Release Notes]
|
||||
|
||||
[section:release_notes_boost_1_56_00 Boost 1.56 Release]
|
||||
|
||||
* Improved Doxygen generated reference and updated and fixed forward-declaration header.
|
||||
|
||||
* [*ABI breaking]: Fixed ABI regression introduced in Boost 1.55 version, mainly noticeable on MSVC compilers.
|
||||
|
||||
* [*Source breaking]: Removed previously deprecated `xxx_dont_splay` functions from splay containers,
|
||||
`splay_set_base_hook` and `splay_set_member_hook`from splay containers and `bool splay = true`
|
||||
extra parameter is `splaytree_algorithms` functions.
|
||||
|
||||
* Fixed bugs:
|
||||
* [@https://svn.boost.org/trac/boost/ticket/9332 #9332: ['"has_member_function_callable_with.hpp compile error on msvc-12.0"]].
|
||||
|
||||
* Optimized tree rebalancing code to avoid redundant assignments.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:release_notes_boost_1_55_00 Boost 1.55 Release]
|
||||
|
||||
* [*Source breaking]: Deprecated `xxx_dont_splay` functions from splay containers.
|
||||
Deprecated `splay_set_hook` from splay containers, use `bs_set_hook` instead.
|
||||
Deprecated `splay_set_base_hook` and `splay_set_member_hook`from splay containers, use
|
||||
`bs_set_base_hook` or `bs_set_member_hook` instead.
|
||||
Both will be removed in Boost 1.56.
|
||||
|
||||
* [*ABI breaking]: Hash containers' end iterator was implemented pointing to one-past the end of the bucket array
|
||||
|
@ -24,7 +24,8 @@ class MyClass : public auto_unlink_hook
|
||||
|
||||
public:
|
||||
MyClass(int i = 0) : int_(i) {}
|
||||
void unlink() { auto_unlink_hook::unlink(); }
|
||||
int get_int() { return int_; }
|
||||
void unlink() { auto_unlink_hook::unlink(); }
|
||||
bool is_linked() { return auto_unlink_hook::is_linked(); }
|
||||
};
|
||||
|
||||
|
@ -1,129 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2007-2013
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/intrusive for documentation.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//[doc_external_value_traits
|
||||
#include <boost/intrusive/list.hpp>
|
||||
#include <vector>
|
||||
|
||||
using namespace boost::intrusive;
|
||||
|
||||
//This type is not modifiable so we can't store hooks or custom nodes
|
||||
typedef int identifier_t;
|
||||
|
||||
//This value traits will associate elements from an array of identifiers with
|
||||
//elements of an array of nodes. The element i of the value array will use the
|
||||
//node i of the node array:
|
||||
class external_traits
|
||||
{
|
||||
//Non-copyable
|
||||
external_traits(const external_traits &);
|
||||
external_traits& operator=(const external_traits &);
|
||||
|
||||
public:
|
||||
typedef list_node_traits<void*> node_traits;
|
||||
typedef node_traits::node node;
|
||||
typedef node * node_ptr;
|
||||
typedef const node * const_node_ptr;
|
||||
typedef identifier_t value_type;
|
||||
typedef identifier_t * pointer;
|
||||
typedef const identifier_t * const_pointer;
|
||||
static const link_mode_type link_mode = normal_link;
|
||||
|
||||
external_traits(pointer ids, std::size_t NumElements)
|
||||
: ids_(ids), nodes_(NumElements)
|
||||
{}
|
||||
|
||||
///Note: non static functions!
|
||||
node_ptr to_node_ptr (value_type &value)
|
||||
{ return &this->nodes_[0] + (&value - this->ids_); }
|
||||
const_node_ptr to_node_ptr (const value_type &value) const
|
||||
{ return &this->nodes_[0] + (&value - this->ids_); }
|
||||
pointer to_value_ptr(node_ptr n)
|
||||
{ return this->ids_ + (n - &this->nodes_[0]); }
|
||||
const_pointer to_value_ptr(const_node_ptr n) const
|
||||
{ return this->ids_ + (n - &this->nodes_[0]); }
|
||||
|
||||
private:
|
||||
pointer ids_;
|
||||
//This is an array of nodes that is necessary to form the linked list
|
||||
std::vector<list_node_traits<void*>::node> nodes_;
|
||||
};
|
||||
|
||||
//This is the value traits class that will be stored in the container
|
||||
//and that will lead to the external traits using the address
|
||||
//of the container.
|
||||
struct internal_traits
|
||||
{
|
||||
static const bool external_value_traits = true;
|
||||
typedef external_traits value_traits;
|
||||
|
||||
template<class Container>
|
||||
value_traits &get_value_traits(Container &cont);
|
||||
|
||||
template<class Container>
|
||||
const value_traits &get_value_traits(const Container &cont) const;
|
||||
};
|
||||
|
||||
//The intrusive list that will use external value traits
|
||||
typedef list<identifier_t, value_traits<internal_traits> > List;
|
||||
|
||||
class data_holder
|
||||
: public List
|
||||
{
|
||||
public:
|
||||
data_holder(identifier_t *ids, std::size_t NumElements)
|
||||
: List()
|
||||
, external_traits_(ids, NumElements)
|
||||
{}
|
||||
external_traits external_traits_;
|
||||
};
|
||||
|
||||
template<class Container>
|
||||
internal_traits::value_traits &internal_traits::get_value_traits(Container &cont)
|
||||
{ return static_cast<data_holder&>(cont).external_traits_; }
|
||||
|
||||
template<class Container>
|
||||
const internal_traits::value_traits &internal_traits::get_value_traits(const Container &cont) const
|
||||
{ return static_cast<const data_holder&>(cont).external_traits_; }
|
||||
|
||||
int main()
|
||||
{
|
||||
const int NumElements = 100;
|
||||
|
||||
//This is an array of ids that we want to "store"
|
||||
identifier_t ids [NumElements];
|
||||
|
||||
//Initialize id objects, each one with a different number
|
||||
for(int i = 0; i != NumElements; ++i) ids[i] = i;
|
||||
|
||||
//The data holding the list and the external traits
|
||||
data_holder data(ids, NumElements);
|
||||
|
||||
//This list will store ids without modifying identifier_t instances
|
||||
//Stateful value traits must be explicitly passed in the constructor.
|
||||
List &my_list = data;
|
||||
|
||||
//Insert ids in reverse order in the list
|
||||
for(identifier_t * it(&ids[0]), *itend(&ids[NumElements]); it != itend; ++it)
|
||||
my_list.push_front(*it);
|
||||
|
||||
//Now test lists
|
||||
List::const_iterator list_it (my_list.cbegin());
|
||||
identifier_t *it_val(&ids[NumElements]-1), *it_rbeg_val(&ids[0] -1);
|
||||
|
||||
//Test the objects inserted in the base hook list
|
||||
for(; it_val != it_rbeg_val; --it_val, ++list_it){
|
||||
if(&*list_it != &*it_val) return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
//]
|
@ -11,7 +11,6 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//[doc_splay_set_code
|
||||
#include <boost/intrusive/splay_set.hpp>
|
||||
#include <boost/intrusive/bs_set_hook.hpp>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
@ -20,14 +19,13 @@ using namespace boost::intrusive;
|
||||
class mytag;
|
||||
|
||||
class MyClass
|
||||
: public splay_set_base_hook<> //This is an splay tree base hook
|
||||
, public bs_set_base_hook< tag<mytag> > //This is a binary search tree base hook
|
||||
: public bs_set_base_hook<>
|
||||
{
|
||||
int int_;
|
||||
|
||||
public:
|
||||
//This is a member hook
|
||||
splay_set_member_hook<> member_hook_;
|
||||
bs_set_member_hook<> member_hook_;
|
||||
|
||||
MyClass(int i)
|
||||
: int_(i)
|
||||
@ -43,11 +41,8 @@ class MyClass
|
||||
//Define a set using the base hook that will store values in reverse order
|
||||
typedef splay_set< MyClass, compare<std::greater<MyClass> > > BaseSplaySet;
|
||||
|
||||
//Define a set using the binary search tree hook
|
||||
typedef splay_set< MyClass, base_hook<bs_set_base_hook< tag<mytag> > > > BaseBsSplaySet;
|
||||
|
||||
//Define an multiset using the member hook
|
||||
typedef member_hook<MyClass, splay_set_member_hook<>, &MyClass::member_hook_> MemberOption;
|
||||
typedef member_hook<MyClass, bs_set_member_hook<>, &MyClass::member_hook_> MemberOption;
|
||||
typedef splay_multiset< MyClass, MemberOption> MemberSplayMultiset;
|
||||
|
||||
int main()
|
||||
@ -59,21 +54,18 @@ int main()
|
||||
for(int i = 0; i < 100; ++i) values.push_back(MyClass(i));
|
||||
|
||||
BaseSplaySet baseset;
|
||||
BaseBsSplaySet bsbaseset;
|
||||
MemberSplayMultiset membermultiset;
|
||||
|
||||
|
||||
//Insert values in the container
|
||||
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it){
|
||||
baseset.insert(*it);
|
||||
bsbaseset.insert(*it);
|
||||
membermultiset.insert(*it);
|
||||
}
|
||||
|
||||
//Now test sets
|
||||
{
|
||||
BaseSplaySet::reverse_iterator rbit(baseset.rbegin());
|
||||
BaseBsSplaySet::iterator bsit(bsbaseset.begin());
|
||||
MemberSplayMultiset::iterator mit(membermultiset.begin());
|
||||
VectIt it(values.begin()), itend(values.end());
|
||||
|
||||
@ -83,8 +75,7 @@ int main()
|
||||
}
|
||||
|
||||
//Test the objects inserted in member and binary search hook sets
|
||||
for(it = values.begin(); it != itend; ++it, ++bsit, ++mit){
|
||||
if(&*bsit != &*it) return 1;
|
||||
for(it = values.begin(); it != itend; ++it, ++mit){
|
||||
if(&*mit != &*it) return 1;
|
||||
}
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ struct make_any_base_hook
|
||||
//! \c link_mode<> will specify the linking mode of the hook (\c normal_link, \c safe_link).
|
||||
//!
|
||||
//! \c void_pointer<> is the pointer type that will be used internally in the hook
|
||||
//! and the the container configured to use this hook.
|
||||
//! and the container configured to use this hook.
|
||||
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template<class ...Options>
|
||||
#else
|
||||
@ -175,7 +175,7 @@ struct make_any_member_hook
|
||||
//! \c link_mode<> will specify the linking mode of the hook (\c normal_link or \c safe_link).
|
||||
//!
|
||||
//! \c void_pointer<> is the pointer type that will be used internally in the hook
|
||||
//! and the the container configured to use this hook.
|
||||
//! and the container configured to use this hook.
|
||||
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template<class ...Options>
|
||||
#else
|
||||
|
@ -249,13 +249,19 @@ class avl_set_impl
|
||||
template<class Disposer>
|
||||
void clear_and_dispose(Disposer disposer);
|
||||
|
||||
#endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
|
||||
//! @copydoc ::boost::intrusive::avltree::count(const_reference)const
|
||||
size_type count(const_reference value) const;
|
||||
size_type count(const_reference value) const
|
||||
{ return static_cast<size_type>(this->tree_type::find(value) != this->tree_type::cend()); }
|
||||
|
||||
//! @copydoc ::boost::intrusive::avltree::count(const KeyType&,KeyValueCompare)const
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
size_type count(const KeyType& key, KeyValueCompare comp) const;
|
||||
|
||||
size_type count(const KeyType& key, KeyValueCompare comp) const
|
||||
{ return static_cast<size_type>(this->tree_type::find(key, comp) != this->tree_type::cend()); }
|
||||
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
|
||||
//! @copydoc ::boost::intrusive::avltree::lower_bound(const_reference)
|
||||
iterator lower_bound(const_reference value);
|
||||
|
||||
@ -298,21 +304,29 @@ class avl_set_impl
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
const_iterator find(const KeyType& key, KeyValueCompare comp) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::avltree::equal_range(const_reference)
|
||||
std::pair<iterator,iterator> equal_range(const_reference value);
|
||||
#endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
|
||||
//! @copydoc ::boost::intrusive::avltree::equal_range(const KeyType&,KeyValueCompare)
|
||||
//! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference)
|
||||
std::pair<iterator,iterator> equal_range(const_reference value)
|
||||
{ return this->tree_type::lower_bound_range(value); }
|
||||
|
||||
//! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare)
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
std::pair<iterator,iterator> equal_range(const KeyType& key, KeyValueCompare comp);
|
||||
std::pair<iterator,iterator> equal_range(const KeyType& key, KeyValueCompare comp)
|
||||
{ return this->tree_type::lower_bound_range(key, comp); }
|
||||
|
||||
//! @copydoc ::boost::intrusive::avltree::equal_range(const_reference)const
|
||||
//! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference)const
|
||||
std::pair<const_iterator, const_iterator>
|
||||
equal_range(const_reference value) const;
|
||||
equal_range(const_reference value) const
|
||||
{ return this->tree_type::lower_bound_range(value); }
|
||||
|
||||
//! @copydoc ::boost::intrusive::avltree::equal_range(const KeyType&,KeyValueCompare)const
|
||||
//! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare)const
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
std::pair<const_iterator, const_iterator>
|
||||
equal_range(const KeyType& key, KeyValueCompare comp) const;
|
||||
equal_range(const KeyType& key, KeyValueCompare comp) const
|
||||
{ return this->tree_type::lower_bound_range(key, comp); }
|
||||
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
|
||||
//! @copydoc ::boost::intrusive::avltree::bounded_range(const_reference,const_reference,bool,bool)
|
||||
std::pair<iterator,iterator> bounded_range
|
||||
@ -692,7 +706,7 @@ class avl_multiset_impl
|
||||
//! @copydoc ::boost::intrusive::avltree::count(const KeyType&,KeyValueCompare)const
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
size_type count(const KeyType& key, KeyValueCompare comp) const;
|
||||
|
||||
|
||||
//! @copydoc ::boost::intrusive::avltree::lower_bound(const_reference)
|
||||
iterator lower_bound(const_reference value);
|
||||
|
||||
|
@ -74,7 +74,7 @@ struct make_avl_set_base_hook
|
||||
//! unique tag.
|
||||
//!
|
||||
//! \c void_pointer<> is the pointer type that will be used internally in the hook
|
||||
//! and the the container configured to use this hook.
|
||||
//! and the container configured to use this hook.
|
||||
//!
|
||||
//! \c link_mode<> will specify the linking mode of the hook (\c normal_link,
|
||||
//! \c auto_unlink or \c safe_link).
|
||||
@ -200,7 +200,7 @@ struct make_avl_set_member_hook
|
||||
//! \c link_mode<> and \c optimize_size<>.
|
||||
//!
|
||||
//! \c void_pointer<> is the pointer type that will be used internally in the hook
|
||||
//! and the the container configured to use this hook.
|
||||
//! and the container configured to use this hook.
|
||||
//!
|
||||
//! \c link_mode<> will specify the linking mode of the hook (\c normal_link,
|
||||
//! \c auto_unlink or \c safe_link).
|
||||
|
@ -13,6 +13,7 @@
|
||||
#define BOOST_INTRUSIVE_AVLTREE_HPP
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
@ -21,7 +22,6 @@
|
||||
|
||||
#include <boost/intrusive/detail/assert.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
#include <boost/intrusive/avl_set_hook.hpp>
|
||||
#include <boost/intrusive/detail/avltree_node.hpp>
|
||||
#include <boost/intrusive/bstree.hpp>
|
||||
@ -296,7 +296,7 @@ class avltree_impl
|
||||
//! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
size_type count(const KeyType& key, KeyValueCompare comp) const;
|
||||
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference)
|
||||
iterator lower_bound(const_reference value);
|
||||
|
||||
@ -487,14 +487,13 @@ class avltree
|
||||
public:
|
||||
typedef typename Base::value_compare value_compare;
|
||||
typedef typename Base::value_traits value_traits;
|
||||
typedef typename Base::real_value_traits real_value_traits;
|
||||
typedef typename Base::iterator iterator;
|
||||
typedef typename Base::const_iterator const_iterator;
|
||||
typedef typename Base::reverse_iterator reverse_iterator;
|
||||
typedef typename Base::const_reverse_iterator const_reverse_iterator;
|
||||
|
||||
//Assert if passed value traits are compatible with the type
|
||||
BOOST_STATIC_ASSERT((detail::is_same<typename real_value_traits::value_type, T>::value));
|
||||
BOOST_STATIC_ASSERT((detail::is_same<typename value_traits::value_type, T>::value));
|
||||
|
||||
explicit avltree( const value_compare &cmp = value_compare()
|
||||
, const value_traits &v_traits = value_traits())
|
||||
|
@ -15,9 +15,9 @@
|
||||
#define BOOST_INTRUSIVE_AVLTREE_ALGORITHMS_HPP
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
|
||||
#include <boost/intrusive/detail/assert.hpp>
|
||||
#include <boost/intrusive/detail/utilities.hpp>
|
||||
@ -49,15 +49,6 @@ struct avltree_node_cloner
|
||||
}
|
||||
};
|
||||
|
||||
template<class NodeTraits>
|
||||
struct avltree_erase_fixup
|
||||
{
|
||||
typedef typename NodeTraits::node_ptr node_ptr;
|
||||
|
||||
void operator()(const node_ptr & to_erase, const node_ptr & successor)
|
||||
{ NodeTraits::set_balance(successor, NodeTraits::get_balance(to_erase)); }
|
||||
};
|
||||
|
||||
/// @endcond
|
||||
|
||||
//! avltree_algorithms is configured with a NodeTraits class, which encapsulates the
|
||||
@ -225,7 +216,10 @@ class avltree_algorithms
|
||||
static node_ptr erase(const node_ptr & header, const node_ptr & z)
|
||||
{
|
||||
typename bstree_algo::data_for_rebalance info;
|
||||
bstree_algo::erase(header, z, avltree_erase_fixup<NodeTraits>(), info);
|
||||
bstree_algo::erase(header, z, info);
|
||||
if(info.y != z){
|
||||
NodeTraits::set_balance(info.y, NodeTraits::get_balance(z));
|
||||
}
|
||||
//Rebalance avltree
|
||||
rebalance_after_erasure(header, info.x, info.x_parent);
|
||||
return z;
|
||||
@ -274,6 +268,7 @@ class avltree_algorithms
|
||||
//! @copydoc ::boost::intrusive::bstree_algorithms::count(const const_node_ptr&,const KeyType&,KeyNodePtrCompare)
|
||||
template<class KeyType, class KeyNodePtrCompare>
|
||||
static std::size_t count(const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp);
|
||||
|
||||
#endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal_upper_bound(const node_ptr&,const node_ptr&,NodePtrCompare)
|
||||
@ -357,40 +352,92 @@ class avltree_algorithms
|
||||
|
||||
|
||||
/// @cond
|
||||
static bool verify(const node_ptr &header)
|
||||
{
|
||||
std::size_t height;
|
||||
std::size_t count;
|
||||
return verify_recursion(NodeTraits::get_parent(header), count, height);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static void rebalance_after_erasure(const node_ptr & header, const node_ptr & xnode, const node_ptr & xnode_parent)
|
||||
static bool verify_recursion(node_ptr n, std::size_t &count, std::size_t &height)
|
||||
{
|
||||
if (!n){
|
||||
count = 0;
|
||||
height = 0;
|
||||
return true;
|
||||
}
|
||||
std::size_t leftcount, rightcount;
|
||||
std::size_t leftheight, rightheight;
|
||||
if(!verify_recursion(NodeTraits::get_left (n), leftcount, leftheight) ||
|
||||
!verify_recursion(NodeTraits::get_right(n), rightcount, rightheight) ){
|
||||
return false;
|
||||
}
|
||||
count = 1u + leftcount + rightcount;
|
||||
height = 1u + (leftheight > rightheight ? leftheight : rightheight);
|
||||
|
||||
//If equal height, balance must be zero
|
||||
if(rightheight == leftheight){
|
||||
if(NodeTraits::get_balance(n) != NodeTraits::zero()){
|
||||
BOOST_ASSERT(0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//If right is taller than left, then the difference must be at least 1 and the balance positive
|
||||
else if(rightheight > leftheight){
|
||||
if(rightheight - leftheight > 1 ){
|
||||
BOOST_ASSERT(0);
|
||||
return false;
|
||||
}
|
||||
else if(NodeTraits::get_balance(n) != NodeTraits::positive()){
|
||||
BOOST_ASSERT(0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//If left is taller than right, then the difference must be at least 1 and the balance negative
|
||||
else{
|
||||
if(leftheight - rightheight > 1 ){
|
||||
BOOST_ASSERT(0);
|
||||
return false;
|
||||
}
|
||||
else if(NodeTraits::get_balance(n) != NodeTraits::negative()){
|
||||
BOOST_ASSERT(0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void rebalance_after_erasure(const node_ptr & header, node_ptr x, node_ptr x_parent)
|
||||
{
|
||||
node_ptr x(xnode), x_parent(xnode_parent);
|
||||
for (node_ptr root = NodeTraits::get_parent(header); x != root; root = NodeTraits::get_parent(header)) {
|
||||
const balance x_parent_balance = NodeTraits::get_balance(x_parent);
|
||||
//Don't cache x_is_leftchild or similar because x can be null and
|
||||
//equal to both x_parent_left and x_parent_right
|
||||
const node_ptr x_parent_left (NodeTraits::get_left(x_parent));
|
||||
const node_ptr x_parent_right(NodeTraits::get_right(x_parent));
|
||||
|
||||
if(x_parent_balance == NodeTraits::zero()){
|
||||
NodeTraits::set_balance(x_parent,
|
||||
(x == NodeTraits::get_right(x_parent) ? NodeTraits::negative() : NodeTraits::positive()));
|
||||
NodeTraits::set_balance( x_parent, x == x_parent_right ? NodeTraits::negative() : NodeTraits::positive() );
|
||||
break; // the height didn't change, let's stop here
|
||||
}
|
||||
else if(x_parent_balance == NodeTraits::negative()){
|
||||
if (x == NodeTraits::get_left(x_parent)) {
|
||||
if (x == x_parent_left) { ////x is left child or x and sibling are null
|
||||
NodeTraits::set_balance(x_parent, NodeTraits::zero()); // balanced
|
||||
x = x_parent;
|
||||
x_parent = NodeTraits::get_parent(x_parent);
|
||||
}
|
||||
else {
|
||||
// x is right child
|
||||
// a is left child
|
||||
node_ptr a = NodeTraits::get_left(x_parent);
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(a);
|
||||
if (NodeTraits::get_balance(a) == NodeTraits::positive()) {
|
||||
// a MUST have a right child
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_right(a));
|
||||
rotate_left_right(x_parent, header);
|
||||
x = NodeTraits::get_parent(x_parent);
|
||||
x_parent = NodeTraits::get_parent(x);
|
||||
// x is right child (x_parent_left is the left child)
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(x_parent_left);
|
||||
if (NodeTraits::get_balance(x_parent_left) == NodeTraits::positive()) {
|
||||
// x_parent_left MUST have a right child
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_right(x_parent_left));
|
||||
x = avl_rotate_left_right(x_parent, x_parent_left, header);
|
||||
}
|
||||
else {
|
||||
rotate_right(x_parent, header);
|
||||
x = NodeTraits::get_parent(x_parent);
|
||||
x_parent = NodeTraits::get_parent(x);
|
||||
avl_rotate_right(x_parent, x_parent_left, header);
|
||||
x = x_parent_left;
|
||||
}
|
||||
|
||||
// if changed from negative to NodeTraits::positive(), no need to check above
|
||||
@ -400,28 +447,22 @@ class avltree_algorithms
|
||||
}
|
||||
}
|
||||
else if(x_parent_balance == NodeTraits::positive()){
|
||||
if (x == NodeTraits::get_right(x_parent)) {
|
||||
if (x == x_parent_right) { //x is right child or x and sibling are null
|
||||
NodeTraits::set_balance(x_parent, NodeTraits::zero()); // balanced
|
||||
x = x_parent;
|
||||
x_parent = NodeTraits::get_parent(x_parent);
|
||||
}
|
||||
else {
|
||||
// x is left child
|
||||
// a is right child
|
||||
node_ptr a = NodeTraits::get_right(x_parent);
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(a);
|
||||
if (NodeTraits::get_balance(a) == NodeTraits::negative()) {
|
||||
// a MUST have then a left child
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_left(a));
|
||||
rotate_right_left(x_parent, header);
|
||||
|
||||
x = NodeTraits::get_parent(x_parent);
|
||||
x_parent = NodeTraits::get_parent(x);
|
||||
// x is left child (x_parent_right is the right child)
|
||||
const node_ptr x_parent_right(NodeTraits::get_right(x_parent));
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(x_parent_right);
|
||||
if (NodeTraits::get_balance(x_parent_right) == NodeTraits::negative()) {
|
||||
// x_parent_right MUST have then a left child
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_left(x_parent_right));
|
||||
x = avl_rotate_right_left(x_parent, x_parent_right, header);
|
||||
}
|
||||
else {
|
||||
rotate_left(x_parent, header);
|
||||
x = NodeTraits::get_parent(x_parent);
|
||||
x_parent = NodeTraits::get_parent(x);
|
||||
avl_rotate_left(x_parent, x_parent_right, header);
|
||||
x = x_parent_right;
|
||||
}
|
||||
// if changed from NodeTraits::positive() to negative, no need to check above
|
||||
if (NodeTraits::get_balance(x) == NodeTraits::negative()){
|
||||
@ -432,47 +473,47 @@ class avltree_algorithms
|
||||
else{
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(false); // never reached
|
||||
}
|
||||
x_parent = NodeTraits::get_parent(x);
|
||||
}
|
||||
}
|
||||
|
||||
static void rebalance_after_insertion(const node_ptr & header, const node_ptr & xnode)
|
||||
static void rebalance_after_insertion(const node_ptr & header, node_ptr x)
|
||||
{
|
||||
node_ptr x(xnode);
|
||||
NodeTraits::set_balance(x, NodeTraits::zero());
|
||||
// Rebalance.
|
||||
for(node_ptr root = NodeTraits::get_parent(header); x != root; root = NodeTraits::get_parent(header)){
|
||||
const balance x_parent_balance = NodeTraits::get_balance(NodeTraits::get_parent(x));
|
||||
|
||||
node_ptr const x_parent(NodeTraits::get_parent(x));
|
||||
node_ptr const x_parent_left(NodeTraits::get_left(x_parent));
|
||||
const balance x_parent_balance = NodeTraits::get_balance(x_parent);
|
||||
const bool x_is_leftchild(x == x_parent_left);
|
||||
if(x_parent_balance == NodeTraits::zero()){
|
||||
// if x is left, parent will have parent->bal_factor = negative
|
||||
// else, parent->bal_factor = NodeTraits::positive()
|
||||
NodeTraits::set_balance( NodeTraits::get_parent(x)
|
||||
, x == NodeTraits::get_left(NodeTraits::get_parent(x))
|
||||
? NodeTraits::negative() : NodeTraits::positive() );
|
||||
x = NodeTraits::get_parent(x);
|
||||
NodeTraits::set_balance( x_parent, x_is_leftchild ? NodeTraits::negative() : NodeTraits::positive() );
|
||||
x = x_parent;
|
||||
}
|
||||
else if(x_parent_balance == NodeTraits::positive()){
|
||||
// if x is a left child, parent->bal_factor = zero
|
||||
if (x == NodeTraits::get_left(NodeTraits::get_parent(x)))
|
||||
NodeTraits::set_balance(NodeTraits::get_parent(x), NodeTraits::zero());
|
||||
if (x_is_leftchild)
|
||||
NodeTraits::set_balance(x_parent, NodeTraits::zero());
|
||||
else{ // x is a right child, needs rebalancing
|
||||
if (NodeTraits::get_balance(x) == NodeTraits::negative())
|
||||
rotate_right_left(NodeTraits::get_parent(x), header);
|
||||
avl_rotate_right_left(x_parent, x, header);
|
||||
else
|
||||
rotate_left(NodeTraits::get_parent(x), header);
|
||||
avl_rotate_left(x_parent, x, header);
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if(x_parent_balance == NodeTraits::negative()){
|
||||
// if x is a left child, needs rebalancing
|
||||
if (x == NodeTraits::get_left(NodeTraits::get_parent(x))) {
|
||||
if (x_is_leftchild) {
|
||||
if (NodeTraits::get_balance(x) == NodeTraits::positive())
|
||||
rotate_left_right(NodeTraits::get_parent(x), header);
|
||||
avl_rotate_left_right(x_parent, x, header);
|
||||
else
|
||||
rotate_right(NodeTraits::get_parent(x), header);
|
||||
avl_rotate_right(x_parent, x, header);
|
||||
}
|
||||
else
|
||||
NodeTraits::set_balance(NodeTraits::get_parent(x), NodeTraits::zero());
|
||||
NodeTraits::set_balance(x_parent, NodeTraits::zero());
|
||||
break;
|
||||
}
|
||||
else{
|
||||
@ -486,26 +527,28 @@ class avltree_algorithms
|
||||
// balancing...
|
||||
const balance c_balance = NodeTraits::get_balance(c);
|
||||
const balance zero_balance = NodeTraits::zero();
|
||||
const balance posi_balance = NodeTraits::positive();
|
||||
const balance nega_balance = NodeTraits::negative();
|
||||
NodeTraits::set_balance(c, zero_balance);
|
||||
if(c_balance == NodeTraits::negative()){
|
||||
NodeTraits::set_balance(a, NodeTraits::positive());
|
||||
if(c_balance == nega_balance){
|
||||
NodeTraits::set_balance(a, posi_balance);
|
||||
NodeTraits::set_balance(b, zero_balance);
|
||||
}
|
||||
else if(c_balance == zero_balance){
|
||||
NodeTraits::set_balance(a, zero_balance);
|
||||
NodeTraits::set_balance(b, zero_balance);
|
||||
}
|
||||
else if(c_balance == NodeTraits::positive()){
|
||||
else if(c_balance == posi_balance){
|
||||
NodeTraits::set_balance(a, zero_balance);
|
||||
NodeTraits::set_balance(b, NodeTraits::negative());
|
||||
NodeTraits::set_balance(b, nega_balance);
|
||||
}
|
||||
else{
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(false); // never reached
|
||||
}
|
||||
}
|
||||
|
||||
static void rotate_left_right(const node_ptr a, const node_ptr & hdr)
|
||||
{
|
||||
static node_ptr avl_rotate_left_right(const node_ptr a, const node_ptr a_oldleft, const node_ptr & hdr)
|
||||
{ // [note: 'a_oldleft' is 'b']
|
||||
// | | //
|
||||
// a(-2) c //
|
||||
// / \ / \ //
|
||||
@ -513,16 +556,19 @@ class avltree_algorithms
|
||||
// (pos)b [g] b a //
|
||||
// / \ / \ / \ //
|
||||
// [d] c [d] e f [g] //
|
||||
// / \ //
|
||||
// e f //
|
||||
node_ptr b = NodeTraits::get_left(a), c = NodeTraits::get_right(b);
|
||||
bstree_algo::rotate_left(b, hdr);
|
||||
bstree_algo::rotate_right(a, hdr);
|
||||
left_right_balancing(a, b, c);
|
||||
// / \ //
|
||||
// e f //
|
||||
const node_ptr c = NodeTraits::get_right(a_oldleft);
|
||||
bstree_algo::rotate_left_no_parent_fix(a_oldleft, c);
|
||||
//No need to link c with a [NodeTraits::set_parent(c, a) + NodeTraits::set_left(a, c)]
|
||||
//as c is not root and another rotation is coming
|
||||
bstree_algo::rotate_right(a, c, NodeTraits::get_parent(a), hdr);
|
||||
left_right_balancing(a, a_oldleft, c);
|
||||
return c;
|
||||
}
|
||||
|
||||
static void rotate_right_left(const node_ptr a, const node_ptr & hdr)
|
||||
{
|
||||
static node_ptr avl_rotate_right_left(const node_ptr a, const node_ptr a_oldright, const node_ptr & hdr)
|
||||
{ // [note: 'a_oldright' is 'b']
|
||||
// | | //
|
||||
// a(pos) c //
|
||||
// / \ / \ //
|
||||
@ -532,41 +578,42 @@ class avltree_algorithms
|
||||
// c [g] [d] e f [g] //
|
||||
// / \ //
|
||||
// e f //
|
||||
node_ptr b = NodeTraits::get_right(a), c = NodeTraits::get_left(b);
|
||||
bstree_algo::rotate_right(b, hdr);
|
||||
bstree_algo::rotate_left(a, hdr);
|
||||
left_right_balancing(b, a, c);
|
||||
const node_ptr c (NodeTraits::get_left(a_oldright));
|
||||
bstree_algo::rotate_right_no_parent_fix(a_oldright, c);
|
||||
//No need to link c with a [NodeTraits::set_parent(c, a) + NodeTraits::set_right(a, c)]
|
||||
//as c is not root and another rotation is coming.
|
||||
bstree_algo::rotate_left(a, c, NodeTraits::get_parent(a), hdr);
|
||||
left_right_balancing(a_oldright, a, c);
|
||||
return c;
|
||||
}
|
||||
|
||||
static void rotate_left(const node_ptr x, const node_ptr & hdr)
|
||||
static void avl_rotate_left(const node_ptr &x, const node_ptr &x_oldright, const node_ptr & hdr)
|
||||
{
|
||||
const node_ptr y = NodeTraits::get_right(x);
|
||||
bstree_algo::rotate_left(x, hdr);
|
||||
bstree_algo::rotate_left(x, x_oldright, NodeTraits::get_parent(x), hdr);
|
||||
|
||||
// reset the balancing factor
|
||||
if (NodeTraits::get_balance(y) == NodeTraits::positive()) {
|
||||
if (NodeTraits::get_balance(x_oldright) == NodeTraits::positive()) {
|
||||
NodeTraits::set_balance(x, NodeTraits::zero());
|
||||
NodeTraits::set_balance(y, NodeTraits::zero());
|
||||
NodeTraits::set_balance(x_oldright, NodeTraits::zero());
|
||||
}
|
||||
else { // this doesn't happen during insertions
|
||||
NodeTraits::set_balance(x, NodeTraits::positive());
|
||||
NodeTraits::set_balance(y, NodeTraits::negative());
|
||||
NodeTraits::set_balance(x_oldright, NodeTraits::negative());
|
||||
}
|
||||
}
|
||||
|
||||
static void rotate_right(const node_ptr x, const node_ptr & hdr)
|
||||
static void avl_rotate_right(const node_ptr &x, const node_ptr &x_oldleft, const node_ptr & hdr)
|
||||
{
|
||||
const node_ptr y = NodeTraits::get_left(x);
|
||||
bstree_algo::rotate_right(x, hdr);
|
||||
bstree_algo::rotate_right(x, x_oldleft, NodeTraits::get_parent(x), hdr);
|
||||
|
||||
// reset the balancing factor
|
||||
if (NodeTraits::get_balance(y) == NodeTraits::negative()) {
|
||||
if (NodeTraits::get_balance(x_oldleft) == NodeTraits::negative()) {
|
||||
NodeTraits::set_balance(x, NodeTraits::zero());
|
||||
NodeTraits::set_balance(y, NodeTraits::zero());
|
||||
NodeTraits::set_balance(x_oldleft, NodeTraits::zero());
|
||||
}
|
||||
else { // this doesn't happen during insertions
|
||||
NodeTraits::set_balance(x, NodeTraits::negative());
|
||||
NodeTraits::set_balance(y, NodeTraits::positive());
|
||||
NodeTraits::set_balance(x_oldleft, NodeTraits::positive());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -247,13 +247,19 @@ class bs_set_impl
|
||||
template<class Disposer>
|
||||
void clear_and_dispose(Disposer disposer);
|
||||
|
||||
#endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::count(const_reference)const
|
||||
size_type count(const_reference value) const;
|
||||
size_type count(const_reference value) const
|
||||
{ return static_cast<size_type>(this->tree_type::find(value) == this->tree_type::cend()); }
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
size_type count(const KeyType& key, KeyValueCompare comp) const;
|
||||
|
||||
size_type count(const KeyType& key, KeyValueCompare comp) const
|
||||
{ return static_cast<size_type>(this->tree_type::find(key, comp) == this->tree_type::cend()); }
|
||||
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference)
|
||||
iterator lower_bound(const_reference value);
|
||||
|
||||
@ -296,21 +302,29 @@ class bs_set_impl
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
const_iterator find(const KeyType& key, KeyValueCompare comp) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::equal_range(const_reference)
|
||||
std::pair<iterator,iterator> equal_range(const_reference value);
|
||||
#endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare)
|
||||
//! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference)
|
||||
std::pair<iterator,iterator> equal_range(const_reference value)
|
||||
{ return this->tree_type::lower_bound_range(value); }
|
||||
|
||||
//! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare)
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
std::pair<iterator,iterator> equal_range(const KeyType& key, KeyValueCompare comp);
|
||||
std::pair<iterator,iterator> equal_range(const KeyType& key, KeyValueCompare comp)
|
||||
{ return this->tree_type::lower_bound_range(key, comp); }
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::equal_range(const_reference)const
|
||||
//! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference)const
|
||||
std::pair<const_iterator, const_iterator>
|
||||
equal_range(const_reference value) const;
|
||||
equal_range(const_reference value) const
|
||||
{ return this->tree_type::lower_bound_range(value); }
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare)const
|
||||
//! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare)const
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
std::pair<const_iterator, const_iterator>
|
||||
equal_range(const KeyType& key, KeyValueCompare comp) const;
|
||||
equal_range(const KeyType& key, KeyValueCompare comp) const
|
||||
{ return this->tree_type::lower_bound_range(key, comp); }
|
||||
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::bounded_range(const_reference,const_reference,bool,bool)
|
||||
std::pair<iterator,iterator> bounded_range
|
||||
|
@ -73,7 +73,7 @@ struct make_bs_set_base_hook
|
||||
//! unique tag.
|
||||
//!
|
||||
//! \c void_pointer<> is the pointer type that will be used internally in the hook
|
||||
//! and the the container configured to use this hook.
|
||||
//! and the container configured to use this hook.
|
||||
//!
|
||||
//! \c link_mode<> will specify the linking mode of the hook (\c normal_link,
|
||||
//! \c auto_unlink or \c safe_link).
|
||||
@ -196,7 +196,7 @@ struct make_bs_set_member_hook
|
||||
//! The hook admits the following options: \c void_pointer<>, \c link_mode<>.
|
||||
//!
|
||||
//! \c void_pointer<> is the pointer type that will be used internally in the hook
|
||||
//! and the the container configured to use this hook.
|
||||
//! and the container configured to use this hook.
|
||||
//!
|
||||
//! \c link_mode<> will specify the linking mode of the hook (\c normal_link,
|
||||
//! \c auto_unlink or \c safe_link).
|
||||
|
@ -14,8 +14,8 @@
|
||||
#define BOOST_INTRUSIVE_BSTREE_ALGORITHMS_HPP
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/detail/assert.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
#include <boost/intrusive/detail/assert.hpp>
|
||||
#include <cstddef>
|
||||
#include <boost/intrusive/detail/utilities.hpp>
|
||||
#include <boost/intrusive/pointer_traits.hpp>
|
||||
@ -173,7 +173,20 @@ class bstree_algorithms
|
||||
static node_ptr end_node(const const_node_ptr & header)
|
||||
{ return detail::uncast(header); }
|
||||
|
||||
//! <b>Requires</b>: 'node' is a node of the tree or an node initialized
|
||||
//! <b>Requires</b>: 'header' is the header node of a tree.
|
||||
//!
|
||||
//! <b>Effects</b>: Returns the root of the tree if any, header otherwise
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant time.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static node_ptr root_node(const const_node_ptr & header)
|
||||
{
|
||||
node_ptr p = node_traits::get_parent(header);
|
||||
return p ? p : detail::uncast(header);
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: 'node' is a node of the tree or a node initialized
|
||||
//! by init(...) or init_node.
|
||||
//!
|
||||
//! <b>Effects</b>: Returns true if the node is initialized by init() or init_node().
|
||||
@ -487,18 +500,18 @@ class bstree_algorithms
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static node_ptr next_node(const node_ptr & node)
|
||||
{
|
||||
node_ptr p_right(NodeTraits::get_right(node));
|
||||
if(p_right){
|
||||
return minimum(p_right);
|
||||
node_ptr const n_right(NodeTraits::get_right(node));
|
||||
if(n_right){
|
||||
return minimum(n_right);
|
||||
}
|
||||
else {
|
||||
node_ptr p(node);
|
||||
node_ptr x = NodeTraits::get_parent(p);
|
||||
while(p == NodeTraits::get_right(x)){
|
||||
p = x;
|
||||
x = NodeTraits::get_parent(x);
|
||||
node_ptr n(node);
|
||||
node_ptr p(NodeTraits::get_parent(n));
|
||||
while(n == NodeTraits::get_right(p)){
|
||||
n = p;
|
||||
p = NodeTraits::get_parent(p);
|
||||
}
|
||||
return NodeTraits::get_right(p) != x ? x : detail::uncast(p);
|
||||
return NodeTraits::get_right(n) != p ? p : n;
|
||||
}
|
||||
}
|
||||
|
||||
@ -536,7 +549,7 @@ class bstree_algorithms
|
||||
//! <b>Complexity</b>: Logarithmic to the size of the subtree.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
static node_ptr minimum (node_ptr node)
|
||||
static node_ptr minimum(node_ptr node)
|
||||
{
|
||||
for(node_ptr p_left = NodeTraits::get_left(node)
|
||||
;p_left
|
||||
@ -766,7 +779,7 @@ class bstree_algorithms
|
||||
//! ordering compatible with the strict weak ordering used to create the
|
||||
//! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs.
|
||||
//!
|
||||
//! <b>Effects</b>: Returns an node_ptr to the element that is equivalent to
|
||||
//! <b>Effects</b>: Returns a node_ptr to the first element that is equivalent to
|
||||
//! "key" according to "comp" or "header" if that element does not exist.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
@ -825,7 +838,6 @@ class bstree_algorithms
|
||||
//If the upper_key is less than x, the target
|
||||
//range is on the left part
|
||||
else if(comp(upper_key, x)){
|
||||
//y > upper_key
|
||||
y = x;
|
||||
x = NodeTraits::get_left(x);
|
||||
}
|
||||
@ -864,7 +876,7 @@ class bstree_algorithms
|
||||
//! ordering compatible with the strict weak ordering used to create the
|
||||
//! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs.
|
||||
//!
|
||||
//! <b>Effects</b>: Returns the number of elements with a key equivalent to "key"pair of node_ptr delimiting a range containing
|
||||
//! <b>Effects</b>: Returns the number of elements with a key equivalent to "key"
|
||||
//! according to "comp".
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
@ -908,7 +920,32 @@ class bstree_algorithms
|
||||
//! ordering compatible with the strict weak ordering used to create the
|
||||
//! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs.
|
||||
//!
|
||||
//! <b>Effects</b>: Returns an node_ptr to the first element that is
|
||||
//! <b>Effects</b>: Returns an a pair of node_ptr delimiting a range containing
|
||||
//! the first element that is equivalent to "key" according to "comp" or an
|
||||
//! empty range that indicates the position where that element would be
|
||||
//! if there are no equivalent elements.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
//!
|
||||
//! <b>Throws</b>: If "comp" throws.
|
||||
template<class KeyType, class KeyNodePtrCompare>
|
||||
static std::pair<node_ptr, node_ptr> lower_bound_range
|
||||
(const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp)
|
||||
{
|
||||
node_ptr const lb(lower_bound(header, key, comp));
|
||||
std::pair<node_ptr, node_ptr> ret_ii(lb, lb);
|
||||
if(lb != header && !comp(key, lb)){
|
||||
ret_ii.second = next_node(ret_ii.second);
|
||||
}
|
||||
return ret_ii;
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: "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.
|
||||
//!
|
||||
//! <b>Effects</b>: Returns a node_ptr to the first element that is
|
||||
//! not less than "key" according to "comp" or "header" if that element does
|
||||
//! not exist.
|
||||
//!
|
||||
@ -927,7 +964,7 @@ class bstree_algorithms
|
||||
//! ordering compatible with the strict weak ordering used to create the
|
||||
//! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs.
|
||||
//!
|
||||
//! <b>Effects</b>: Returns an node_ptr to the first element that is greater
|
||||
//! <b>Effects</b>: Returns a node_ptr to the first element that is greater
|
||||
//! than "key" according to "comp" or "header" if that element does not exist.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
@ -1025,16 +1062,12 @@ class bstree_algorithms
|
||||
//Since we've found the upper bound there is no other value with the same key if:
|
||||
// - There is no previous node
|
||||
// - The previous node is less than the key
|
||||
if(!prev || comp(prev, key)){
|
||||
const bool not_present = !prev || comp(prev, key);
|
||||
if(not_present){
|
||||
commit_data.link_left = left_child;
|
||||
commit_data.node = y;
|
||||
return std::pair<node_ptr, bool>(node_ptr(), true);
|
||||
}
|
||||
//If the previous value was not less than key, it means that it's equal
|
||||
//(because we've checked the upper bound)
|
||||
else{
|
||||
return std::pair<node_ptr, bool>(prev, false);
|
||||
}
|
||||
return std::pair<node_ptr, bool>(prev, not_present);
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: "header" must be the header node of a tree.
|
||||
@ -1325,7 +1358,7 @@ class bstree_algorithms
|
||||
static void erase(const node_ptr & header, const node_ptr & z)
|
||||
{
|
||||
data_for_rebalance ignored;
|
||||
erase_impl(header, z, ignored);
|
||||
erase(header, z, ignored);
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: node is a tree node but not the header.
|
||||
@ -1410,6 +1443,88 @@ class bstree_algorithms
|
||||
}
|
||||
|
||||
protected:
|
||||
static void erase(const node_ptr & header, const node_ptr & z, data_for_rebalance &info)
|
||||
{
|
||||
node_ptr y(z);
|
||||
node_ptr x;
|
||||
const node_ptr z_left(NodeTraits::get_left(z));
|
||||
const node_ptr z_right(NodeTraits::get_right(z));
|
||||
|
||||
if(!z_left){
|
||||
x = z_right; // x might be null.
|
||||
}
|
||||
else if(!z_right){ // z has exactly one non-null child. y == z.
|
||||
x = z_left; // x is not null.
|
||||
BOOST_ASSERT(x);
|
||||
}
|
||||
else{ //make y != z
|
||||
// y = find z's successor
|
||||
y = bstree_algorithms::minimum(z_right);
|
||||
x = NodeTraits::get_right(y); // x might be null.
|
||||
}
|
||||
|
||||
node_ptr x_parent;
|
||||
const node_ptr z_parent(NodeTraits::get_parent(z));
|
||||
const bool z_is_leftchild(NodeTraits::get_left(z_parent) == z);
|
||||
|
||||
if(y != z){ //has two children and y is the minimum of z
|
||||
//y is z's successor and it has a null left child.
|
||||
//x is the right child of y (it can be null)
|
||||
//Relink y in place of z and link x with y's old parent
|
||||
NodeTraits::set_parent(z_left, y);
|
||||
NodeTraits::set_left(y, z_left);
|
||||
if(y != z_right){
|
||||
//Link y with the right tree of z
|
||||
NodeTraits::set_right(y, z_right);
|
||||
NodeTraits::set_parent(z_right, y);
|
||||
//Link x with y's old parent (y must be a left child)
|
||||
x_parent = NodeTraits::get_parent(y);
|
||||
BOOST_ASSERT(NodeTraits::get_left(x_parent) == y);
|
||||
if(x)
|
||||
NodeTraits::set_parent(x, x_parent);
|
||||
//Since y was the successor and not the right child of z, it must be a left child
|
||||
NodeTraits::set_left(x_parent, x);
|
||||
}
|
||||
else{ //y was the right child of y so no need to fix x's position
|
||||
x_parent = y;
|
||||
}
|
||||
NodeTraits::set_parent(y, z_parent);
|
||||
bstree_algorithms::set_child(header, y, z_parent, z_is_leftchild);
|
||||
}
|
||||
else { // z has zero or one child, x is one child (it can be null)
|
||||
//Just link x to z's parent
|
||||
x_parent = z_parent;
|
||||
if(x)
|
||||
NodeTraits::set_parent(x, z_parent);
|
||||
bstree_algorithms::set_child(header, x, z_parent, z_is_leftchild);
|
||||
|
||||
//Now update leftmost/rightmost in case z was one of them
|
||||
if(NodeTraits::get_left(header) == z){
|
||||
//z_left must be null because z is the leftmost
|
||||
BOOST_ASSERT(!z_left);
|
||||
NodeTraits::set_left(header, !z_right ?
|
||||
z_parent : // makes leftmost == header if z == root
|
||||
bstree_algorithms::minimum(z_right));
|
||||
}
|
||||
if(NodeTraits::get_right(header) == z){
|
||||
//z_right must be null because z is the rightmost
|
||||
BOOST_ASSERT(!z_right);
|
||||
NodeTraits::set_right(header, !z_left ?
|
||||
z_parent : // makes rightmost == header if z == root
|
||||
bstree_algorithms::maximum(z_left));
|
||||
}
|
||||
}
|
||||
|
||||
//If z had 0/1 child, y == z and one of its children (and maybe null)
|
||||
//If z had 2 children, y is the successor of z and x is the right child of y
|
||||
info.x = x;
|
||||
info.y = y;
|
||||
//If z had 0/1 child, x_parent is the new parent of the old right child of y (z's successor)
|
||||
//If z had 2 children, x_parent is the new parent of y (z_parent)
|
||||
BOOST_ASSERT(!x || NodeTraits::get_parent(x) == x_parent);
|
||||
info.x_parent = x_parent;
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: node is a node of the tree but it's not the header.
|
||||
//!
|
||||
//! <b>Effects</b>: Returns the number of nodes of the subtree.
|
||||
@ -1473,83 +1588,6 @@ class bstree_algorithms
|
||||
static bool is_right_child(const node_ptr & p)
|
||||
{ return NodeTraits::get_right(NodeTraits::get_parent(p)) == p; }
|
||||
|
||||
template<class F>
|
||||
static void erase(const node_ptr & header, const node_ptr & z, F z_and_successor_fixup, data_for_rebalance &info)
|
||||
{
|
||||
erase_impl(header, z, info);
|
||||
if(info.y != z){
|
||||
z_and_successor_fixup(z, info.y);
|
||||
}
|
||||
}
|
||||
|
||||
//Fix header and own's parent data when replacing x with own, providing own's old data with parent
|
||||
static void replace_own_impl(const node_ptr & own, const node_ptr & x, const node_ptr & header, const node_ptr & own_parent, bool own_was_left)
|
||||
{
|
||||
if(NodeTraits::get_parent(header) == own)
|
||||
NodeTraits::set_parent(header, x);
|
||||
else if(own_was_left)
|
||||
NodeTraits::set_left(own_parent, x);
|
||||
else
|
||||
NodeTraits::set_right(own_parent, x);
|
||||
}
|
||||
|
||||
//Fix header and own's parent data when replacing x with own, supposing own
|
||||
//links with its parent are still ok
|
||||
static void replace_own(const node_ptr & own, const node_ptr & x, const node_ptr & header)
|
||||
{
|
||||
node_ptr own_parent(NodeTraits::get_parent(own));
|
||||
bool own_is_left(NodeTraits::get_left(own_parent) == own);
|
||||
replace_own_impl(own, x, header, own_parent, own_is_left);
|
||||
}
|
||||
|
||||
// rotate parent p to left (no header and p's parent fixup)
|
||||
static node_ptr rotate_left(const node_ptr & p)
|
||||
{
|
||||
node_ptr x(NodeTraits::get_right(p));
|
||||
node_ptr x_left(NodeTraits::get_left(x));
|
||||
NodeTraits::set_right(p, x_left);
|
||||
if(x_left){
|
||||
NodeTraits::set_parent(x_left, p);
|
||||
}
|
||||
NodeTraits::set_left(x, p);
|
||||
NodeTraits::set_parent(p, x);
|
||||
return x;
|
||||
}
|
||||
|
||||
// rotate parent p to left (with header and p's parent fixup)
|
||||
static void rotate_left(const node_ptr & p, const node_ptr & header)
|
||||
{
|
||||
bool p_was_left(is_left_child(p));
|
||||
node_ptr p_old_parent(NodeTraits::get_parent(p));
|
||||
node_ptr x(rotate_left(p));
|
||||
NodeTraits::set_parent(x, p_old_parent);
|
||||
replace_own_impl(p, x, header, p_old_parent, p_was_left);
|
||||
}
|
||||
|
||||
// rotate parent p to right (no header and p's parent fixup)
|
||||
static node_ptr rotate_right(const node_ptr & p)
|
||||
{
|
||||
node_ptr x(NodeTraits::get_left(p));
|
||||
node_ptr x_right(NodeTraits::get_right(x));
|
||||
NodeTraits::set_left(p, x_right);
|
||||
if(x_right){
|
||||
NodeTraits::set_parent(x_right, p);
|
||||
}
|
||||
NodeTraits::set_right(x, p);
|
||||
NodeTraits::set_parent(p, x);
|
||||
return x;
|
||||
}
|
||||
|
||||
// rotate parent p to right (with header and p's parent fixup)
|
||||
static void rotate_right(const node_ptr & p, const node_ptr & header)
|
||||
{
|
||||
bool p_was_left(is_left_child(p));
|
||||
node_ptr p_old_parent(NodeTraits::get_parent(p));
|
||||
node_ptr x(rotate_right(p));
|
||||
NodeTraits::set_parent(x, p_old_parent);
|
||||
replace_own_impl(p, x, header, p_old_parent, p_was_left);
|
||||
}
|
||||
|
||||
static void insert_before_check
|
||||
(const node_ptr &header, const node_ptr & pos
|
||||
, insert_commit_data &commit_data
|
||||
@ -1631,12 +1669,40 @@ class bstree_algorithms
|
||||
template<class NodePtrCompare>
|
||||
static void insert_equal_upper_bound_check
|
||||
(const node_ptr & h, const node_ptr & new_node, NodePtrCompare comp, insert_commit_data & commit_data, std::size_t *pdepth = 0)
|
||||
{ insert_equal_check_impl(true, h, new_node, comp, commit_data, pdepth); }
|
||||
{
|
||||
std::size_t depth = 0;
|
||||
node_ptr y(h);
|
||||
node_ptr x(NodeTraits::get_parent(y));
|
||||
|
||||
while(x){
|
||||
++depth;
|
||||
y = x;
|
||||
x = comp(new_node, x) ?
|
||||
NodeTraits::get_left(x) : NodeTraits::get_right(x);
|
||||
}
|
||||
if(pdepth) *pdepth = depth;
|
||||
commit_data.link_left = (y == h) || comp(new_node, y);
|
||||
commit_data.node = y;
|
||||
}
|
||||
|
||||
template<class NodePtrCompare>
|
||||
static void insert_equal_lower_bound_check
|
||||
(const node_ptr & h, const node_ptr & new_node, NodePtrCompare comp, insert_commit_data & commit_data, std::size_t *pdepth = 0)
|
||||
{ insert_equal_check_impl(false, h, new_node, comp, commit_data, pdepth); }
|
||||
{
|
||||
std::size_t depth = 0;
|
||||
node_ptr y(h);
|
||||
node_ptr x(NodeTraits::get_parent(y));
|
||||
|
||||
while(x){
|
||||
++depth;
|
||||
y = x;
|
||||
x = !comp(x, new_node) ?
|
||||
NodeTraits::get_left(x) : NodeTraits::get_right(x);
|
||||
}
|
||||
if(pdepth) *pdepth = depth;
|
||||
commit_data.link_left = (y == h) || !comp(y, new_node);
|
||||
commit_data.node = y;
|
||||
}
|
||||
|
||||
static void insert_commit
|
||||
(const node_ptr & header, const node_ptr & new_node, const insert_commit_data &commit_data)
|
||||
@ -1664,7 +1730,61 @@ class bstree_algorithms
|
||||
NodeTraits::set_left(new_node, node_ptr());
|
||||
}
|
||||
|
||||
//Fix header and own's parent data when replacing x with own, providing own's old data with parent
|
||||
static void set_child(const node_ptr & header, const node_ptr & new_child, const node_ptr & new_parent, const bool link_left)
|
||||
{
|
||||
if(new_parent == header)
|
||||
NodeTraits::set_parent(header, new_child);
|
||||
else if(link_left)
|
||||
NodeTraits::set_left(new_parent, new_child);
|
||||
else
|
||||
NodeTraits::set_right(new_parent, new_child);
|
||||
}
|
||||
|
||||
// rotate p to left (no header and p's parent fixup)
|
||||
static void rotate_left_no_parent_fix(const node_ptr & p, const node_ptr &p_right)
|
||||
{
|
||||
node_ptr p_right_left(NodeTraits::get_left(p_right));
|
||||
NodeTraits::set_right(p, p_right_left);
|
||||
if(p_right_left){
|
||||
NodeTraits::set_parent(p_right_left, p);
|
||||
}
|
||||
NodeTraits::set_left(p_right, p);
|
||||
NodeTraits::set_parent(p, p_right);
|
||||
}
|
||||
|
||||
// rotate p to left (with header and p's parent fixup)
|
||||
static void rotate_left(const node_ptr & p, const node_ptr & p_right, const node_ptr & p_parent, const node_ptr & header)
|
||||
{
|
||||
const bool p_was_left(NodeTraits::get_left(p_parent) == p);
|
||||
rotate_left_no_parent_fix(p, p_right);
|
||||
NodeTraits::set_parent(p_right, p_parent);
|
||||
set_child(header, p_right, p_parent, p_was_left);
|
||||
}
|
||||
|
||||
// rotate p to right (no header and p's parent fixup)
|
||||
static void rotate_right_no_parent_fix(const node_ptr & p, const node_ptr &p_left)
|
||||
{
|
||||
node_ptr p_left_right(NodeTraits::get_right(p_left));
|
||||
NodeTraits::set_left(p, p_left_right);
|
||||
if(p_left_right){
|
||||
NodeTraits::set_parent(p_left_right, p);
|
||||
}
|
||||
NodeTraits::set_right(p_left, p);
|
||||
NodeTraits::set_parent(p, p_left);
|
||||
}
|
||||
|
||||
// rotate p to right (with header and p's parent fixup)
|
||||
static void rotate_right(const node_ptr & p, const node_ptr & p_left, const node_ptr & p_parent, const node_ptr & header)
|
||||
{
|
||||
const bool p_was_left(NodeTraits::get_left(p_parent) == p);
|
||||
rotate_right_no_parent_fix(p, p_left);
|
||||
NodeTraits::set_parent(p_left, p_parent);
|
||||
set_child(header, p_left, p_parent, p_was_left);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static void subtree_to_vine(node_ptr vine_tail, std::size_t &size)
|
||||
{
|
||||
//Inspired by LibAVL:
|
||||
@ -1877,98 +1997,6 @@ class bstree_algorithms
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
|
||||
template<class NodePtrCompare>
|
||||
static void insert_equal_check_impl
|
||||
(bool upper, const node_ptr & h, const node_ptr & new_node, NodePtrCompare comp, insert_commit_data & commit_data, std::size_t *pdepth = 0)
|
||||
{
|
||||
std::size_t depth = 0;
|
||||
node_ptr y(h);
|
||||
node_ptr x(NodeTraits::get_parent(y));
|
||||
bool link_left;
|
||||
|
||||
if(upper){
|
||||
while(x){
|
||||
++depth;
|
||||
y = x;
|
||||
x = comp(new_node, x) ?
|
||||
NodeTraits::get_left(x) : NodeTraits::get_right(x);
|
||||
}
|
||||
link_left = (y == h) || comp(new_node, y);
|
||||
}
|
||||
else{
|
||||
while(x){
|
||||
++depth;
|
||||
y = x;
|
||||
x = !comp(x, new_node) ?
|
||||
NodeTraits::get_left(x) : NodeTraits::get_right(x);
|
||||
}
|
||||
link_left = (y == h) || !comp(y, new_node);
|
||||
}
|
||||
|
||||
commit_data.link_left = link_left;
|
||||
commit_data.node = y;
|
||||
if(pdepth) *pdepth = depth;
|
||||
}
|
||||
|
||||
static void erase_impl(const node_ptr & header, const node_ptr & z, data_for_rebalance &info)
|
||||
{
|
||||
node_ptr y(z);
|
||||
node_ptr x;
|
||||
node_ptr x_parent = node_ptr();
|
||||
node_ptr z_left(NodeTraits::get_left(z));
|
||||
node_ptr z_right(NodeTraits::get_right(z));
|
||||
if(!z_left){
|
||||
x = z_right; // x might be null.
|
||||
}
|
||||
else if(!z_right){ // z has exactly one non-null child. y == z.
|
||||
x = z_left; // x is not null.
|
||||
}
|
||||
else{
|
||||
// find z's successor
|
||||
y = bstree_algorithms::minimum (z_right);
|
||||
x = NodeTraits::get_right(y); // x might be null.
|
||||
}
|
||||
|
||||
if(y != z){
|
||||
// relink y in place of z. y is z's successor
|
||||
NodeTraits::set_parent(NodeTraits::get_left(z), y);
|
||||
NodeTraits::set_left(y, NodeTraits::get_left(z));
|
||||
if(y != NodeTraits::get_right(z)){
|
||||
x_parent = NodeTraits::get_parent(y);
|
||||
if(x)
|
||||
NodeTraits::set_parent(x, x_parent);
|
||||
NodeTraits::set_left(x_parent, x); // y must be a child of left_
|
||||
NodeTraits::set_right(y, NodeTraits::get_right(z));
|
||||
NodeTraits::set_parent(NodeTraits::get_right(z), y);
|
||||
}
|
||||
else
|
||||
x_parent = y;
|
||||
bstree_algorithms::replace_own (z, y, header);
|
||||
NodeTraits::set_parent(y, NodeTraits::get_parent(z));
|
||||
}
|
||||
else { // y == z --> z has only one child, or void
|
||||
x_parent = NodeTraits::get_parent(z);
|
||||
if(x)
|
||||
NodeTraits::set_parent(x, x_parent);
|
||||
bstree_algorithms::replace_own (z, x, header);
|
||||
if(NodeTraits::get_left(header) == z){
|
||||
NodeTraits::set_left(header, !NodeTraits::get_right(z) ? // z->get_left() must be null also
|
||||
NodeTraits::get_parent(z) : // makes leftmost == header if z == root
|
||||
bstree_algorithms::minimum (x));
|
||||
}
|
||||
if(NodeTraits::get_right(header) == z){
|
||||
NodeTraits::set_right(header, !NodeTraits::get_left(z) ? // z->get_right() must be null also
|
||||
NodeTraits::get_parent(z) : // makes rightmost == header if z == root
|
||||
bstree_algorithms::maximum(x));
|
||||
}
|
||||
}
|
||||
|
||||
info.x = x;
|
||||
info.x_parent = x_parent;
|
||||
info.y = y;
|
||||
}
|
||||
};
|
||||
|
||||
/// @cond
|
||||
|
@ -13,6 +13,9 @@
|
||||
#ifndef BOOST_INTRUSIVE_DERIVATION_VALUE_TRAITS_HPP
|
||||
#define BOOST_INTRUSIVE_DERIVATION_VALUE_TRAITS_HPP
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
|
||||
#include <boost/intrusive/link_mode.hpp>
|
||||
#include <boost/pointer_cast.hpp>
|
||||
#include <boost/pointer_to_other.hpp>
|
||||
@ -24,7 +27,12 @@ namespace intrusive {
|
||||
//!This value traits template is used to create value traits
|
||||
//!from user defined node traits where value_traits::value_type will
|
||||
//!derive from node_traits::node
|
||||
template<class T, class NodeTraits, link_mode_type LinkMode = safe_link>
|
||||
|
||||
template<class T, class NodeTraits, link_mode_type LinkMode
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
= safe_link
|
||||
#endif
|
||||
>
|
||||
struct derivation_value_traits
|
||||
{
|
||||
public:
|
||||
@ -67,4 +75,6 @@ struct derivation_value_traits
|
||||
} //namespace intrusive
|
||||
} //namespace boost
|
||||
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTRUSIVE_DERIVATION_VALUE_TRAITS_HPP
|
||||
|
@ -13,7 +13,7 @@
|
||||
#ifndef BOOST_INTRUSIVE_DETAIL_ASSERT_HPP
|
||||
#define BOOST_INTRUSIVE_DETAIL_ASSERT_HPP
|
||||
|
||||
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
@ -33,9 +33,9 @@ enum base_hook_type
|
||||
, SlistBaseHookId
|
||||
, RbTreeBaseHookId
|
||||
, HashBaseHookId
|
||||
, SplayTreeBaseHookId
|
||||
, AvlTreeBaseHookId
|
||||
, BsTreeBaseHookId
|
||||
, TreapTreeBaseHookId
|
||||
, AnyBaseHookId
|
||||
};
|
||||
|
||||
@ -59,10 +59,6 @@ template <class HookTags>
|
||||
struct hook_tags_definer<HookTags, HashBaseHookId>
|
||||
{ typedef HookTags default_hashtable_hook; };
|
||||
|
||||
template <class HookTags>
|
||||
struct hook_tags_definer<HookTags, SplayTreeBaseHookId>
|
||||
{ typedef HookTags default_splaytree_hook; };
|
||||
|
||||
template <class HookTags>
|
||||
struct hook_tags_definer<HookTags, AvlTreeBaseHookId>
|
||||
{ typedef HookTags default_avltree_hook; };
|
||||
|
@ -70,11 +70,11 @@
|
||||
#error "BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END not defined!"
|
||||
#endif
|
||||
|
||||
#if BOOST_PP_ITERATION_START() != 0
|
||||
#error "BOOST_PP_ITERATION_START() must be zero (0)"
|
||||
#if BOOST_PP_ITERATION_START() > BOOST_PP_ITERATION_FINISH()
|
||||
#error "BOOST_PP_ITERATION_START() must be <= BOOST_PP_ITERATION_FINISH()"
|
||||
#endif
|
||||
|
||||
#if BOOST_PP_ITERATION() == 0
|
||||
#if BOOST_PP_ITERATION() == BOOST_PP_ITERATION_START()
|
||||
|
||||
BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN
|
||||
|
||||
@ -114,6 +114,119 @@
|
||||
};
|
||||
//!
|
||||
|
||||
#else //!defined(BOOST_INTRUSIVE_PERFECT_FORWARDING)
|
||||
|
||||
template<typename Fun, bool HasFunc, class ...Args>
|
||||
struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl);
|
||||
|
||||
template<typename Fun, class ...Args>
|
||||
struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl)
|
||||
<Fun, false, Args...>
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
#ifdef BOOST_NO_CXX11_DECLTYPE
|
||||
|
||||
//Special case for 0 args
|
||||
template< class F
|
||||
, std::size_t N =
|
||||
sizeof((boost::move_detail::declval<F>().
|
||||
BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME (), 0))>
|
||||
struct BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)
|
||||
{
|
||||
boost_intrusive_has_member_function_callable_with::yes_type dummy;
|
||||
BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)(int);
|
||||
};
|
||||
|
||||
//For buggy compilers like MSVC 7.1+ ((F*)0)->func() does not
|
||||
//SFINAE-out the zeroarg_checker_ instantiation but sizeof yields to 0.
|
||||
template<class F>
|
||||
struct BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<F, 0>
|
||||
{
|
||||
boost_intrusive_has_member_function_callable_with::no_type dummy;
|
||||
BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)(int);
|
||||
};
|
||||
|
||||
#endif //#ifdef BOOST_NO_CXX11_DECLTYPE
|
||||
|
||||
template<typename Fun>
|
||||
struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl)
|
||||
<Fun, true>
|
||||
{
|
||||
#ifndef BOOST_NO_CXX11_DECLTYPE
|
||||
template<class U, class V = decltype(boost::move_detail::declval<U>().BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME()) >
|
||||
static boost_intrusive_has_member_function_callable_with::yes_type Test(U*);
|
||||
#else
|
||||
template<class U>
|
||||
static BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)
|
||||
<U> Test(BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<U>*);
|
||||
#endif
|
||||
|
||||
template <class U>
|
||||
static boost_intrusive_has_member_function_callable_with::no_type Test(...);
|
||||
|
||||
static const bool value = sizeof(Test< Fun >(0))
|
||||
== sizeof(boost_intrusive_has_member_function_callable_with::yes_type);
|
||||
};
|
||||
|
||||
template<typename Fun, class ...DontCares>
|
||||
struct BOOST_PP_CAT( funwrap_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME )
|
||||
: Fun
|
||||
{
|
||||
BOOST_PP_CAT( funwrap_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME )();
|
||||
using Fun::BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME;
|
||||
|
||||
boost_intrusive_has_member_function_callable_with::private_type
|
||||
BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME
|
||||
( DontCares...) const;
|
||||
};
|
||||
|
||||
template<typename Fun, class ...Args>
|
||||
struct BOOST_PP_CAT( BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME), _impl)
|
||||
<Fun, true , Args...>
|
||||
{
|
||||
template<class T>
|
||||
struct make_dontcare
|
||||
{
|
||||
typedef boost_intrusive_has_member_function_callable_with::dont_care type;
|
||||
};
|
||||
|
||||
typedef BOOST_PP_CAT( funwrap_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME )
|
||||
<Fun, typename make_dontcare<Args>::type...> FunWrap;
|
||||
|
||||
static bool const value = (sizeof(boost_intrusive_has_member_function_callable_with::no_type) ==
|
||||
sizeof(boost_intrusive_has_member_function_callable_with::is_private_type
|
||||
( (::boost::move_detail::declval< FunWrap >().
|
||||
BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME
|
||||
( ::boost::move_detail::declval<Args>()... ), 0) )
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
template<typename Fun, class ...Args>
|
||||
struct BOOST_PP_CAT( has_member_function_callable_with_
|
||||
, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)
|
||||
: public BOOST_PP_CAT( BOOST_PP_CAT(has_member_function_callable_with_
|
||||
, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl)
|
||||
< Fun
|
||||
, BOOST_PP_CAT( has_member_function_named_
|
||||
, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME )<Fun>::value
|
||||
, Args... >
|
||||
{};
|
||||
|
||||
#endif //!defined(BOOST_INTRUSIVE_PERFECT_FORWARDING)
|
||||
|
||||
BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END
|
||||
|
||||
#endif //BOOST_PP_ITERATION() == BOOST_PP_ITERATION_START()
|
||||
|
||||
#if BOOST_PP_ITERATION() == 0
|
||||
|
||||
BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN
|
||||
|
||||
#if !defined(BOOST_INTRUSIVE_PERFECT_FORWARDING)
|
||||
|
||||
#if !defined(_MSC_VER) || (_MSC_VER < 1600)
|
||||
|
||||
#if defined(BOOST_INTRUSIVE_DETAIL_HAS_MEMBER_FUNCTION_CALLABLE_WITH_0_ARGS_UNSUPPORTED)
|
||||
@ -171,9 +284,9 @@
|
||||
<Fun, true BOOST_PP_ENUM_TRAILING(BOOST_PP_SUB(BOOST_PP_ITERATION_FINISH(), BOOST_PP_ITERATION()), BOOST_INTRUSIVE_PP_IDENTITY, void)>
|
||||
{
|
||||
template<class U>
|
||||
static decltype( boost::move_detail::declval<Fun>().BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME()
|
||||
static decltype( boost::move_detail::declval<U>().BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME()
|
||||
, boost_intrusive_has_member_function_callable_with::yes_type())
|
||||
Test(Fun*);
|
||||
Test(U*);
|
||||
|
||||
template<class U>
|
||||
static boost_intrusive_has_member_function_callable_with::no_type Test(...);
|
||||
@ -185,96 +298,6 @@
|
||||
|
||||
#else //#if !defined(BOOST_INTRUSIVE_PERFECT_FORWARDING)
|
||||
|
||||
template<typename Fun, bool HasFunc, class ...Args>
|
||||
struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl);
|
||||
|
||||
template<typename Fun, class ...Args>
|
||||
struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl)
|
||||
<Fun, false, Args...>
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
//Special case for 0 args
|
||||
template< class F
|
||||
, std::size_t N =
|
||||
sizeof((boost::move_detail::declval<F>().
|
||||
BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME (), 0))>
|
||||
struct BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)
|
||||
{
|
||||
boost_intrusive_has_member_function_callable_with::yes_type dummy;
|
||||
BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)(int);
|
||||
};
|
||||
|
||||
//For buggy compilers like MSVC 7.1+ ((F*)0)->func() does not
|
||||
//SFINAE-out the zeroarg_checker_ instantiation but sizeof yields to 0.
|
||||
template<class F>
|
||||
struct BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<F, 0>
|
||||
{
|
||||
boost_intrusive_has_member_function_callable_with::no_type dummy;
|
||||
BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)(int);
|
||||
};
|
||||
|
||||
template<typename Fun>
|
||||
struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl)
|
||||
<Fun, true>
|
||||
{
|
||||
template<class U>
|
||||
static BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)
|
||||
<U> Test(BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<U>*);
|
||||
|
||||
template <class U>
|
||||
static boost_intrusive_has_member_function_callable_with::no_type Test(...);
|
||||
|
||||
static const bool value = sizeof(Test< Fun >(0))
|
||||
== sizeof(boost_intrusive_has_member_function_callable_with::yes_type);
|
||||
};
|
||||
|
||||
template<typename Fun, class ...DontCares>
|
||||
struct BOOST_PP_CAT( funwrap_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME )
|
||||
: Fun
|
||||
{
|
||||
BOOST_PP_CAT( funwrap_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME )();
|
||||
using Fun::BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME;
|
||||
|
||||
boost_intrusive_has_member_function_callable_with::private_type
|
||||
BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME
|
||||
( DontCares...) const;
|
||||
};
|
||||
|
||||
template<typename Fun, class ...Args>
|
||||
struct BOOST_PP_CAT( BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME), _impl)
|
||||
<Fun, true , Args...>
|
||||
{
|
||||
template<class T>
|
||||
struct make_dontcare
|
||||
{
|
||||
typedef boost_intrusive_has_member_function_callable_with::dont_care type;
|
||||
};
|
||||
|
||||
typedef BOOST_PP_CAT( funwrap_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME )
|
||||
<Fun, typename make_dontcare<Args>::type...> FunWrap;
|
||||
|
||||
static bool const value = (sizeof(boost_intrusive_has_member_function_callable_with::no_type) ==
|
||||
sizeof(boost_intrusive_has_member_function_callable_with::is_private_type
|
||||
( (::boost::move_detail::declval< FunWrap >().
|
||||
BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME
|
||||
( ::boost::move_detail::declval<Args>()... ), 0) )
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
template<typename Fun, class ...Args>
|
||||
struct BOOST_PP_CAT( has_member_function_callable_with_
|
||||
, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)
|
||||
: public BOOST_PP_CAT( BOOST_PP_CAT(has_member_function_callable_with_
|
||||
, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl)
|
||||
< Fun
|
||||
, BOOST_PP_CAT( has_member_function_named_
|
||||
, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME )<Fun>::value
|
||||
, Args... >
|
||||
{};
|
||||
|
||||
#endif //#if !defined(BOOST_INTRUSIVE_PERFECT_FORWARDING)
|
||||
|
||||
BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END
|
||||
|
@ -17,7 +17,7 @@
|
||||
#ifndef BOOST_INTRUSIVE_ALLOCATOR_MEMORY_UTIL_HPP
|
||||
#define BOOST_INTRUSIVE_ALLOCATOR_MEMORY_UTIL_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
#if defined(_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
@ -118,25 +118,25 @@ struct LowPriorityConversion
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME pointer_to
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace intrusive { namespace detail {
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
|
||||
#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, 1, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
|
||||
#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 1, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
|
||||
#include BOOST_PP_ITERATE()
|
||||
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME static_cast_from
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace intrusive { namespace detail {
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
|
||||
#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, 1, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
|
||||
#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 1, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
|
||||
#include BOOST_PP_ITERATE()
|
||||
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME const_cast_from
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace intrusive { namespace detail {
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
|
||||
#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, 1, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
|
||||
#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 1, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
|
||||
#include BOOST_PP_ITERATE()
|
||||
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME dynamic_cast_from
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace intrusive { namespace detail {
|
||||
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
|
||||
#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, 1, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
|
||||
#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 1, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
|
||||
#include BOOST_PP_ITERATE()
|
||||
|
||||
namespace boost {
|
||||
|
@ -29,6 +29,12 @@ struct bool_
|
||||
static const bool value = C_;
|
||||
};
|
||||
|
||||
template< class Integer, Integer Value >
|
||||
struct integer
|
||||
{
|
||||
static const Integer value = Value;
|
||||
};
|
||||
|
||||
typedef bool_<true> true_;
|
||||
typedef bool_<false> false_;
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
#ifndef BOOST_INTRUSIVE_DETAIL_PREPROCESSOR_HPP
|
||||
#define BOOST_INTRUSIVE_DETAIL_PREPROCESSOR_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
#if defined(_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -13,12 +13,47 @@
|
||||
#ifndef BOOST_INTRUSIVE_FWD_HPP
|
||||
#define BOOST_INTRUSIVE_FWD_HPP
|
||||
|
||||
//! \file
|
||||
//! This header file forward declares most Intrusive classes.
|
||||
//!
|
||||
//! It forward declares the following containers and hooks:
|
||||
//! - boost::intrusive::slist / boost::intrusive::slist_base_hook / boost::intrusive::slist_member_hook
|
||||
//! - boost::intrusive::list / boost::intrusive::list_base_hook / boost::intrusive::list_member_hook
|
||||
//! - boost::intrusive::bstree / boost::intrusive::bs_set / boost::intrusive::bs_multiset /
|
||||
//! boost::intrusive::bs_set_base_hook / boost::intrusive::bs_set_member_hook
|
||||
//! - boost::intrusive::rbtree / boost::intrusive::set / boost::intrusive::multiset /
|
||||
//! boost::intrusive::set_base_hook / boost::intrusive::set_member_hook
|
||||
//! - boost::intrusive::avltree / boost::intrusive::avl_set / boost::intrusive::avl_multiset /
|
||||
//! boost::intrusive::avl_set_base_hook / boost::intrusive::avl_set_member_hook
|
||||
//! - boost::intrusive::splaytree / boost::intrusive::splay_set / boost::intrusive::splay_multiset
|
||||
//! - boost::intrusive::sgtree / boost::intrusive::sg_set / boost::intrusive::sg_multiset
|
||||
//! - boost::intrusive::treap / boost::intrusive::treap_set / boost::intrusive::treap_multiset
|
||||
//! - boost::intrusive::hashtable / boost::intrusive::unordered_set / boost::intrusive::unordered_multiset /
|
||||
//! boost::intrusive::unordered_set_base_hook / boost::intrusive::unordered_set_member_hook /
|
||||
//! - boost::intrusive::any_base_hook / boost::intrusive::any_member_hook
|
||||
//!
|
||||
//! It forward declares the following container or hook options:
|
||||
//! - boost::intrusive::constant_time_size / boost::intrusive::size_type / boost::intrusive::compare / boost::intrusive::equal
|
||||
//! - boost::intrusive::floating_point / boost::intrusive::priority / boost::intrusive::hash
|
||||
//! - boost::intrusive::value_traits / boost::intrusive::member_hook / boost::intrusive::function_hook / boost::intrusive::base_hook
|
||||
//! - boost::intrusive::void_pointer / boost::intrusive::tag / boost::intrusive::link_mode
|
||||
//! - boost::intrusive::optimize_size / boost::intrusive::linear / boost::intrusive::cache_last
|
||||
//! - boost::intrusive::bucket_traits / boost::intrusive::store_hash / boost::intrusive::optimize_multikey
|
||||
//! - boost::intrusive::power_2_buckets / boost::intrusive::cache_begin / boost::intrusive::compare_hash / boost::intrusive::incremental
|
||||
//!
|
||||
//! It forward declares the following value traits utilities:
|
||||
//! - boost::intrusive::value_traits / boost::intrusive::derivation_value_traits /
|
||||
//! boost::intrusive::trivial_value_traits
|
||||
//!
|
||||
//! Finally it forward declares the following general purpose utilities:
|
||||
//! - boost::intrusive::pointer_plus_bits / boost::intrusive::priority_compare.
|
||||
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
|
||||
|
||||
#include <cstddef>
|
||||
#include <boost/intrusive/link_mode.hpp>
|
||||
#include <boost/intrusive/detail/workaround.hpp>
|
||||
|
||||
/// @cond
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
|
||||
@ -33,15 +68,33 @@ class circular_list_algorithms;
|
||||
template<class NodeTraits>
|
||||
class circular_slist_algorithms;
|
||||
|
||||
template<class NodeTraits>
|
||||
class linear_slist_algorithms;
|
||||
|
||||
template<class NodeTraits>
|
||||
class bstree_algorithms;
|
||||
|
||||
template<class NodeTraits>
|
||||
class rbtree_algorithms;
|
||||
|
||||
template<class NodeTraits>
|
||||
class avltree_algorithms;
|
||||
|
||||
template<class NodeTraits>
|
||||
class sgtree_algorithms;
|
||||
|
||||
template<class NodeTraits>
|
||||
class splaytree_algorithms;
|
||||
|
||||
template<class NodeTraits>
|
||||
class treap_algorithms;
|
||||
|
||||
////////////////////////////
|
||||
// Containers
|
||||
////////////////////////////
|
||||
|
||||
//slist
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template
|
||||
< class T
|
||||
, class O1 = void
|
||||
@ -55,7 +108,7 @@ template<class T, class ...Options>
|
||||
#endif
|
||||
class slist;
|
||||
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template
|
||||
< class O1 = void
|
||||
, class O2 = void
|
||||
@ -66,7 +119,7 @@ template<class ...Options>
|
||||
#endif
|
||||
class slist_base_hook;
|
||||
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template
|
||||
< class O1 = void
|
||||
, class O2 = void
|
||||
@ -78,7 +131,7 @@ template<class ...Options>
|
||||
class slist_member_hook;
|
||||
|
||||
//list
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template
|
||||
< class T
|
||||
, class O1 = void
|
||||
@ -90,7 +143,7 @@ template<class T, class ...Options>
|
||||
#endif
|
||||
class list;
|
||||
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template
|
||||
< class O1 = void
|
||||
, class O2 = void
|
||||
@ -101,7 +154,7 @@ template<class ...Options>
|
||||
#endif
|
||||
class list_base_hook;
|
||||
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template
|
||||
< class O1 = void
|
||||
, class O2 = void
|
||||
@ -112,19 +165,8 @@ template<class ...Options>
|
||||
#endif
|
||||
class list_member_hook;
|
||||
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template
|
||||
< class O1 = void
|
||||
, class O2 = void
|
||||
, class O3 = void
|
||||
>
|
||||
#else
|
||||
template<class ...Options>
|
||||
#endif
|
||||
class list_hook;
|
||||
|
||||
//rbtree/set/multiset
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template
|
||||
< class T
|
||||
, class O1 = void
|
||||
@ -137,7 +179,7 @@ template<class T, class ...Options>
|
||||
#endif
|
||||
class rbtree;
|
||||
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template
|
||||
< class T
|
||||
, class O1 = void
|
||||
@ -150,7 +192,7 @@ template<class T, class ...Options>
|
||||
#endif
|
||||
class set;
|
||||
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template
|
||||
< class T
|
||||
, class O1 = void
|
||||
@ -163,7 +205,7 @@ template<class T, class ...Options>
|
||||
#endif
|
||||
class multiset;
|
||||
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template
|
||||
< class O1 = void
|
||||
, class O2 = void
|
||||
@ -175,7 +217,7 @@ template<class ...Options>
|
||||
#endif
|
||||
class set_base_hook;
|
||||
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template
|
||||
< class O1 = void
|
||||
, class O2 = void
|
||||
@ -188,7 +230,7 @@ template<class ...Options>
|
||||
class set_member_hook;
|
||||
|
||||
//splaytree/splay_set/splay_multiset
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template
|
||||
< class T
|
||||
, class O1 = void
|
||||
@ -201,7 +243,7 @@ template<class T, class ...Options>
|
||||
#endif
|
||||
class splaytree;
|
||||
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template
|
||||
< class T
|
||||
, class O1 = void
|
||||
@ -214,7 +256,7 @@ template<class T, class ...Options>
|
||||
#endif
|
||||
class splay_set;
|
||||
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template
|
||||
< class T
|
||||
, class O1 = void
|
||||
@ -227,30 +269,8 @@ template<class T, class ...Options>
|
||||
#endif
|
||||
class splay_multiset;
|
||||
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template
|
||||
< class O1 = void
|
||||
, class O2 = void
|
||||
, class O3 = void
|
||||
>
|
||||
#else
|
||||
template<class ...Options>
|
||||
#endif
|
||||
class splay_set_base_hook;
|
||||
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template
|
||||
< class O1 = void
|
||||
, class O2 = void
|
||||
, class O3 = void
|
||||
>
|
||||
#else
|
||||
template<class ...Options>
|
||||
#endif
|
||||
class splay_set_member_hook;
|
||||
|
||||
//avltree/avl_set/avl_multiset
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template
|
||||
< class T
|
||||
, class O1 = void
|
||||
@ -263,7 +283,7 @@ template<class T, class ...Options>
|
||||
#endif
|
||||
class avltree;
|
||||
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template
|
||||
< class T
|
||||
, class O1 = void
|
||||
@ -276,7 +296,7 @@ template<class T, class ...Options>
|
||||
#endif
|
||||
class avl_set;
|
||||
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template
|
||||
< class T
|
||||
, class O1 = void
|
||||
@ -289,7 +309,7 @@ template<class T, class ...Options>
|
||||
#endif
|
||||
class avl_multiset;
|
||||
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template
|
||||
< class O1 = void
|
||||
, class O2 = void
|
||||
@ -301,7 +321,7 @@ template<class ...Options>
|
||||
#endif
|
||||
class avl_set_base_hook;
|
||||
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template
|
||||
< class O1 = void
|
||||
, class O2 = void
|
||||
@ -315,7 +335,7 @@ class avl_set_member_hook;
|
||||
|
||||
|
||||
//treap/treap_set/treap_multiset
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template
|
||||
< class T
|
||||
, class O1 = void
|
||||
@ -328,7 +348,7 @@ template<class T, class ...Options>
|
||||
#endif
|
||||
class treap;
|
||||
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template
|
||||
< class T
|
||||
, class O1 = void
|
||||
@ -341,7 +361,7 @@ template<class T, class ...Options>
|
||||
#endif
|
||||
class treap_set;
|
||||
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template
|
||||
< class T
|
||||
, class O1 = void
|
||||
@ -354,12 +374,8 @@ template<class T, class ...Options>
|
||||
#endif
|
||||
class treap_multiset;
|
||||
|
||||
//Default priority comparison functor
|
||||
template <class T>
|
||||
struct priority_compare;
|
||||
|
||||
//sgtree/sg_set/sg_multiset
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template
|
||||
< class T
|
||||
, class O1 = void
|
||||
@ -372,7 +388,7 @@ template<class T, class ...Options>
|
||||
#endif
|
||||
class sgtree;
|
||||
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template
|
||||
< class T
|
||||
, class O1 = void
|
||||
@ -385,7 +401,7 @@ template<class T, class ...Options>
|
||||
#endif
|
||||
class sg_set;
|
||||
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template
|
||||
< class T
|
||||
, class O1 = void
|
||||
@ -398,7 +414,7 @@ template<class T, class ...Options>
|
||||
#endif
|
||||
class sg_multiset;
|
||||
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template
|
||||
< class T
|
||||
, class O1 = void
|
||||
@ -411,7 +427,7 @@ template<class T, class ...Options>
|
||||
#endif
|
||||
class bstree;
|
||||
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template
|
||||
< class T
|
||||
, class O1 = void
|
||||
@ -424,7 +440,7 @@ template<class T, class ...Options>
|
||||
#endif
|
||||
class bs_set;
|
||||
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template
|
||||
< class T
|
||||
, class O1 = void
|
||||
@ -437,7 +453,7 @@ template<class T, class ...Options>
|
||||
#endif
|
||||
class bs_multiset;
|
||||
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template
|
||||
< class O1 = void
|
||||
, class O2 = void
|
||||
@ -448,7 +464,7 @@ template<class ...Options>
|
||||
#endif
|
||||
class bs_set_base_hook;
|
||||
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template
|
||||
< class O1 = void
|
||||
, class O2 = void
|
||||
@ -461,7 +477,7 @@ class bs_set_member_hook;
|
||||
|
||||
//hashtable/unordered_set/unordered_multiset
|
||||
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template
|
||||
< class T
|
||||
, class O1 = void
|
||||
@ -480,7 +496,7 @@ template<class T, class ...Options>
|
||||
#endif
|
||||
class hashtable;
|
||||
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template
|
||||
< class T
|
||||
, class O1 = void
|
||||
@ -499,7 +515,7 @@ template<class T, class ...Options>
|
||||
#endif
|
||||
class unordered_set;
|
||||
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template
|
||||
< class T
|
||||
, class O1 = void
|
||||
@ -518,7 +534,7 @@ template<class T, class ...Options>
|
||||
#endif
|
||||
class unordered_multiset;
|
||||
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template
|
||||
< class O1 = void
|
||||
, class O2 = void
|
||||
@ -530,7 +546,7 @@ template<class ...Options>
|
||||
#endif
|
||||
class unordered_set_base_hook;
|
||||
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template
|
||||
< class O1 = void
|
||||
, class O2 = void
|
||||
@ -542,7 +558,7 @@ template<class ...Options>
|
||||
#endif
|
||||
class unordered_set_member_hook;
|
||||
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template
|
||||
< class O1 = void
|
||||
, class O2 = void
|
||||
@ -553,7 +569,7 @@ template<class ...Options>
|
||||
#endif
|
||||
class any_base_hook;
|
||||
|
||||
#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template
|
||||
< class O1 = void
|
||||
, class O2 = void
|
||||
@ -564,9 +580,126 @@ template<class ...Options>
|
||||
#endif
|
||||
class any_member_hook;
|
||||
|
||||
//Options
|
||||
|
||||
template<bool Enabled>
|
||||
struct constant_time_size;
|
||||
|
||||
template<typename SizeType>
|
||||
struct size_type;
|
||||
|
||||
template<typename Compare>
|
||||
struct compare;
|
||||
|
||||
template<bool Enabled>
|
||||
struct floating_point;
|
||||
|
||||
template<typename Equal>
|
||||
struct equal;
|
||||
|
||||
template<typename Priority>
|
||||
struct priority;
|
||||
|
||||
template<typename Hash>
|
||||
struct hash;
|
||||
|
||||
template<typename ValueTraits> struct value_traits;
|
||||
|
||||
template< typename Parent
|
||||
, typename MemberHook
|
||||
, MemberHook Parent::* PtrToMember>
|
||||
struct member_hook;
|
||||
|
||||
template<typename Functor>
|
||||
struct function_hook;
|
||||
|
||||
template<typename BaseHook>
|
||||
struct base_hook;
|
||||
|
||||
template<typename VoidPointer>
|
||||
struct void_pointer;
|
||||
|
||||
template<typename Tag>
|
||||
struct tag;
|
||||
|
||||
template<link_mode_type LinkType>
|
||||
struct link_mode;
|
||||
|
||||
template<bool Enabled> struct
|
||||
optimize_size;
|
||||
|
||||
template<bool Enabled>
|
||||
struct linear;
|
||||
|
||||
template<bool Enabled>
|
||||
struct cache_last;
|
||||
|
||||
template<typename BucketTraits>
|
||||
struct bucket_traits;
|
||||
|
||||
template<bool Enabled>
|
||||
struct store_hash;
|
||||
|
||||
template<bool Enabled>
|
||||
struct optimize_multikey;
|
||||
|
||||
template<bool Enabled>
|
||||
struct power_2_buckets;
|
||||
|
||||
template<bool Enabled>
|
||||
struct cache_begin;
|
||||
|
||||
template<bool Enabled>
|
||||
struct compare_hash;
|
||||
|
||||
template<bool Enabled>
|
||||
struct incremental;
|
||||
|
||||
//Value traits
|
||||
|
||||
template<typename ValueTraits>
|
||||
struct value_traits;
|
||||
|
||||
template< typename Parent
|
||||
, typename MemberHook
|
||||
, MemberHook Parent::* PtrToMember>
|
||||
struct member_hook;
|
||||
|
||||
template< typename Functor>
|
||||
struct function_hook;
|
||||
|
||||
template<typename BaseHook>
|
||||
struct base_hook;
|
||||
|
||||
template<class T, class NodeTraits, link_mode_type LinkMode = safe_link>
|
||||
struct derivation_value_traits;
|
||||
|
||||
template<class NodeTraits, link_mode_type LinkMode = normal_link>
|
||||
struct trivial_value_traits;
|
||||
|
||||
//Additional utilities
|
||||
|
||||
template<typename VoidPointer, std::size_t Alignment>
|
||||
struct max_pointer_plus_bits;
|
||||
|
||||
template<std::size_t Alignment>
|
||||
struct max_pointer_plus_bits<void *, Alignment>;
|
||||
|
||||
template<typename Pointer, std::size_t NumBits>
|
||||
struct pointer_plus_bits;
|
||||
|
||||
template<typename T, std::size_t NumBits>
|
||||
struct pointer_plus_bits<T *, NumBits>;
|
||||
|
||||
template<typename Ptr>
|
||||
struct pointer_traits;
|
||||
|
||||
template<typename T>
|
||||
struct pointer_traits<T *>;
|
||||
|
||||
} //namespace intrusive {
|
||||
} //namespace boost {
|
||||
|
||||
/// @endcond
|
||||
#endif //#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
|
||||
|
||||
#endif //#ifndef BOOST_INTRUSIVE_FWD_HPP
|
||||
|
@ -77,7 +77,7 @@ struct make_list_base_hook
|
||||
//! \c auto_unlink or \c safe_link).
|
||||
//!
|
||||
//! \c void_pointer<> is the pointer type that will be used internally in the hook
|
||||
//! and the the container configured to use this hook.
|
||||
//! and the container configured to use this hook.
|
||||
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template<class ...Options>
|
||||
#else
|
||||
@ -199,7 +199,7 @@ struct make_list_member_hook
|
||||
//! \c auto_unlink or \c safe_link).
|
||||
//!
|
||||
//! \c void_pointer<> is the pointer type that will be used internally in the hook
|
||||
//! and the the container configured to use this hook.
|
||||
//! and the container configured to use this hook.
|
||||
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template<class ...Options>
|
||||
#else
|
||||
|
@ -13,6 +13,9 @@
|
||||
#ifndef BOOST_INTRUSIVE_MEMBER_VALUE_TRAITS_HPP
|
||||
#define BOOST_INTRUSIVE_MEMBER_VALUE_TRAITS_HPP
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
|
||||
#include <boost/intrusive/link_mode.hpp>
|
||||
#include <iterator>
|
||||
#include <boost/intrusive/detail/parent_from_member.hpp>
|
||||
@ -26,7 +29,11 @@ namespace intrusive {
|
||||
//!store a node_traits::node
|
||||
template< class T, class NodeTraits
|
||||
, typename NodeTraits::node T::* PtrToMember
|
||||
, link_mode_type LinkMode = safe_link>
|
||||
, link_mode_type LinkMode
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
= safe_link
|
||||
#endif
|
||||
>
|
||||
struct member_value_traits
|
||||
{
|
||||
public:
|
||||
@ -67,4 +74,6 @@ struct member_value_traits
|
||||
} //namespace intrusive
|
||||
} //namespace boost
|
||||
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTRUSIVE_MEMBER_VALUE_TRAITS_HPP
|
||||
|
@ -16,15 +16,15 @@
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
#include <boost/intrusive/link_mode.hpp>
|
||||
#include <boost/intrusive/pack_options.hpp>
|
||||
#include <boost/intrusive/detail/mpl.hpp>
|
||||
#include <boost/intrusive/detail/utilities.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
|
||||
/// @cond
|
||||
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
|
||||
//typedef void default_tag;
|
||||
struct default_tag;
|
||||
@ -34,8 +34,6 @@ namespace detail{
|
||||
|
||||
struct default_hook_tag{};
|
||||
|
||||
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
|
||||
#define BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER) \
|
||||
struct BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER : public default_hook_tag\
|
||||
{\
|
||||
@ -50,35 +48,9 @@ BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_rbtree_hook);
|
||||
BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_hashtable_hook);
|
||||
BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_avltree_hook);
|
||||
BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_bstree_hook);
|
||||
//BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_splaytree_hook);
|
||||
//BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_sgtree_hook);
|
||||
//BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_treap_hook);
|
||||
|
||||
#undef BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION
|
||||
|
||||
#endif //BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
|
||||
template <class ValueTraits>
|
||||
struct eval_value_traits
|
||||
{
|
||||
typedef typename ValueTraits::value_traits type;
|
||||
};
|
||||
|
||||
template<class ValueTraits>
|
||||
struct get_real_value_traits
|
||||
: public eval_if_c
|
||||
< external_value_traits_bool_is_true<ValueTraits>::value
|
||||
, eval_value_traits<ValueTraits>
|
||||
, identity<ValueTraits>
|
||||
>
|
||||
{};
|
||||
|
||||
template <class BucketTraits>
|
||||
struct eval_bucket_traits
|
||||
{
|
||||
typedef typename BucketTraits::bucket_traits type;
|
||||
};
|
||||
|
||||
template <class T, class BaseHook>
|
||||
struct concrete_hook_base_value_traits
|
||||
{
|
||||
@ -165,7 +137,7 @@ struct get_value_traits
|
||||
//...get it's internal value traits using
|
||||
//the provided T value type.
|
||||
, get_base_value_traits<T, supposed_value_traits>
|
||||
//...else use it's internal value traits tag
|
||||
//...else use its internal value traits tag
|
||||
//(member hooks and custom value traits are in this group)
|
||||
, detail::eval_if_c
|
||||
< internal_member_value_traits<supposed_value_traits>::value
|
||||
@ -191,7 +163,7 @@ struct get_node_traits
|
||||
//...get it's internal value traits using
|
||||
//the provided T value type.
|
||||
, get_base_node_traits<supposed_value_traits>
|
||||
//...else use it's internal value traits tag
|
||||
//...else use its internal value traits tag
|
||||
//(member hooks and custom value traits are in this group)
|
||||
, detail::eval_if_c
|
||||
< internal_member_value_traits<supposed_value_traits>::value
|
||||
@ -203,50 +175,20 @@ struct get_node_traits
|
||||
|
||||
} //namespace detail{
|
||||
|
||||
/// @endcond
|
||||
#endif //BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
|
||||
//!This option setter specifies if the intrusive
|
||||
//!container stores its size as a member to
|
||||
//!obtain constant-time size() member.
|
||||
template<bool Enabled>
|
||||
struct constant_time_size
|
||||
{
|
||||
/// @cond
|
||||
template<class Base>
|
||||
struct pack : Base
|
||||
{
|
||||
static const bool constant_time_size = Enabled;
|
||||
};
|
||||
/// @endcond
|
||||
};
|
||||
BOOST_INTRUSIVE_OPTION_CONSTANT(constant_time_size, bool, Enabled, constant_time_size)
|
||||
|
||||
//!This option setter specifies the type that
|
||||
//!the container will use to store its size.
|
||||
template<class SizeType>
|
||||
struct size_type
|
||||
{
|
||||
/// @cond
|
||||
template<class Base>
|
||||
struct pack : Base
|
||||
{
|
||||
typedef SizeType size_type;
|
||||
};
|
||||
/// @endcond
|
||||
};
|
||||
BOOST_INTRUSIVE_OPTION_TYPE(size_type, SizeType, SizeType, size_type)
|
||||
|
||||
//!This option setter specifies the strict weak ordering
|
||||
//!comparison functor for the value type
|
||||
template<class Compare>
|
||||
struct compare
|
||||
{
|
||||
/// @cond
|
||||
template<class Base>
|
||||
struct pack : Base
|
||||
{
|
||||
typedef Compare compare;
|
||||
};
|
||||
/// @endcond
|
||||
};
|
||||
BOOST_INTRUSIVE_OPTION_TYPE(compare, Compare, Compare, compare)
|
||||
|
||||
//!This option setter for scapegoat containers specifies if
|
||||
//!the intrusive scapegoat container should use a non-variable
|
||||
@ -260,74 +202,39 @@ struct compare
|
||||
//!If the user only needs an alpha value near 1/sqrt(2), this
|
||||
//!option also improves performance since avoids logarithm
|
||||
//!and division operations when rebalancing the tree.
|
||||
template<bool Enabled>
|
||||
struct floating_point
|
||||
{
|
||||
/// @cond
|
||||
template<class Base>
|
||||
struct pack : Base
|
||||
{
|
||||
static const bool floating_point = Enabled;
|
||||
};
|
||||
/// @endcond
|
||||
};
|
||||
BOOST_INTRUSIVE_OPTION_CONSTANT(floating_point, bool, Enabled, floating_point)
|
||||
|
||||
//!This option setter specifies the equality
|
||||
//!functor for the value type
|
||||
template<class Equal>
|
||||
struct equal
|
||||
{
|
||||
/// @cond
|
||||
template<class Base>
|
||||
struct pack : Base
|
||||
{
|
||||
typedef Equal equal;
|
||||
};
|
||||
/// @endcond
|
||||
};
|
||||
BOOST_INTRUSIVE_OPTION_TYPE(equal, Equal, Equal, equal)
|
||||
|
||||
//!This option setter specifies the equality
|
||||
//!functor for the value type
|
||||
template<class Priority>
|
||||
struct priority
|
||||
{
|
||||
/// @cond
|
||||
template<class Base>
|
||||
struct pack : Base
|
||||
{
|
||||
typedef Priority priority;
|
||||
};
|
||||
/// @endcond
|
||||
};
|
||||
BOOST_INTRUSIVE_OPTION_TYPE(priority, Priority, Priority, priority)
|
||||
|
||||
//!This option setter specifies the hash
|
||||
//!functor for the value type
|
||||
template<class Hash>
|
||||
struct hash
|
||||
{
|
||||
/// @cond
|
||||
template<class Base>
|
||||
struct pack : Base
|
||||
{
|
||||
typedef Hash hash;
|
||||
};
|
||||
/// @endcond
|
||||
};
|
||||
BOOST_INTRUSIVE_OPTION_TYPE(hash, Hash, Hash, hash)
|
||||
|
||||
//!This option setter specifies the relationship between the type
|
||||
//!to be managed by the container (the value type) and the node to be
|
||||
//!used in the node algorithms. It also specifies the linking policy.
|
||||
template<typename ValueTraits>
|
||||
struct value_traits
|
||||
{
|
||||
/// @cond
|
||||
template<class Base>
|
||||
struct pack : Base
|
||||
{
|
||||
typedef ValueTraits proto_value_traits;
|
||||
};
|
||||
/// @endcond
|
||||
};
|
||||
BOOST_INTRUSIVE_OPTION_TYPE(value_traits, ValueTraits, ValueTraits, proto_value_traits)
|
||||
|
||||
//#define BOOST_INTRUSIVE_COMMA ,
|
||||
//#define BOOST_INTRUSIVE_LESS <
|
||||
//#define BOOST_INTRUSIVE_MORE >
|
||||
//BOOST_INTRUSIVE_OPTION_TYPE (member_hook, Parent BOOST_INTRUSIVE_COMMA class MemberHook BOOST_INTRUSIVE_COMMA MemberHook Parent::* PtrToMember , mhtraits BOOST_INTRUSIVE_LESS Parent BOOST_INTRUSIVE_COMMA MemberHook BOOST_INTRUSIVE_COMMA PtrToMember BOOST_INTRUSIVE_MORE , proto_value_traits)
|
||||
//template< class Parent , class MemberHook , MemberHook Parent::* PtrToMember>
|
||||
//struct member_hook {
|
||||
// template<class Base> struct pack : Base {
|
||||
// typedef mhtraits < Parent , MemberHook , PtrToMember > proto_value_traits;
|
||||
// };
|
||||
//};
|
||||
//
|
||||
//#undef BOOST_INTRUSIVE_COMMA
|
||||
//#undef BOOST_INTRUSIVE_LESS
|
||||
//#undef BOOST_INTRUSIVE_MORE
|
||||
|
||||
//!This option setter specifies the member hook the
|
||||
//!container must use.
|
||||
@ -336,27 +243,21 @@ template< typename Parent
|
||||
, MemberHook Parent::* PtrToMember>
|
||||
struct member_hook
|
||||
{
|
||||
/// @cond
|
||||
/*
|
||||
typedef typename MemberHook::hooktags::node_traits node_traits;
|
||||
typedef typename node_traits::node node_type;
|
||||
typedef node_type Parent::* Ptr2MemNode;
|
||||
typedef mhtraits
|
||||
< Parent
|
||||
, node_traits
|
||||
//This cast is really ugly but necessary to reduce template bloat.
|
||||
//Since we control the layout between the hook and the node, and there is
|
||||
//always single inheritance, the offset of the node is exactly the offset of
|
||||
//the hook. Since the node type is shared between all member hooks, this saves
|
||||
//quite a lot of symbol stuff.
|
||||
, (Ptr2MemNode)PtrToMember
|
||||
, MemberHook::hooktags::link_mode> member_value_traits;
|
||||
*/
|
||||
typedef mhtraits
|
||||
< Parent
|
||||
, MemberHook
|
||||
, PtrToMember
|
||||
> member_value_traits;
|
||||
// @cond
|
||||
// typedef typename MemberHook::hooktags::node_traits node_traits;
|
||||
// typedef typename node_traits::node node_type;
|
||||
// typedef node_type Parent::* Ptr2MemNode;
|
||||
// typedef mhtraits
|
||||
// < Parent
|
||||
// , node_traits
|
||||
// //This cast is really ugly but necessary to reduce template bloat.
|
||||
// //Since we control the layout between the hook and the node, and there is
|
||||
// //always single inheritance, the offset of the node is exactly the offset of
|
||||
// //the hook. Since the node type is shared between all member hooks, this saves
|
||||
// //quite a lot of symbol stuff.
|
||||
// , (Ptr2MemNode)PtrToMember
|
||||
// , MemberHook::hooktags::link_mode> member_value_traits;
|
||||
typedef mhtraits <Parent, MemberHook, PtrToMember> member_value_traits;
|
||||
template<class Base>
|
||||
struct pack : Base
|
||||
{
|
||||
@ -365,158 +266,55 @@ struct member_hook
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
|
||||
//!This option setter specifies the function object that will
|
||||
//!be used to convert between values to be inserted in a container
|
||||
//!and the hook to be used for that purpose.
|
||||
template< typename Functor>
|
||||
struct function_hook
|
||||
{
|
||||
/// @cond
|
||||
typedef fhtraits
|
||||
<Functor> function_value_traits;
|
||||
template<class Base>
|
||||
struct pack : Base
|
||||
{
|
||||
typedef function_value_traits proto_value_traits;
|
||||
};
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
BOOST_INTRUSIVE_OPTION_TYPE(function_hook, Functor, fhtraits<Functor>, proto_value_traits)
|
||||
|
||||
//!This option setter specifies that the container
|
||||
//!must use the specified base hook
|
||||
template<typename BaseHook>
|
||||
struct base_hook
|
||||
{
|
||||
/// @cond
|
||||
template<class Base>
|
||||
struct pack : Base
|
||||
{
|
||||
typedef BaseHook proto_value_traits;
|
||||
};
|
||||
/// @endcond
|
||||
};
|
||||
BOOST_INTRUSIVE_OPTION_TYPE(base_hook, BaseHook, BaseHook, proto_value_traits)
|
||||
|
||||
//!This option setter specifies the type of
|
||||
//!a void pointer. This will instruct the hook
|
||||
//!to use this type of pointer instead of the
|
||||
//!default one
|
||||
template<class VoidPointer>
|
||||
struct void_pointer
|
||||
{
|
||||
/// @cond
|
||||
template<class Base>
|
||||
struct pack : Base
|
||||
{
|
||||
typedef VoidPointer void_pointer;
|
||||
};
|
||||
/// @endcond
|
||||
};
|
||||
BOOST_INTRUSIVE_OPTION_TYPE(void_pointer, VoidPointer, VoidPointer, void_pointer)
|
||||
|
||||
//!This option setter specifies the type of
|
||||
//!the tag of a base hook. A type cannot have two
|
||||
//!base hooks of the same type, so a tag can be used
|
||||
//!to differentiate two base hooks with otherwise same type
|
||||
template<class Tag>
|
||||
struct tag
|
||||
{
|
||||
/// @cond
|
||||
template<class Base>
|
||||
struct pack : Base
|
||||
{
|
||||
typedef Tag tag;
|
||||
};
|
||||
/// @endcond
|
||||
};
|
||||
BOOST_INTRUSIVE_OPTION_TYPE(tag, Tag, Tag, tag)
|
||||
|
||||
//!This option setter specifies the link mode
|
||||
//!(normal_link, safe_link or auto_unlink)
|
||||
template<link_mode_type LinkType>
|
||||
struct link_mode
|
||||
{
|
||||
/// @cond
|
||||
template<class Base>
|
||||
struct pack : Base
|
||||
{
|
||||
static const link_mode_type link_mode = LinkType;
|
||||
};
|
||||
/// @endcond
|
||||
};
|
||||
BOOST_INTRUSIVE_OPTION_CONSTANT(link_mode, link_mode_type, LinkType, link_mode)
|
||||
|
||||
//!This option setter specifies if the hook
|
||||
//!should be optimized for size instead of for speed.
|
||||
template<bool Enabled>
|
||||
struct optimize_size
|
||||
{
|
||||
/// @cond
|
||||
template<class Base>
|
||||
struct pack : Base
|
||||
{
|
||||
static const bool optimize_size = Enabled;
|
||||
};
|
||||
/// @endcond
|
||||
};
|
||||
BOOST_INTRUSIVE_OPTION_CONSTANT(optimize_size, bool, Enabled, optimize_size)
|
||||
|
||||
//!This option setter specifies if the list container should
|
||||
//!This option setter specifies if the slist container should
|
||||
//!use a linear implementation instead of a circular one.
|
||||
template<bool Enabled>
|
||||
struct linear
|
||||
{
|
||||
/// @cond
|
||||
template<class Base>
|
||||
struct pack : Base
|
||||
{
|
||||
static const bool linear = Enabled;
|
||||
};
|
||||
/// @endcond
|
||||
};
|
||||
BOOST_INTRUSIVE_OPTION_CONSTANT(linear, bool, Enabled, linear)
|
||||
|
||||
//!This option setter specifies if the list container should
|
||||
//!use a linear implementation instead of a circular one.
|
||||
template<bool Enabled>
|
||||
struct cache_last
|
||||
{
|
||||
/// @cond
|
||||
template<class Base>
|
||||
struct pack : Base
|
||||
{
|
||||
static const bool cache_last = Enabled;
|
||||
};
|
||||
/// @endcond
|
||||
};
|
||||
//!If true, slist also stores a pointer to the last element of the singly linked list.
|
||||
//!This allows O(1) swap and splice_after(iterator, slist &) for circular slists and makes
|
||||
//!possible new functions like push_back(reference) and back().
|
||||
BOOST_INTRUSIVE_OPTION_CONSTANT(cache_last, bool, Enabled, cache_last)
|
||||
|
||||
//!This option setter specifies the bucket traits
|
||||
//!class for unordered associative containers. When this option is specified,
|
||||
//!instead of using the default bucket traits, a user defined holder will be defined
|
||||
template<class BucketTraits>
|
||||
struct bucket_traits
|
||||
{
|
||||
/// @cond
|
||||
template<class Base>
|
||||
struct pack : Base
|
||||
{
|
||||
typedef BucketTraits bucket_traits;
|
||||
};
|
||||
/// @endcond
|
||||
};
|
||||
BOOST_INTRUSIVE_OPTION_TYPE(bucket_traits, BucketTraits, BucketTraits, bucket_traits)
|
||||
|
||||
//!This option setter specifies if the unordered hook
|
||||
//!should offer room to store the hash value.
|
||||
//!Storing the hash in the hook will speed up rehashing
|
||||
//!processes in applications where rehashing is frequent,
|
||||
//!rehashing might throw or the value is heavy to hash.
|
||||
template<bool Enabled>
|
||||
struct store_hash
|
||||
{
|
||||
/// @cond
|
||||
template<class Base>
|
||||
struct pack : Base
|
||||
{
|
||||
static const bool store_hash = Enabled;
|
||||
};
|
||||
/// @endcond
|
||||
};
|
||||
BOOST_INTRUSIVE_OPTION_CONSTANT(store_hash, bool, Enabled, store_hash)
|
||||
|
||||
//!This option setter specifies if the unordered hook
|
||||
//!should offer room to store another link to another node
|
||||
@ -524,51 +322,20 @@ struct store_hash
|
||||
//!Storing this link will speed up lookups and insertions on
|
||||
//!unordered_multiset containers with a great number of elements
|
||||
//!with the same key.
|
||||
template<bool Enabled>
|
||||
struct optimize_multikey
|
||||
{
|
||||
/// @cond
|
||||
template<class Base>
|
||||
struct pack : Base
|
||||
{
|
||||
static const bool optimize_multikey = Enabled;
|
||||
};
|
||||
/// @endcond
|
||||
};
|
||||
BOOST_INTRUSIVE_OPTION_CONSTANT(optimize_multikey, bool, Enabled, optimize_multikey)
|
||||
|
||||
//!This option setter specifies if the bucket array will be always power of two.
|
||||
//!This allows using masks instead of the default modulo operation to determine
|
||||
//!the bucket number from the hash value, leading to better performance.
|
||||
//!In debug mode, if power of two buckets mode is activated, the bucket length
|
||||
//!will be checked to through assertions to assure the bucket length is power of two.
|
||||
template<bool Enabled>
|
||||
struct power_2_buckets
|
||||
{
|
||||
/// @cond
|
||||
template<class Base>
|
||||
struct pack : Base
|
||||
{
|
||||
static const bool power_2_buckets = Enabled;
|
||||
};
|
||||
/// @endcond
|
||||
};
|
||||
BOOST_INTRUSIVE_OPTION_CONSTANT(power_2_buckets, bool, Enabled, power_2_buckets)
|
||||
|
||||
//!This option setter specifies if the container will cache a pointer to the first
|
||||
//!non-empty bucket so that begin() is always constant-time.
|
||||
//!This is specially helpful when we can have containers with a few elements
|
||||
//!but with big bucket arrays (that is, hashtables with low load factors).
|
||||
template<bool Enabled>
|
||||
struct cache_begin
|
||||
{
|
||||
/// @cond
|
||||
template<class Base>
|
||||
struct pack : Base
|
||||
{
|
||||
static const bool cache_begin = Enabled;
|
||||
};
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
BOOST_INTRUSIVE_OPTION_CONSTANT(cache_begin, bool, Enabled, cache_begin)
|
||||
|
||||
//!This option setter specifies if the container will compare the hash value
|
||||
//!before comparing objects. This option can't be specified if store_hash<>
|
||||
@ -576,17 +343,7 @@ struct cache_begin
|
||||
//!This is specially helpful when we have containers with a high load factor.
|
||||
//!and the comparison function is much more expensive that comparing already
|
||||
//!stored hash values.
|
||||
template<bool Enabled>
|
||||
struct compare_hash
|
||||
{
|
||||
/// @cond
|
||||
template<class Base>
|
||||
struct pack : Base
|
||||
{
|
||||
static const bool compare_hash = Enabled;
|
||||
};
|
||||
/// @endcond
|
||||
};
|
||||
BOOST_INTRUSIVE_OPTION_CONSTANT(compare_hash, bool, Enabled, compare_hash)
|
||||
|
||||
//!This option setter specifies if the hash container will use incremental
|
||||
//!hashing. With incremental hashing the cost of hash table expansion is spread
|
||||
@ -594,17 +351,7 @@ struct compare_hash
|
||||
//!Therefore linear hashing is well suited for interactive applications or real-time
|
||||
//!appplications where the worst-case insertion time of non-incremental hash containers
|
||||
//!(rehashing the whole bucket array) is not admisible.
|
||||
template<bool Enabled>
|
||||
struct incremental
|
||||
{
|
||||
/// @cond
|
||||
template<class Base>
|
||||
struct pack : Base
|
||||
{
|
||||
static const bool incremental = Enabled;
|
||||
};
|
||||
/// @endcond
|
||||
};
|
||||
BOOST_INTRUSIVE_OPTION_CONSTANT(incremental, bool, Enabled, incremental)
|
||||
|
||||
/// @cond
|
||||
|
||||
@ -615,210 +362,6 @@ struct none
|
||||
{};
|
||||
};
|
||||
|
||||
//To-do: pass to variadic templates
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
|
||||
template<class Prev, class Next>
|
||||
struct do_pack
|
||||
{
|
||||
//Use "pack" member template to pack options
|
||||
typedef typename Next::template pack<Prev> type;
|
||||
};
|
||||
|
||||
template<class Prev>
|
||||
struct do_pack<Prev, void>
|
||||
{
|
||||
//Avoid packing "void" to shorten template names
|
||||
typedef Prev type;
|
||||
};
|
||||
|
||||
template
|
||||
< class DefaultOptions
|
||||
, class O1 = void
|
||||
, class O2 = void
|
||||
, class O3 = void
|
||||
, class O4 = void
|
||||
, class O5 = void
|
||||
, class O6 = void
|
||||
, class O7 = void
|
||||
, class O8 = void
|
||||
, class O9 = void
|
||||
, class O10 = void
|
||||
, class O11 = void
|
||||
>
|
||||
struct pack_options
|
||||
{
|
||||
// join options
|
||||
typedef
|
||||
typename do_pack
|
||||
< typename do_pack
|
||||
< typename do_pack
|
||||
< typename do_pack
|
||||
< typename do_pack
|
||||
< typename do_pack
|
||||
< typename do_pack
|
||||
< typename do_pack
|
||||
< typename do_pack
|
||||
< typename do_pack
|
||||
< typename do_pack
|
||||
< DefaultOptions
|
||||
, O1
|
||||
>::type
|
||||
, O2
|
||||
>::type
|
||||
, O3
|
||||
>::type
|
||||
, O4
|
||||
>::type
|
||||
, O5
|
||||
>::type
|
||||
, O6
|
||||
>::type
|
||||
, O7
|
||||
>::type
|
||||
, O8
|
||||
>::type
|
||||
, O9
|
||||
>::type
|
||||
, O10
|
||||
>::type
|
||||
, O11
|
||||
>::type
|
||||
type;
|
||||
};
|
||||
#else
|
||||
|
||||
//index_tuple
|
||||
template<int... Indexes>
|
||||
struct index_tuple{};
|
||||
|
||||
//build_number_seq
|
||||
template<std::size_t Num, typename Tuple = index_tuple<> >
|
||||
struct build_number_seq;
|
||||
|
||||
template<std::size_t Num, int... Indexes>
|
||||
struct build_number_seq<Num, index_tuple<Indexes...> >
|
||||
: build_number_seq<Num - 1, index_tuple<Indexes..., sizeof...(Indexes)> >
|
||||
{};
|
||||
|
||||
template<int... Indexes>
|
||||
struct build_number_seq<0, index_tuple<Indexes...> >
|
||||
{ typedef index_tuple<Indexes...> type; };
|
||||
|
||||
template<class ...Types>
|
||||
struct typelist
|
||||
{};
|
||||
|
||||
//invert_typelist
|
||||
template<class T>
|
||||
struct invert_typelist;
|
||||
|
||||
template<int I, typename Tuple>
|
||||
struct typelist_element;
|
||||
|
||||
template<int I, typename Head, typename... Tail>
|
||||
struct typelist_element<I, typelist<Head, Tail...> >
|
||||
{
|
||||
typedef typename typelist_element<I-1, typelist<Tail...> >::type type;
|
||||
};
|
||||
|
||||
template<typename Head, typename... Tail>
|
||||
struct typelist_element<0, typelist<Head, Tail...> >
|
||||
{
|
||||
typedef Head type;
|
||||
};
|
||||
|
||||
template<int ...Ints, class ...Types>
|
||||
typelist<typename typelist_element<(sizeof...(Types) - 1) - Ints, typelist<Types...> >::type...>
|
||||
inverted_typelist(index_tuple<Ints...>, typelist<Types...>)
|
||||
{
|
||||
return typelist<typename typelist_element<(sizeof...(Types) - 1) - Ints, typelist<Types...> >::type...>();
|
||||
}
|
||||
|
||||
//sizeof_typelist
|
||||
template<class Typelist>
|
||||
struct sizeof_typelist;
|
||||
|
||||
template<class ...Types>
|
||||
struct sizeof_typelist< typelist<Types...> >
|
||||
{
|
||||
static const std::size_t value = sizeof...(Types);
|
||||
};
|
||||
|
||||
//invert_typelist_impl
|
||||
template<class Typelist, class Indexes>
|
||||
struct invert_typelist_impl;
|
||||
|
||||
|
||||
template<class Typelist, int ...Ints>
|
||||
struct invert_typelist_impl< Typelist, index_tuple<Ints...> >
|
||||
{
|
||||
static const std::size_t last_idx = sizeof_typelist<Typelist>::value - 1;
|
||||
typedef typelist
|
||||
<typename typelist_element<last_idx - Ints, Typelist>::type...> type;
|
||||
};
|
||||
|
||||
template<class Typelist, int Int>
|
||||
struct invert_typelist_impl< Typelist, index_tuple<Int> >
|
||||
{
|
||||
typedef Typelist type;
|
||||
};
|
||||
|
||||
template<class Typelist>
|
||||
struct invert_typelist_impl< Typelist, index_tuple<> >
|
||||
{
|
||||
typedef Typelist type;
|
||||
};
|
||||
|
||||
//invert_typelist
|
||||
template<class Typelist>
|
||||
struct invert_typelist;
|
||||
|
||||
template<class ...Types>
|
||||
struct invert_typelist< typelist<Types...> >
|
||||
{
|
||||
typedef typelist<Types...> typelist_t;
|
||||
typedef typename build_number_seq<sizeof...(Types)>::type indexes_t;
|
||||
typedef typename invert_typelist_impl<typelist_t, indexes_t>::type type;
|
||||
};
|
||||
|
||||
//Do pack
|
||||
template<class Typelist>
|
||||
struct do_pack;
|
||||
|
||||
template<>
|
||||
struct do_pack<typelist<> >;
|
||||
|
||||
template<class Prev>
|
||||
struct do_pack<typelist<Prev> >
|
||||
{
|
||||
typedef Prev type;
|
||||
};
|
||||
|
||||
template<class Prev, class Last>
|
||||
struct do_pack<typelist<Prev, Last> >
|
||||
{
|
||||
typedef typename Prev::template pack<Last> type;
|
||||
};
|
||||
|
||||
template<class Prev, class ...Others>
|
||||
struct do_pack<typelist<Prev, Others...> >
|
||||
{
|
||||
typedef typename Prev::template pack
|
||||
<typename do_pack<typelist<Others...> >::type> type;
|
||||
};
|
||||
|
||||
|
||||
template<class ...Options>
|
||||
struct pack_options
|
||||
{
|
||||
typedef typelist<Options...> typelist_t;
|
||||
typedef typename invert_typelist<typelist_t>::type inverted_typelist;
|
||||
typedef typename do_pack<inverted_typelist>::type type;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
struct hook_defaults
|
||||
{
|
||||
typedef void* void_pointer;
|
||||
|
@ -13,6 +13,8 @@
|
||||
#define BOOST_INTRUSIVE_GET_PARENT_FROM_MEMBER_HPP
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
|
||||
#include <boost/intrusive/detail/parent_from_member.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
@ -13,6 +13,8 @@
|
||||
#ifndef BOOST_INTRUSIVE_POINTER_PLUS_BITS_HPP
|
||||
#define BOOST_INTRUSIVE_POINTER_PLUS_BITS_HPP
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
#include <boost/intrusive/detail/mpl.hpp> //ls_zeros
|
||||
#include <boost/intrusive/detail/assert.hpp> //BOOST_INTRUSIVE_INVARIANT_ASSERT
|
||||
|
||||
@ -83,4 +85,6 @@ struct pointer_plus_bits<T*, NumBits>
|
||||
} //namespace intrusive
|
||||
} //namespace boost
|
||||
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTRUSIVE_POINTER_PLUS_BITS_HPP
|
||||
|
@ -17,11 +17,12 @@
|
||||
#ifndef BOOST_INTRUSIVE_POINTER_TRAITS_HPP
|
||||
#define BOOST_INTRUSIVE_POINTER_TRAITS_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
#if defined(_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
#include <boost/intrusive/detail/workaround.hpp>
|
||||
#include <boost/intrusive/detail/memory_util.hpp>
|
||||
#include <boost/type_traits/integral_constant.hpp>
|
||||
|
@ -23,8 +23,12 @@ namespace intrusive {
|
||||
|
||||
template <class T>
|
||||
struct priority_compare
|
||||
: public std::binary_function<T, T, bool>
|
||||
{
|
||||
//Compatibility with std::binary_function
|
||||
typedef T first_argument_type;
|
||||
typedef T second_argument_type;
|
||||
typedef bool result_type;
|
||||
|
||||
bool operator()(const T &val, const T &val2) const
|
||||
{
|
||||
return priority_order(val, val2);
|
||||
|
@ -13,13 +13,13 @@
|
||||
#define BOOST_INTRUSIVE_RBTREE_HPP
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
|
||||
#include <boost/intrusive/detail/assert.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
#include <boost/intrusive/set_hook.hpp>
|
||||
#include <boost/intrusive/detail/rbtree_node.hpp>
|
||||
#include <boost/intrusive/bstree.hpp>
|
||||
@ -292,7 +292,7 @@ class rbtree_impl
|
||||
//! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
size_type count(const KeyType& key, KeyValueCompare comp) const;
|
||||
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference)
|
||||
iterator lower_bound(const_reference value);
|
||||
|
||||
@ -483,14 +483,13 @@ class rbtree
|
||||
public:
|
||||
typedef typename Base::value_compare value_compare;
|
||||
typedef typename Base::value_traits value_traits;
|
||||
typedef typename Base::real_value_traits real_value_traits;
|
||||
typedef typename Base::iterator iterator;
|
||||
typedef typename Base::const_iterator const_iterator;
|
||||
typedef typename Base::reverse_iterator reverse_iterator;
|
||||
typedef typename Base::const_reverse_iterator const_reverse_iterator;
|
||||
|
||||
//Assert if passed value traits are compatible with the type
|
||||
BOOST_STATIC_ASSERT((detail::is_same<typename real_value_traits::value_type, T>::value));
|
||||
BOOST_STATIC_ASSERT((detail::is_same<typename value_traits::value_type, T>::value));
|
||||
|
||||
explicit rbtree( const value_compare &cmp = value_compare()
|
||||
, const value_traits &v_traits = value_traits())
|
||||
|
@ -10,31 +10,6 @@
|
||||
// See http://www.boost.org/libs/intrusive for documentation.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// The internal implementation of red-black trees is based on that of SGI STL
|
||||
// stl_tree.h file:
|
||||
//
|
||||
// Copyright (c) 1996,1997
|
||||
// Silicon Graphics Computer Systems, Inc.
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. Silicon Graphics makes no
|
||||
// representations about the suitability of this software for any
|
||||
// purpose. It is provided "as is" without express or implied warranty.
|
||||
//
|
||||
//
|
||||
// Copyright (c) 1994
|
||||
// Hewlett-Packard Company
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. Hewlett-Packard Company makes no
|
||||
// representations about the suitability of this software for any
|
||||
// purpose. It is provided "as is" without express or implied warranty.
|
||||
//
|
||||
// The tree destruction algorithm is based on Julienne Walker and The EC Team code:
|
||||
//
|
||||
@ -49,9 +24,9 @@
|
||||
#define BOOST_INTRUSIVE_RBTREE_ALGORITHMS_HPP
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
|
||||
#include <boost/intrusive/detail/assert.hpp>
|
||||
#include <boost/intrusive/detail/utilities.hpp>
|
||||
@ -82,21 +57,6 @@ struct rbtree_node_cloner
|
||||
}
|
||||
};
|
||||
|
||||
template<class NodeTraits>
|
||||
struct rbtree_erase_fixup
|
||||
{
|
||||
typedef typename NodeTraits::node_ptr node_ptr;
|
||||
typedef typename NodeTraits::color color;
|
||||
|
||||
void operator()(const node_ptr & to_erase, const node_ptr & successor)
|
||||
{
|
||||
//Swap color of y and z
|
||||
color tmp(NodeTraits::get_color(successor));
|
||||
NodeTraits::set_color(successor, NodeTraits::get_color(to_erase));
|
||||
NodeTraits::set_color(to_erase, tmp);
|
||||
}
|
||||
};
|
||||
|
||||
#endif //#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
|
||||
//! rbtree_algorithms provides basic algorithms to manipulate
|
||||
@ -270,10 +230,18 @@ class rbtree_algorithms
|
||||
static node_ptr erase(const node_ptr & header, const node_ptr & z)
|
||||
{
|
||||
typename bstree_algo::data_for_rebalance info;
|
||||
bstree_algo::erase(header, z, rbtree_erase_fixup<NodeTraits>(), info);
|
||||
bstree_algo::erase(header, z, info);
|
||||
|
||||
//Rebalance rbtree
|
||||
if(NodeTraits::get_color(z) != NodeTraits::red()){
|
||||
color new_z_color;
|
||||
if(info.y != z){
|
||||
new_z_color = NodeTraits::get_color(info.y);
|
||||
NodeTraits::set_color(info.y, NodeTraits::get_color(z));
|
||||
}
|
||||
else{
|
||||
new_z_color = NodeTraits::get_color(z);
|
||||
}
|
||||
//Rebalance rbtree if needed
|
||||
if(new_z_color != NodeTraits::red()){
|
||||
rebalance_after_erasure(header, info.x, info.x_parent);
|
||||
}
|
||||
return z;
|
||||
@ -322,6 +290,7 @@ class rbtree_algorithms
|
||||
//! @copydoc ::boost::intrusive::bstree_algorithms::count(const const_node_ptr&,const KeyType&,KeyNodePtrCompare)
|
||||
template<class KeyType, class KeyNodePtrCompare>
|
||||
static std::size_t count(const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp);
|
||||
|
||||
#endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal_upper_bound(const node_ptr&,const node_ptr&,NodePtrCompare)
|
||||
@ -411,64 +380,76 @@ class rbtree_algorithms
|
||||
|
||||
static void rebalance_after_erasure(const node_ptr & header, node_ptr x, node_ptr x_parent)
|
||||
{
|
||||
while(x != NodeTraits::get_parent(header) && (!x || NodeTraits::get_color(x) == NodeTraits::black())){
|
||||
if(x == NodeTraits::get_left(x_parent)){
|
||||
while(1){
|
||||
if(x_parent == header || (x && NodeTraits::get_color(x) != NodeTraits::black())){
|
||||
break;
|
||||
}
|
||||
//Don't cache x_is_leftchild or similar because x can be null and
|
||||
//equal to both x_parent_left and x_parent_right
|
||||
const node_ptr x_parent_left(NodeTraits::get_left(x_parent));
|
||||
if(x == x_parent_left){ //x is left child
|
||||
node_ptr w = NodeTraits::get_right(x_parent);
|
||||
BOOST_ASSERT(w);
|
||||
if(NodeTraits::get_color(w) == NodeTraits::red()){
|
||||
NodeTraits::set_color(w, NodeTraits::black());
|
||||
NodeTraits::set_color(x_parent, NodeTraits::red());
|
||||
bstree_algo::rotate_left(x_parent, header);
|
||||
bstree_algo::rotate_left(x_parent, w, NodeTraits::get_parent(x_parent), header);
|
||||
w = NodeTraits::get_right(x_parent);
|
||||
}
|
||||
if((!NodeTraits::get_left(w) || NodeTraits::get_color(NodeTraits::get_left(w)) == NodeTraits::black()) &&
|
||||
(!NodeTraits::get_right(w) || NodeTraits::get_color(NodeTraits::get_right(w)) == NodeTraits::black())){
|
||||
node_ptr const w_left (NodeTraits::get_left(w));
|
||||
node_ptr const w_right(NodeTraits::get_right(w));
|
||||
if((!w_left || NodeTraits::get_color(w_left) == NodeTraits::black()) &&
|
||||
(!w_right || NodeTraits::get_color(w_right) == NodeTraits::black())){
|
||||
NodeTraits::set_color(w, NodeTraits::red());
|
||||
x = x_parent;
|
||||
x_parent = NodeTraits::get_parent(x_parent);
|
||||
}
|
||||
else {
|
||||
if(!NodeTraits::get_right(w) || NodeTraits::get_color(NodeTraits::get_right(w)) == NodeTraits::black()){
|
||||
NodeTraits::set_color(NodeTraits::get_left(w), NodeTraits::black());
|
||||
if(!w_right || NodeTraits::get_color(w_right) == NodeTraits::black()){
|
||||
NodeTraits::set_color(w_left, NodeTraits::black());
|
||||
NodeTraits::set_color(w, NodeTraits::red());
|
||||
bstree_algo::rotate_right(w, header);
|
||||
bstree_algo::rotate_right(w, w_left, NodeTraits::get_parent(w), header);
|
||||
w = NodeTraits::get_right(x_parent);
|
||||
}
|
||||
NodeTraits::set_color(w, NodeTraits::get_color(x_parent));
|
||||
NodeTraits::set_color(x_parent, NodeTraits::black());
|
||||
if(NodeTraits::get_right(w))
|
||||
NodeTraits::set_color(NodeTraits::get_right(w), NodeTraits::black());
|
||||
bstree_algo::rotate_left(x_parent, header);
|
||||
const node_ptr new_wright(NodeTraits::get_right(w));
|
||||
if(new_wright)
|
||||
NodeTraits::set_color(new_wright, NodeTraits::black());
|
||||
bstree_algo::rotate_left(x_parent, NodeTraits::get_right(x_parent), NodeTraits::get_parent(x_parent), header);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// same as above, with right_ <-> left_.
|
||||
node_ptr w = NodeTraits::get_left(x_parent);
|
||||
node_ptr w = x_parent_left;
|
||||
if(NodeTraits::get_color(w) == NodeTraits::red()){
|
||||
NodeTraits::set_color(w, NodeTraits::black());
|
||||
NodeTraits::set_color(x_parent, NodeTraits::red());
|
||||
bstree_algo::rotate_right(x_parent, header);
|
||||
bstree_algo::rotate_right(x_parent, w, NodeTraits::get_parent(x_parent), header);
|
||||
w = NodeTraits::get_left(x_parent);
|
||||
}
|
||||
if((!NodeTraits::get_right(w) || NodeTraits::get_color(NodeTraits::get_right(w)) == NodeTraits::black()) &&
|
||||
(!NodeTraits::get_left(w) || NodeTraits::get_color(NodeTraits::get_left(w)) == NodeTraits::black())){
|
||||
node_ptr const w_left (NodeTraits::get_left(w));
|
||||
node_ptr const w_right(NodeTraits::get_right(w));
|
||||
if((!w_right || NodeTraits::get_color(w_right) == NodeTraits::black()) &&
|
||||
(!w_left || NodeTraits::get_color(w_left) == NodeTraits::black())){
|
||||
NodeTraits::set_color(w, NodeTraits::red());
|
||||
x = x_parent;
|
||||
x_parent = NodeTraits::get_parent(x_parent);
|
||||
}
|
||||
else {
|
||||
if(!NodeTraits::get_left(w) || NodeTraits::get_color(NodeTraits::get_left(w)) == NodeTraits::black()){
|
||||
NodeTraits::set_color(NodeTraits::get_right(w), NodeTraits::black());
|
||||
if(!w_left || NodeTraits::get_color(w_left) == NodeTraits::black()){
|
||||
NodeTraits::set_color(w_right, NodeTraits::black());
|
||||
NodeTraits::set_color(w, NodeTraits::red());
|
||||
bstree_algo::rotate_left(w, header);
|
||||
bstree_algo::rotate_left(w, w_right, NodeTraits::get_parent(w), header);
|
||||
w = NodeTraits::get_left(x_parent);
|
||||
}
|
||||
NodeTraits::set_color(w, NodeTraits::get_color(x_parent));
|
||||
NodeTraits::set_color(x_parent, NodeTraits::black());
|
||||
if(NodeTraits::get_left(w))
|
||||
NodeTraits::set_color(NodeTraits::get_left(w), NodeTraits::black());
|
||||
bstree_algo::rotate_right(x_parent, header);
|
||||
const node_ptr new_wleft(NodeTraits::get_left(w));
|
||||
if(new_wleft)
|
||||
NodeTraits::set_color(new_wleft, NodeTraits::black());
|
||||
bstree_algo::rotate_right(x_parent, NodeTraits::get_left(x_parent), NodeTraits::get_parent(x_parent), header);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -480,48 +461,49 @@ class rbtree_algorithms
|
||||
static void rebalance_after_insertion(const node_ptr & header, node_ptr p)
|
||||
{
|
||||
NodeTraits::set_color(p, NodeTraits::red());
|
||||
while(p != NodeTraits::get_parent(header) && NodeTraits::get_color(NodeTraits::get_parent(p)) == NodeTraits::red()){
|
||||
while(1){
|
||||
node_ptr p_parent(NodeTraits::get_parent(p));
|
||||
node_ptr p_parent_parent(NodeTraits::get_parent(p_parent));
|
||||
if(bstree_algo::is_left_child(p_parent)){
|
||||
node_ptr x = NodeTraits::get_right(p_parent_parent);
|
||||
if(x && NodeTraits::get_color(x) == NodeTraits::red()){
|
||||
NodeTraits::set_color(p_parent, NodeTraits::black());
|
||||
NodeTraits::set_color(p_parent_parent, NodeTraits::red());
|
||||
NodeTraits::set_color(x, NodeTraits::black());
|
||||
p = p_parent_parent;
|
||||
}
|
||||
else {
|
||||
if(!bstree_algo::is_left_child(p)){
|
||||
p = p_parent;
|
||||
bstree_algo::rotate_left(p, header);
|
||||
}
|
||||
node_ptr new_p_parent(NodeTraits::get_parent(p));
|
||||
node_ptr new_p_parent_parent(NodeTraits::get_parent(new_p_parent));
|
||||
NodeTraits::set_color(new_p_parent, NodeTraits::black());
|
||||
NodeTraits::set_color(new_p_parent_parent, NodeTraits::red());
|
||||
bstree_algo::rotate_right(new_p_parent_parent, header);
|
||||
}
|
||||
const node_ptr p_grandparent(NodeTraits::get_parent(p_parent));
|
||||
if(p_parent == header || NodeTraits::get_color(p_parent) == NodeTraits::black() || p_grandparent == header){
|
||||
break;
|
||||
}
|
||||
else{
|
||||
node_ptr x = NodeTraits::get_left(p_parent_parent);
|
||||
if(x && NodeTraits::get_color(x) == NodeTraits::red()){
|
||||
NodeTraits::set_color(p_parent, NodeTraits::black());
|
||||
NodeTraits::set_color(p_parent_parent, NodeTraits::red());
|
||||
NodeTraits::set_color(x, NodeTraits::black());
|
||||
p = p_parent_parent;
|
||||
}
|
||||
else{
|
||||
if(bstree_algo::is_left_child(p)){
|
||||
p = p_parent;
|
||||
bstree_algo::rotate_right(p, header);
|
||||
|
||||
NodeTraits::set_color(p_grandparent, NodeTraits::red());
|
||||
node_ptr const p_grandparent_left (NodeTraits::get_left (p_grandparent));
|
||||
bool const p_parent_is_left_child = p_parent == p_grandparent_left;
|
||||
node_ptr const x(p_parent_is_left_child ? NodeTraits::get_right(p_grandparent) : p_grandparent_left);
|
||||
|
||||
if(x && NodeTraits::get_color(x) == NodeTraits::red()){
|
||||
NodeTraits::set_color(x, NodeTraits::black());
|
||||
NodeTraits::set_color(p_parent, NodeTraits::black());
|
||||
p = p_grandparent;
|
||||
}
|
||||
else{ //Final step
|
||||
const bool p_is_left_child(NodeTraits::get_left(p_parent) == p);
|
||||
if(p_parent_is_left_child){ //p_parent is left child
|
||||
if(!p_is_left_child){ //p is right child
|
||||
bstree_algo::rotate_left_no_parent_fix(p_parent, p);
|
||||
//No need to link p and p_grandparent:
|
||||
// [NodeTraits::set_parent(p, p_grandparent) + NodeTraits::set_left(p_grandparent, p)]
|
||||
//as p_grandparent is not the header, another rotation is coming and p_parent
|
||||
//will be the left child of p_grandparent
|
||||
p_parent = p;
|
||||
}
|
||||
node_ptr new_p_parent(NodeTraits::get_parent(p));
|
||||
node_ptr new_p_parent_parent(NodeTraits::get_parent(new_p_parent));
|
||||
NodeTraits::set_color(new_p_parent, NodeTraits::black());
|
||||
NodeTraits::set_color(new_p_parent_parent, NodeTraits::red());
|
||||
bstree_algo::rotate_left(new_p_parent_parent, header);
|
||||
bstree_algo::rotate_right(p_grandparent, p_parent, NodeTraits::get_parent(p_grandparent), header);
|
||||
}
|
||||
else{ //p_parent is right child
|
||||
if(p_is_left_child){ //p is left child
|
||||
bstree_algo::rotate_right_no_parent_fix(p_parent, p);
|
||||
//No need to link p and p_grandparent:
|
||||
// [NodeTraits::set_parent(p, p_grandparent) + NodeTraits::set_right(p_grandparent, p)]
|
||||
//as p_grandparent is not the header, another rotation is coming and p_parent
|
||||
//will be the right child of p_grandparent
|
||||
p_parent = p;
|
||||
}
|
||||
bstree_algo::rotate_left(p_grandparent, p_parent, NodeTraits::get_parent(p_grandparent), header);
|
||||
}
|
||||
NodeTraits::set_color(p_parent, NodeTraits::black());
|
||||
break;
|
||||
}
|
||||
}
|
||||
NodeTraits::set_color(NodeTraits::get_parent(header), NodeTraits::black());
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
|
||||
#include <boost/intrusive/detail/mpl.hpp>
|
||||
#include <boost/intrusive/rbtree.hpp>
|
||||
#include <iterator>
|
||||
@ -248,13 +249,19 @@ class set_impl
|
||||
template<class Disposer>
|
||||
void clear_and_dispose(Disposer disposer);
|
||||
|
||||
#endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
|
||||
//! @copydoc ::boost::intrusive::rbtree::count(const_reference)const
|
||||
size_type count(const_reference value) const;
|
||||
size_type count(const_reference value) const
|
||||
{ return static_cast<size_type>(this->tree_type::find(value) != this->tree_type::cend()); }
|
||||
|
||||
//! @copydoc ::boost::intrusive::rbtree::count(const KeyType&,KeyValueCompare)const
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
size_type count(const KeyType& key, KeyValueCompare comp) const;
|
||||
|
||||
size_type count(const KeyType& key, KeyValueCompare comp) const
|
||||
{ return static_cast<size_type>(this->tree_type::find(key, comp) != this->tree_type::cend()); }
|
||||
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
|
||||
//! @copydoc ::boost::intrusive::rbtree::lower_bound(const_reference)
|
||||
iterator lower_bound(const_reference value);
|
||||
|
||||
@ -297,21 +304,29 @@ class set_impl
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
const_iterator find(const KeyType& key, KeyValueCompare comp) const;
|
||||
|
||||
#endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
|
||||
//! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference)
|
||||
std::pair<iterator,iterator> equal_range(const_reference value);
|
||||
std::pair<iterator,iterator> equal_range(const_reference value)
|
||||
{ return this->tree_type::lower_bound_range(value); }
|
||||
|
||||
//! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare)
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
std::pair<iterator,iterator> equal_range(const KeyType& key, KeyValueCompare comp);
|
||||
std::pair<iterator,iterator> equal_range(const KeyType& key, KeyValueCompare comp)
|
||||
{ return this->tree_type::lower_bound_range(key, comp); }
|
||||
|
||||
//! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference)const
|
||||
std::pair<const_iterator, const_iterator>
|
||||
equal_range(const_reference value) const;
|
||||
equal_range(const_reference value) const
|
||||
{ return this->tree_type::lower_bound_range(value); }
|
||||
|
||||
//! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare)const
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
std::pair<const_iterator, const_iterator>
|
||||
equal_range(const KeyType& key, KeyValueCompare comp) const;
|
||||
equal_range(const KeyType& key, KeyValueCompare comp) const
|
||||
{ return this->tree_type::lower_bound_range(key, comp); }
|
||||
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
|
||||
//! @copydoc ::boost::intrusive::rbtree::bounded_range(const_reference,const_reference,bool,bool)
|
||||
std::pair<iterator,iterator> bounded_range
|
||||
@ -691,7 +706,7 @@ class multiset_impl
|
||||
//! @copydoc ::boost::intrusive::rbtree::count(const KeyType&,KeyValueCompare)const
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
size_type count(const KeyType& key, KeyValueCompare comp) const;
|
||||
|
||||
|
||||
//! @copydoc ::boost::intrusive::rbtree::lower_bound(const_reference)
|
||||
iterator lower_bound(const_reference value);
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
|
||||
#include <boost/intrusive/detail/utilities.hpp>
|
||||
#include <boost/intrusive/detail/rbtree_node.hpp>
|
||||
#include <boost/intrusive/rbtree_algorithms.hpp>
|
||||
@ -76,7 +77,7 @@ struct make_set_base_hook
|
||||
//! unique tag.
|
||||
//!
|
||||
//! \c void_pointer<> is the pointer type that will be used internally in the hook
|
||||
//! and the the container configured to use this hook.
|
||||
//! and the container configured to use this hook.
|
||||
//!
|
||||
//! \c link_mode<> will specify the linking mode of the hook (\c normal_link,
|
||||
//! \c auto_unlink or \c safe_link).
|
||||
@ -203,7 +204,7 @@ struct make_set_member_hook
|
||||
//! \c link_mode<> and \c optimize_size<>.
|
||||
//!
|
||||
//! \c void_pointer<> is the pointer type that will be used internally in the hook
|
||||
//! and the the container configured to use this hook.
|
||||
//! and the container configured to use this hook.
|
||||
//!
|
||||
//! \c link_mode<> will specify the linking mode of the hook (\c normal_link,
|
||||
//! \c auto_unlink or \c safe_link).
|
||||
|
@ -247,13 +247,19 @@ class sg_set_impl
|
||||
template<class Disposer>
|
||||
void clear_and_dispose(Disposer disposer);
|
||||
|
||||
#endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
|
||||
//! @copydoc ::boost::intrusive::sgtree::count(const_reference)const
|
||||
size_type count(const_reference value) const;
|
||||
size_type count(const_reference value) const
|
||||
{ return static_cast<size_type>(this->tree_type::find(value) != this->tree_type::cend()); }
|
||||
|
||||
//! @copydoc ::boost::intrusive::sgtree::count(const KeyType&,KeyValueCompare)const
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
size_type count(const KeyType& key, KeyValueCompare comp) const;
|
||||
|
||||
size_type count(const KeyType& key, KeyValueCompare comp) const
|
||||
{ return static_cast<size_type>(this->tree_type::find(key, comp) != this->tree_type::cend()); }
|
||||
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
|
||||
//! @copydoc ::boost::intrusive::sgtree::lower_bound(const_reference)
|
||||
iterator lower_bound(const_reference value);
|
||||
|
||||
@ -296,21 +302,29 @@ class sg_set_impl
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
const_iterator find(const KeyType& key, KeyValueCompare comp) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::sgtree::equal_range(const_reference)
|
||||
std::pair<iterator,iterator> equal_range(const_reference value);
|
||||
#endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
|
||||
//! @copydoc ::boost::intrusive::sgtree::equal_range(const KeyType&,KeyValueCompare)
|
||||
//! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference)
|
||||
std::pair<iterator,iterator> equal_range(const_reference value)
|
||||
{ return this->tree_type::lower_bound_range(value); }
|
||||
|
||||
//! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare)
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
std::pair<iterator,iterator> equal_range(const KeyType& key, KeyValueCompare comp);
|
||||
std::pair<iterator,iterator> equal_range(const KeyType& key, KeyValueCompare comp)
|
||||
{ return this->tree_type::lower_bound_range(key, comp); }
|
||||
|
||||
//! @copydoc ::boost::intrusive::sgtree::equal_range(const_reference)const
|
||||
//! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference)const
|
||||
std::pair<const_iterator, const_iterator>
|
||||
equal_range(const_reference value) const;
|
||||
equal_range(const_reference value) const
|
||||
{ return this->tree_type::lower_bound_range(value); }
|
||||
|
||||
//! @copydoc ::boost::intrusive::sgtree::equal_range(const KeyType&,KeyValueCompare)const
|
||||
//! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare)const
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
std::pair<const_iterator, const_iterator>
|
||||
equal_range(const KeyType& key, KeyValueCompare comp) const;
|
||||
equal_range(const KeyType& key, KeyValueCompare comp) const
|
||||
{ return this->tree_type::lower_bound_range(key, comp); }
|
||||
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
|
||||
//! @copydoc ::boost::intrusive::sgtree::bounded_range(const_reference,const_reference,bool,bool)
|
||||
std::pair<iterator,iterator> bounded_range
|
||||
|
@ -19,6 +19,7 @@
|
||||
#define BOOST_INTRUSIVE_SGTREE_HPP
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
@ -28,7 +29,6 @@
|
||||
#include <cstddef>
|
||||
#include <boost/intrusive/detail/assert.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
#include <boost/intrusive/bs_set_hook.hpp>
|
||||
#include <boost/intrusive/bstree.hpp>
|
||||
#include <boost/intrusive/detail/tree_node.hpp>
|
||||
@ -48,6 +48,12 @@ namespace intrusive {
|
||||
|
||||
namespace detail{
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Halpha for fixed floating_point<false> option
|
||||
//
|
||||
/////////////////////////////////////////////////////////////
|
||||
|
||||
//! Returns floor(log2(n)/log2(sqrt(2))) -> floor(2*log2(n))
|
||||
//! Undefined if N is 0.
|
||||
//!
|
||||
@ -55,7 +61,7 @@ namespace detail{
|
||||
inline std::size_t calculate_h_sqrt2 (std::size_t n)
|
||||
{
|
||||
std::size_t f_log2 = detail::floor_log2(n);
|
||||
return (2*f_log2) + (n >= detail::sqrt2_pow_2xplus1 (f_log2));
|
||||
return (2*f_log2) + static_cast<std::size_t>(n >= detail::sqrt2_pow_2xplus1(f_log2));
|
||||
}
|
||||
|
||||
struct h_alpha_sqrt2_t
|
||||
@ -76,6 +82,12 @@ struct alpha_0_75_by_max_size_t
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Halpha for fixed floating_point<true> option
|
||||
//
|
||||
/////////////////////////////////////////////////////////////
|
||||
|
||||
struct h_alpha_t
|
||||
{
|
||||
explicit h_alpha_t(float inv_minus_logalpha)
|
||||
@ -84,9 +96,12 @@ struct h_alpha_t
|
||||
|
||||
std::size_t operator()(std::size_t n) const
|
||||
{
|
||||
//Returns floor(log2(1/alpha(n))) ->
|
||||
// floor(log2(n)/log(1/alpha)) ->
|
||||
// floor(log2(n)/(-log2(alpha)))
|
||||
////////////////////////////////////////////////////////////
|
||||
// This function must return "floor(log2(1/alpha(n)))" ->
|
||||
// floor(log2(n)/log(1/alpha)) ->
|
||||
// floor(log2(n)/-log2(alpha))
|
||||
// floor(log2(n)*(1/-log2(alpha)))
|
||||
////////////////////////////////////////////////////////////
|
||||
//return static_cast<std::size_t>(std::log(float(n))*inv_minus_logalpha_);
|
||||
return static_cast<std::size_t>(detail::fast_log2(float(n))*inv_minus_logalpha_);
|
||||
}
|
||||
@ -119,7 +134,7 @@ struct alpha_holder
|
||||
typedef boost::intrusive::detail::alpha_by_max_size_t multiply_by_alpha_t;
|
||||
|
||||
alpha_holder() : max_tree_size_(0)
|
||||
{ set_alpha(0.7f); }
|
||||
{ set_alpha(0.70711f); } // ~1/sqrt(2)
|
||||
|
||||
float get_alpha() const
|
||||
{ return alpha_; }
|
||||
@ -211,7 +226,6 @@ class sgtree_impl
|
||||
typedef bstree_impl< ValueTraits, VoidOrKeyComp, SizeType
|
||||
, true, SgTreeAlgorithms> tree_type;
|
||||
typedef tree_type implementation_defined;
|
||||
typedef typename tree_type::real_value_traits real_value_traits;
|
||||
|
||||
/// @endcond
|
||||
|
||||
@ -248,11 +262,11 @@ class sgtree_impl
|
||||
typedef typename alpha_traits::multiply_by_alpha_t multiply_by_alpha_t;
|
||||
|
||||
BOOST_MOVABLE_BUT_NOT_COPYABLE(sgtree_impl)
|
||||
BOOST_STATIC_ASSERT(((int)real_value_traits::link_mode != (int)auto_unlink));
|
||||
BOOST_STATIC_ASSERT(((int)value_traits::link_mode != (int)auto_unlink));
|
||||
|
||||
enum { safemode_or_autounlink =
|
||||
(int)real_value_traits::link_mode == (int)auto_unlink ||
|
||||
(int)real_value_traits::link_mode == (int)safe_link };
|
||||
(int)value_traits::link_mode == (int)auto_unlink ||
|
||||
(int)value_traits::link_mode == (int)safe_link };
|
||||
|
||||
/// @endcond
|
||||
|
||||
@ -397,9 +411,9 @@ class sgtree_impl
|
||||
//! @copydoc ::boost::intrusive::bstree::insert_equal(reference)
|
||||
iterator insert_equal(reference value)
|
||||
{
|
||||
detail::key_nodeptr_comp<value_compare, real_value_traits>
|
||||
key_node_comp(this->value_comp(), &this->get_real_value_traits());
|
||||
node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value));
|
||||
detail::key_nodeptr_comp<value_compare, value_traits>
|
||||
key_node_comp(this->value_comp(), &this->get_value_traits());
|
||||
node_ptr to_insert(this->get_value_traits().to_node_ptr(value));
|
||||
if(safemode_or_autounlink)
|
||||
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert));
|
||||
std::size_t max_tree_size = (std::size_t)this->max_tree_size_;
|
||||
@ -408,15 +422,15 @@ class sgtree_impl
|
||||
, (size_type)this->size(), this->get_h_alpha_func(), max_tree_size);
|
||||
this->tree_type::sz_traits().increment();
|
||||
this->max_tree_size_ = (size_type)max_tree_size;
|
||||
return iterator(p, this->real_value_traits_ptr());
|
||||
return iterator(p, this->value_traits_ptr());
|
||||
}
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::insert_equal(const_iterator,reference)
|
||||
iterator insert_equal(const_iterator hint, reference value)
|
||||
{
|
||||
detail::key_nodeptr_comp<value_compare, real_value_traits>
|
||||
key_node_comp(this->value_comp(), &this->get_real_value_traits());
|
||||
node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value));
|
||||
detail::key_nodeptr_comp<value_compare, value_traits>
|
||||
key_node_comp(this->value_comp(), &this->get_value_traits());
|
||||
node_ptr to_insert(this->get_value_traits().to_node_ptr(value));
|
||||
if(safemode_or_autounlink)
|
||||
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert));
|
||||
std::size_t max_tree_size = (std::size_t)this->max_tree_size_;
|
||||
@ -425,7 +439,7 @@ class sgtree_impl
|
||||
, (std::size_t)this->size(), this->get_h_alpha_func(), max_tree_size);
|
||||
this->tree_type::sz_traits().increment();
|
||||
this->max_tree_size_ = (size_type)max_tree_size;
|
||||
return iterator(p, this->real_value_traits_ptr());
|
||||
return iterator(p, this->value_traits_ptr());
|
||||
}
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::insert_equal(Iterator,Iterator)
|
||||
@ -462,12 +476,12 @@ class sgtree_impl
|
||||
std::pair<iterator, bool> insert_unique_check
|
||||
(const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data)
|
||||
{
|
||||
detail::key_nodeptr_comp<KeyValueCompare, real_value_traits>
|
||||
comp(key_value_comp, &this->get_real_value_traits());
|
||||
detail::key_nodeptr_comp<KeyValueCompare, value_traits>
|
||||
comp(key_value_comp, &this->get_value_traits());
|
||||
std::pair<node_ptr, bool> ret =
|
||||
(node_algorithms::insert_unique_check
|
||||
(this->tree_type::header_ptr(), key, comp, commit_data));
|
||||
return std::pair<iterator, bool>(iterator(ret.first, this->real_value_traits_ptr()), ret.second);
|
||||
return std::pair<iterator, bool>(iterator(ret.first, this->value_traits_ptr()), ret.second);
|
||||
}
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::insert_unique_check(const_iterator,const KeyType&,KeyValueCompare,insert_commit_data&)
|
||||
@ -476,18 +490,18 @@ class sgtree_impl
|
||||
(const_iterator hint, const KeyType &key
|
||||
,KeyValueCompare key_value_comp, insert_commit_data &commit_data)
|
||||
{
|
||||
detail::key_nodeptr_comp<KeyValueCompare, real_value_traits>
|
||||
comp(key_value_comp, &this->get_real_value_traits());
|
||||
detail::key_nodeptr_comp<KeyValueCompare, value_traits>
|
||||
comp(key_value_comp, &this->get_value_traits());
|
||||
std::pair<node_ptr, bool> ret =
|
||||
(node_algorithms::insert_unique_check
|
||||
(this->tree_type::header_ptr(), hint.pointed_node(), key, comp, commit_data));
|
||||
return std::pair<iterator, bool>(iterator(ret.first, this->real_value_traits_ptr()), ret.second);
|
||||
return std::pair<iterator, bool>(iterator(ret.first, this->value_traits_ptr()), ret.second);
|
||||
}
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::insert_unique_commit
|
||||
iterator insert_unique_commit(reference value, const insert_commit_data &commit_data)
|
||||
{
|
||||
node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value));
|
||||
node_ptr to_insert(this->get_value_traits().to_node_ptr(value));
|
||||
if(safemode_or_autounlink)
|
||||
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert));
|
||||
std::size_t max_tree_size = (std::size_t)this->max_tree_size_;
|
||||
@ -496,7 +510,7 @@ class sgtree_impl
|
||||
, (std::size_t)this->size(), this->get_h_alpha_func(), max_tree_size);
|
||||
this->tree_type::sz_traits().increment();
|
||||
this->max_tree_size_ = (size_type)max_tree_size;
|
||||
return iterator(to_insert, this->real_value_traits_ptr());
|
||||
return iterator(to_insert, this->value_traits_ptr());
|
||||
}
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::insert_unique(Iterator,Iterator)
|
||||
@ -517,7 +531,7 @@ class sgtree_impl
|
||||
//! @copydoc ::boost::intrusive::bstree::insert_before
|
||||
iterator insert_before(const_iterator pos, reference value)
|
||||
{
|
||||
node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value));
|
||||
node_ptr to_insert(this->get_value_traits().to_node_ptr(value));
|
||||
if(safemode_or_autounlink)
|
||||
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert));
|
||||
std::size_t max_tree_size = (std::size_t)this->max_tree_size_;
|
||||
@ -526,13 +540,13 @@ class sgtree_impl
|
||||
, (size_type)this->size(), this->get_h_alpha_func(), max_tree_size);
|
||||
this->tree_type::sz_traits().increment();
|
||||
this->max_tree_size_ = (size_type)max_tree_size;
|
||||
return iterator(p, this->real_value_traits_ptr());
|
||||
return iterator(p, this->value_traits_ptr());
|
||||
}
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::push_back
|
||||
void push_back(reference value)
|
||||
{
|
||||
node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value));
|
||||
node_ptr to_insert(this->get_value_traits().to_node_ptr(value));
|
||||
if(safemode_or_autounlink)
|
||||
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert));
|
||||
std::size_t max_tree_size = (std::size_t)this->max_tree_size_;
|
||||
@ -546,7 +560,7 @@ class sgtree_impl
|
||||
//! @copydoc ::boost::intrusive::bstree::push_front
|
||||
void push_front(reference value)
|
||||
{
|
||||
node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value));
|
||||
node_ptr to_insert(this->get_value_traits().to_node_ptr(value));
|
||||
if(safemode_or_autounlink)
|
||||
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert));
|
||||
std::size_t max_tree_size = (std::size_t)this->max_tree_size_;
|
||||
@ -605,7 +619,7 @@ class sgtree_impl
|
||||
{
|
||||
node_ptr to_erase(i.pointed_node());
|
||||
iterator ret(this->erase(i));
|
||||
disposer(this->get_real_value_traits().to_value_ptr(to_erase));
|
||||
disposer(this->get_value_traits().to_value_ptr(to_erase));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -666,7 +680,7 @@ class sgtree_impl
|
||||
//! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
size_type count(const KeyType& key, KeyValueCompare comp) const;
|
||||
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference)
|
||||
iterator lower_bound(const_reference value);
|
||||
|
||||
@ -915,14 +929,13 @@ class sgtree
|
||||
public:
|
||||
typedef typename Base::value_compare value_compare;
|
||||
typedef typename Base::value_traits value_traits;
|
||||
typedef typename Base::real_value_traits real_value_traits;
|
||||
typedef typename Base::iterator iterator;
|
||||
typedef typename Base::const_iterator const_iterator;
|
||||
typedef typename Base::reverse_iterator reverse_iterator;
|
||||
typedef typename Base::const_reverse_iterator const_reverse_iterator;
|
||||
|
||||
//Assert if passed value traits are compatible with the type
|
||||
BOOST_STATIC_ASSERT((detail::is_same<typename real_value_traits::value_type, T>::value));
|
||||
BOOST_STATIC_ASSERT((detail::is_same<typename value_traits::value_type, T>::value));
|
||||
|
||||
explicit sgtree( const value_compare &cmp = value_compare()
|
||||
, const value_traits &v_traits = value_traits())
|
||||
|
@ -18,9 +18,9 @@
|
||||
#define BOOST_INTRUSIVE_SGTREE_ALGORITHMS_HPP
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
#include <boost/intrusive/detail/assert.hpp>
|
||||
#include <boost/intrusive/detail/utilities.hpp>
|
||||
#include <boost/intrusive/bstree_algorithms.hpp>
|
||||
@ -187,6 +187,7 @@ class sgtree_algorithms
|
||||
//! @copydoc ::boost::intrusive::bstree_algorithms::count(const const_node_ptr&,const KeyType&,KeyNodePtrCompare)
|
||||
template<class KeyType, class KeyNodePtrCompare>
|
||||
static std::size_t count(const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp);
|
||||
|
||||
#endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree_algorithms::insert_equal_upper_bound(const node_ptr&,const node_ptr&,NodePtrCompare)
|
||||
@ -330,25 +331,21 @@ class sgtree_algorithms
|
||||
//than the weight balanced method.
|
||||
node_ptr s = x;
|
||||
std::size_t size = 1;
|
||||
for(std::size_t ancestor = 1; true; ++ancestor){
|
||||
if(ancestor == depth){ //Check if whole tree must be rebuilt
|
||||
max_tree_size = tree_size;
|
||||
bstree_algo::rebalance_subtree(NodeTraits::get_parent(s));
|
||||
break;
|
||||
}
|
||||
else{ //Go to the next scapegoat candidate
|
||||
const node_ptr s_parent = NodeTraits::get_parent(s);
|
||||
const node_ptr s_parent_left = NodeTraits::get_left(s_parent);
|
||||
//Obtain parent's size (previous size + parent + sibling tree)
|
||||
const node_ptr s_sibling = s_parent_left == s ? NodeTraits::get_right(s_parent) : s_parent_left;
|
||||
size += 1 + bstree_algo::subtree_size(s_sibling);
|
||||
s = s_parent;
|
||||
if(ancestor > h_alpha(size)){ //is 's' scapegoat?
|
||||
bstree_algo::rebalance_subtree(s);
|
||||
break;
|
||||
}
|
||||
for(std::size_t ancestor = 1; ancestor != depth; ++ancestor){
|
||||
const node_ptr s_parent = NodeTraits::get_parent(s);
|
||||
const node_ptr s_parent_left = NodeTraits::get_left(s_parent);
|
||||
//Obtain parent's size (previous size + parent + sibling tree)
|
||||
const node_ptr s_sibling = s_parent_left == s ? NodeTraits::get_right(s_parent) : s_parent_left;
|
||||
size += 1 + bstree_algo::subtree_size(s_sibling);
|
||||
s = s_parent;
|
||||
if(ancestor > h_alpha(size)){ //is 's' scapegoat?
|
||||
bstree_algo::rebalance_subtree(s);
|
||||
return;
|
||||
}
|
||||
}
|
||||
//The whole tree must be rebuilt
|
||||
max_tree_size = tree_size;
|
||||
bstree_algo::rebalance_subtree(NodeTraits::get_parent(s));
|
||||
}
|
||||
}
|
||||
/// @endcond
|
||||
|
@ -80,7 +80,7 @@ struct make_slist_base_hook
|
||||
//! \c auto_unlink or \c safe_link).
|
||||
//!
|
||||
//! \c void_pointer<> is the pointer type that will be used internally in the hook
|
||||
//! and the the container configured to use this hook.
|
||||
//! and the container configured to use this hook.
|
||||
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template<class ...Options>
|
||||
#else
|
||||
@ -203,7 +203,7 @@ struct make_slist_member_hook
|
||||
//! \c auto_unlink or \c safe_link).
|
||||
//!
|
||||
//! \c void_pointer<> is the pointer type that will be used internally in the hook
|
||||
//! and the the container configured to use this hook.
|
||||
//! and the container configured to use this hook.
|
||||
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template<class ...Options>
|
||||
#else
|
||||
|
@ -247,12 +247,18 @@ class splay_set_impl
|
||||
template<class Disposer>
|
||||
void clear_and_dispose(Disposer disposer);
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::count(const_reference)
|
||||
size_type count(const_reference value);
|
||||
#endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::count(const_reference)const
|
||||
size_type count(const_reference value) const
|
||||
{ return static_cast<size_type>(this->tree_type::find(value) != this->tree_type::cend()); }
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::count(const KeyType&,KeyValueCompare)const
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
size_type count(const KeyType& key, KeyValueCompare comp);
|
||||
size_type count(const KeyType& key, KeyValueCompare comp) const
|
||||
{ return static_cast<size_type>(this->tree_type::find(key, comp) != this->tree_type::cend()); }
|
||||
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::count(const_reference)const
|
||||
size_type count(const_reference value) const;
|
||||
@ -261,13 +267,6 @@ class splay_set_impl
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
size_type count(const KeyType& key, KeyValueCompare comp) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::count_dont_splay(const_reference)const
|
||||
size_type count_dont_splay(const_reference value) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::count_dont_splay(const KeyType&,KeyValueCompare)const
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
size_type count_dont_splay(const KeyType& key, KeyValueCompare comp) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::lower_bound(const_reference)
|
||||
iterator lower_bound(const_reference value);
|
||||
|
||||
@ -282,13 +281,6 @@ class splay_set_impl
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::lower_bound_dont_splay(const_reference)const
|
||||
const_iterator lower_bound_dont_splay(const_reference value) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::lower_bound_dont_splay(const KeyType&,KeyValueCompare)const
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
const_iterator lower_bound_dont_splay(const KeyType& key, KeyValueCompare comp) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::upper_bound(const_reference)
|
||||
iterator upper_bound(const_reference value);
|
||||
|
||||
@ -303,13 +295,6 @@ class splay_set_impl
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::upper_bound_dont_splay(const_reference)const
|
||||
const_iterator upper_bound_dont_splay(const_reference value) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::upper_bound_dont_splay(const KeyType&,KeyValueCompare)const
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
const_iterator upper_bound_dont_splay(const KeyType& key, KeyValueCompare comp) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::find(const_reference)
|
||||
iterator find(const_reference value);
|
||||
|
||||
@ -324,37 +309,29 @@ class splay_set_impl
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
const_iterator find(const KeyType& key, KeyValueCompare comp) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::find_dont_splay(const_reference)const
|
||||
const_iterator find_dont_splay(const_reference value) const;
|
||||
#endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::find_dont_splay(const KeyType&,KeyValueCompare)const
|
||||
//! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference)
|
||||
std::pair<iterator,iterator> equal_range(const_reference value)
|
||||
{ return this->tree_type::lower_bound_range(value); }
|
||||
|
||||
//! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare)
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
const_iterator find_dont_splay(const KeyType& key, KeyValueCompare comp) const;
|
||||
std::pair<iterator,iterator> equal_range(const KeyType& key, KeyValueCompare comp)
|
||||
{ return this->tree_type::lower_bound_range(key, comp); }
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::equal_range(const_reference)
|
||||
std::pair<iterator,iterator> equal_range(const_reference value);
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::equal_range(const KeyType&,KeyValueCompare)
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
std::pair<iterator,iterator> equal_range(const KeyType& key, KeyValueCompare comp);
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::equal_range(const_reference)const
|
||||
//! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference)const
|
||||
std::pair<const_iterator, const_iterator>
|
||||
equal_range(const_reference value) const;
|
||||
equal_range(const_reference value) const
|
||||
{ return this->tree_type::lower_bound_range(value); }
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::equal_range(const KeyType&,KeyValueCompare)const
|
||||
//! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare)const
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
std::pair<const_iterator, const_iterator>
|
||||
equal_range(const KeyType& key, KeyValueCompare comp) const;
|
||||
equal_range(const KeyType& key, KeyValueCompare comp) const
|
||||
{ return this->tree_type::lower_bound_range(key, comp); }
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::equal_range_dont_splay(const_reference)const
|
||||
std::pair<const_iterator, const_iterator>
|
||||
equal_range_dont_splay(const_reference value) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::equal_range_dont_splay(const KeyType&,KeyValueCompare)const
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
std::pair<const_iterator, const_iterator>
|
||||
equal_range_dont_splay(const KeyType& key, KeyValueCompare comp) const;
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::bounded_range(const_reference,const_reference,bool,bool)
|
||||
std::pair<iterator,iterator> bounded_range
|
||||
@ -374,15 +351,6 @@ class splay_set_impl
|
||||
std::pair<const_iterator, const_iterator> bounded_range
|
||||
(const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::bounded_range_dont_splay(const_reference,const_reference,bool,bool)const
|
||||
std::pair<const_iterator, const_iterator> bounded_range_dont_splay
|
||||
(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::bounded_range_dont_splay(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
std::pair<const_iterator, const_iterator> bounded_range_dont_splay
|
||||
(const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::s_iterator_to(reference)
|
||||
static iterator s_iterator_to(reference value);
|
||||
|
||||
@ -760,20 +728,6 @@ class splay_multiset_impl
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
size_type count(const KeyType& key, KeyValueCompare comp);
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::count(const_reference)const
|
||||
size_type count(const_reference value) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::count(const KeyType&,KeyValueCompare)const
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
size_type count(const KeyType& key, KeyValueCompare comp) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::count_dont_splay(const_reference)const
|
||||
size_type count_dont_splay(const_reference value) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::count_dont_splay(const KeyType&,KeyValueCompare)const
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
size_type count_dont_splay(const KeyType& key, KeyValueCompare comp) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::lower_bound(const_reference)
|
||||
iterator lower_bound(const_reference value);
|
||||
|
||||
@ -788,13 +742,6 @@ class splay_multiset_impl
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::lower_bound_dont_splay(const_reference)const
|
||||
const_iterator lower_bound_dont_splay(const_reference value) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::lower_bound_dont_splay(const KeyType&,KeyValueCompare)const
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
const_iterator lower_bound_dont_splay(const KeyType& key, KeyValueCompare comp) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::upper_bound(const_reference)
|
||||
iterator upper_bound(const_reference value);
|
||||
|
||||
@ -809,13 +756,6 @@ class splay_multiset_impl
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::upper_bound_dont_splay(const_reference)const
|
||||
const_iterator upper_bound_dont_splay(const_reference value) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::upper_bound_dont_splay(const KeyType&,KeyValueCompare)const
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
const_iterator upper_bound_dont_splay(const KeyType& key, KeyValueCompare comp) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::find(const_reference)
|
||||
iterator find(const_reference value);
|
||||
|
||||
@ -830,13 +770,6 @@ class splay_multiset_impl
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
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<class KeyType, class KeyValueCompare>
|
||||
const_iterator find_dont_splay(const KeyType& key, KeyValueCompare comp) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::equal_range(const_reference)
|
||||
std::pair<iterator,iterator> equal_range(const_reference value);
|
||||
|
||||
@ -853,15 +786,6 @@ class splay_multiset_impl
|
||||
std::pair<const_iterator, const_iterator>
|
||||
equal_range(const KeyType& key, KeyValueCompare comp) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::equal_range_dont_splay(const_reference)const
|
||||
std::pair<const_iterator, const_iterator>
|
||||
equal_range_dont_splay(const_reference value) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::equal_range_dont_splay(const KeyType&,KeyValueCompare)const
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
std::pair<const_iterator, const_iterator>
|
||||
equal_range_dont_splay(const KeyType& key, KeyValueCompare comp) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::bounded_range(const_reference,const_reference,bool,bool)
|
||||
std::pair<iterator,iterator> bounded_range
|
||||
(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed);
|
||||
@ -880,15 +804,6 @@ class splay_multiset_impl
|
||||
std::pair<const_iterator, const_iterator> bounded_range
|
||||
(const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::bounded_range_dont_splay(const_reference,const_reference,bool,bool)const
|
||||
std::pair<const_iterator, const_iterator> bounded_range_dont_splay
|
||||
(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::bounded_range_dont_splay(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
std::pair<const_iterator, const_iterator> bounded_range_dont_splay
|
||||
(const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::splaytree::s_iterator_to(reference)
|
||||
static iterator s_iterator_to(reference value);
|
||||
|
||||
|
@ -1,286 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Olaf Krzikalla 2004-2006.
|
||||
// (C) Copyright Ion Gaztanaga 2006-2013
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/intrusive for documentation.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef BOOST_INTRUSIVE_SPLAY_SET_HOOK_HPP
|
||||
#define BOOST_INTRUSIVE_SPLAY_SET_HOOK_HPP
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/bs_set_hook.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
|
||||
//! Helper metafunction to define a \c splay_set_base_hook that yields to the same
|
||||
//! type when the same options (either explicitly or implicitly) are used.
|
||||
//! <b>WARNING: </b> Deprecated class, use `make_bs_set_base_hook` instead.
|
||||
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template<class ...Options>
|
||||
#else
|
||||
template<class O1 = void, class O2 = void, class O3 = void>
|
||||
#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<Options...>
|
||||
#else
|
||||
: public make_bs_set_base_hook<O1, O2, O3>
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
/// @cond
|
||||
typedef typename make_bs_set_base_hook
|
||||
<
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
O1, O2, O3
|
||||
#else
|
||||
Options...
|
||||
#endif
|
||||
>::type implementation_defined;
|
||||
/// @endcond
|
||||
typedef implementation_defined type;
|
||||
};
|
||||
|
||||
//! Derive a class from splay_set_base_hook in order to store objects in
|
||||
//! in a splay_set/splay_multiset. splay_set_base_hook holds the data necessary to maintain
|
||||
//! the splay_set/splay_multiset and provides an appropriate value_traits class for splay_set/splay_multiset.
|
||||
//!
|
||||
//! The hook admits the following options: \c tag<>, \c void_pointer<>,
|
||||
//! \c link_mode<> and \c optimize_size<>.
|
||||
//!
|
||||
//! \c tag<> defines a tag to identify the node.
|
||||
//! The same tag value can be used in different classes, but if a class is
|
||||
//! derived from more than one \c list_base_hook, then each \c list_base_hook needs its
|
||||
//! unique tag.
|
||||
//!
|
||||
//! \c void_pointer<> is the pointer type that will be used internally in the hook
|
||||
//! and the the container configured to use this hook.
|
||||
//!
|
||||
//! \c link_mode<> will specify the linking mode of the hook (\c normal_link,
|
||||
//! \c auto_unlink or \c safe_link).
|
||||
//!
|
||||
//! <b>WARNING: </b> Deprecated class, use `bs_set_base_hook` instead.
|
||||
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template<class ...Options>
|
||||
#else
|
||||
template<class O1, class O2, class O3>
|
||||
#endif
|
||||
class splay_set_base_hook
|
||||
: public make_splay_set_base_hook<
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
O1, O2, O3
|
||||
#else
|
||||
Options...
|
||||
#endif
|
||||
>::type
|
||||
{
|
||||
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
|
||||
public:
|
||||
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
|
||||
//! initializes the node to an unlinked state.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
splay_set_base_hook();
|
||||
|
||||
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
|
||||
//! initializes the node to an unlinked state. The argument is ignored.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Rationale</b>: Providing a copy-constructor
|
||||
//! makes classes using the hook STL-compliant without forcing the
|
||||
//! user to do some additional work. \c swap can be used to emulate
|
||||
//! move-semantics.
|
||||
splay_set_base_hook(const splay_set_base_hook& );
|
||||
|
||||
//! <b>Effects</b>: Empty function. The argument is ignored.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Rationale</b>: Providing an assignment operator
|
||||
//! makes classes using the hook STL-compliant without forcing the
|
||||
//! user to do some additional work. \c swap can be used to emulate
|
||||
//! move-semantics.
|
||||
splay_set_base_hook& operator=(const splay_set_base_hook& );
|
||||
|
||||
//! <b>Effects</b>: If link_mode is \c normal_link, the destructor does
|
||||
//! nothing (ie. no code is generated). If link_mode is \c safe_link and the
|
||||
//! object is stored in a set an assertion is raised. If link_mode is
|
||||
//! \c auto_unlink and \c is_linked() is true, the node is unlinked.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
~splay_set_base_hook();
|
||||
|
||||
//! <b>Effects</b>: Swapping two nodes swaps the position of the elements
|
||||
//! related to those nodes in one or two containers. That is, if the node
|
||||
//! this is part of the element e1, the node x is part of the element e2
|
||||
//! and both elements are included in the containers s1 and s2, then after
|
||||
//! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1
|
||||
//! at the position of e1. If one element is not in a container, then
|
||||
//! after the swap-operation the other element is not in a container.
|
||||
//! Iterators to e1 and e2 related to those nodes are invalidated.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
void swap_nodes(splay_set_base_hook &other);
|
||||
|
||||
//! <b>Precondition</b>: link_mode must be \c safe_link or \c auto_unlink.
|
||||
//!
|
||||
//! <b>Returns</b>: true, if the node belongs to a container, false
|
||||
//! otherwise. This function can be used to test whether \c set::iterator_to
|
||||
//! will return a valid iterator.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
bool is_linked() const;
|
||||
|
||||
//! <b>Effects</b>: Removes the node if it's inserted in a container.
|
||||
//! This function is only allowed if link_mode is \c auto_unlink.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
void unlink();
|
||||
#endif
|
||||
};
|
||||
|
||||
//! Helper metafunction to define a \c splay_set_member_hook that yields to the same
|
||||
//! type when the same options (either explicitly or implicitly) are used.
|
||||
//!
|
||||
//! <b>WARNING: </b> Deprecated class, use `make_bs_set_member_hook` instead.
|
||||
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template<class ...Options>
|
||||
#else
|
||||
template<class O1 = void, class O2 = void, class O3 = void>
|
||||
#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<Options...>
|
||||
#else
|
||||
: public make_bs_set_member_hook<O1, O2, O3>
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
/// @cond
|
||||
typedef typename make_bs_set_member_hook
|
||||
<
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
O1, O2, O3
|
||||
#else
|
||||
Options...
|
||||
#endif
|
||||
>::type implementation_defined;
|
||||
/// @endcond
|
||||
typedef implementation_defined type;
|
||||
};
|
||||
|
||||
//! Put a public data member splay_set_member_hook in order to store objects of this
|
||||
//! class in a splay_set/splay_multiset. splay_set_member_hook holds the data
|
||||
//! necessary for maintaining the splay_set/splay_multiset and provides an appropriate
|
||||
//! value_traits class for splay_set/splay_multiset.
|
||||
//!
|
||||
//! The hook admits the following options: \c void_pointer<>,
|
||||
//! \c link_mode<> and \c optimize_size<>.
|
||||
//!
|
||||
//! \c void_pointer<> is the pointer type that will be used internally in the hook
|
||||
//! and the the container configured to use this hook.
|
||||
//!
|
||||
//! \c link_mode<> will specify the linking mode of the hook (\c normal_link,
|
||||
//! \c auto_unlink or \c safe_link).
|
||||
//!
|
||||
//! <b>WARNING: </b> Deprecated class, use `bs_set_member_hook` instead.
|
||||
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
template<class ...Options>
|
||||
#else
|
||||
template<class O1, class O2, class O3>
|
||||
#endif
|
||||
class splay_set_member_hook
|
||||
: public make_splay_set_member_hook<
|
||||
#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
||||
O1, O2, O3
|
||||
#else
|
||||
Options...
|
||||
#endif
|
||||
>::type
|
||||
{
|
||||
#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
|
||||
public:
|
||||
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
|
||||
//! initializes the node to an unlinked state.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
splay_set_member_hook();
|
||||
|
||||
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
|
||||
//! initializes the node to an unlinked state. The argument is ignored.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Rationale</b>: Providing a copy-constructor
|
||||
//! makes classes using the hook STL-compliant without forcing the
|
||||
//! user to do some additional work. \c swap can be used to emulate
|
||||
//! move-semantics.
|
||||
splay_set_member_hook(const splay_set_member_hook& );
|
||||
|
||||
//! <b>Effects</b>: Empty function. The argument is ignored.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Rationale</b>: Providing an assignment operator
|
||||
//! makes classes using the hook STL-compliant without forcing the
|
||||
//! user to do some additional work. \c swap can be used to emulate
|
||||
//! move-semantics.
|
||||
splay_set_member_hook& operator=(const splay_set_member_hook& );
|
||||
|
||||
//! <b>Effects</b>: If link_mode is \c normal_link, the destructor does
|
||||
//! nothing (ie. no code is generated). If link_mode is \c safe_link and the
|
||||
//! object is stored in a set an assertion is raised. If link_mode is
|
||||
//! \c auto_unlink and \c is_linked() is true, the node is unlinked.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
~splay_set_member_hook();
|
||||
|
||||
//! <b>Effects</b>: Swapping two nodes swaps the position of the elements
|
||||
//! related to those nodes in one or two containers. That is, if the node
|
||||
//! this is part of the element e1, the node x is part of the element e2
|
||||
//! and both elements are included in the containers s1 and s2, then after
|
||||
//! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1
|
||||
//! at the position of e1. If one element is not in a container, then
|
||||
//! after the swap-operation the other element is not in a container.
|
||||
//! Iterators to e1 and e2 related to those nodes are invalidated.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
void swap_nodes(splay_set_member_hook &other);
|
||||
|
||||
//! <b>Precondition</b>: link_mode must be \c safe_link or \c auto_unlink.
|
||||
//!
|
||||
//! <b>Returns</b>: true, if the node belongs to a container, false
|
||||
//! otherwise. This function can be used to test whether \c set::iterator_to
|
||||
//! will return a valid iterator.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
bool is_linked() const;
|
||||
|
||||
//! <b>Effects</b>: Removes the node if it's inserted in a container.
|
||||
//! This function is only allowed if link_mode is \c auto_unlink.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
void unlink();
|
||||
#endif
|
||||
};
|
||||
|
||||
} //namespace intrusive
|
||||
} //namespace boost
|
||||
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTRUSIVE_SPLAY_SET_HOOK_HPP
|
@ -13,6 +13,7 @@
|
||||
#define BOOST_INTRUSIVE_SPLAYTREE_HPP
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
@ -20,8 +21,6 @@
|
||||
|
||||
#include <boost/intrusive/detail/assert.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
#include <boost/intrusive/splay_set_hook.hpp>
|
||||
#include <boost/intrusive/bstree.hpp>
|
||||
#include <boost/intrusive/detail/tree_node.hpp>
|
||||
#include <boost/intrusive/detail/ebo_functor_holder.hpp>
|
||||
@ -77,7 +76,6 @@ class splaytree_impl
|
||||
/// @cond
|
||||
typedef bstree_impl< ValueTraits, VoidOrKeyComp, SizeType
|
||||
, ConstantTimeSize, SplayTreeAlgorithms> tree_type;
|
||||
typedef typename tree_type::real_value_traits real_value_traits;
|
||||
typedef tree_type implementation_defined;
|
||||
/// @endcond
|
||||
|
||||
@ -267,7 +265,6 @@ class splaytree_impl
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::erase(const KeyType&,KeyValueCompare)
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
|
||||
size_type erase(const KeyType& key, KeyValueCompare comp);
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::erase_and_dispose(const_iterator,Disposer)
|
||||
@ -293,60 +290,32 @@ class splaytree_impl
|
||||
template<class Disposer>
|
||||
void clear_and_dispose(Disposer disposer);
|
||||
|
||||
#endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::count(const_reference)const
|
||||
//! Additional note: non-const function, splaying is performed for the first
|
||||
//! element of the equal range of "value"
|
||||
size_type count(const_reference value)
|
||||
{ return this->count(value, this->value_comp()); }
|
||||
//! Additional note: non-const function, splaying is performed.
|
||||
size_type count(const_reference value);
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const
|
||||
//! Additional note: non-const function, splaying is performed for the first
|
||||
//! element of the equal range of "key"
|
||||
//! Additional note: non-const function, splaying is performed.
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
size_type count(const KeyType &key, KeyValueCompare comp)
|
||||
{
|
||||
std::pair<const_iterator, const_iterator> ret = this->equal_range(key, comp);
|
||||
return std::distance(ret.first, ret.second);
|
||||
}
|
||||
size_type count(const KeyType &key, KeyValueCompare comp);
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::count(const_reference)const
|
||||
//! Additional note: Deprecated function, use count const overload instead.
|
||||
size_type count(const_reference value) const
|
||||
{ return tree_type::count(value); }
|
||||
//! Additional note: const function, no splaying is performed
|
||||
size_type count(const_reference value) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const
|
||||
//! Additional note: Deprecated function, use count const overload instead.
|
||||
//! Additional note: const function, no splaying is performed
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
size_type count(const KeyType &key, KeyValueCompare comp) const
|
||||
{ return tree_type::count(key, comp); }
|
||||
size_type count(const KeyType &key, KeyValueCompare comp) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::count(const_reference)const
|
||||
//! Additional note: Deprecated function, use count const overload instead.
|
||||
size_type count_dont_splay(const_reference value) const
|
||||
{ return tree_type::count(value); }
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const
|
||||
//! Additional note: Deprecated function, use count const overload instead.
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
size_type count_dont_splay(const KeyType &key, KeyValueCompare comp) const
|
||||
{ return tree_type::count(key, comp); }
|
||||
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
//! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference)
|
||||
//! Additional note: non-const function, splaying is performed for the first
|
||||
//! element of the equal range of "value"
|
||||
//! Additional note: non-const function, splaying is performed.
|
||||
iterator lower_bound(const_reference value);
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference)const
|
||||
//! Additional note: const function, no splaying is performed
|
||||
const_iterator lower_bound(const_reference value) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference)const
|
||||
//! Additional note: Deprecated function, use lower_bound const overload instead.
|
||||
const_iterator lower_bound_dont_splay(const_reference value) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare)
|
||||
//! Additional note: non-const function, splaying is performed for the first
|
||||
//! element of the equal range of "key"
|
||||
@ -358,11 +327,6 @@ class splaytree_impl
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
const_iterator lower_bound(const KeyType &key, KeyValueCompare comp) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::lower_bound(const KeyType&,KeyValueCompare)
|
||||
//! Additional note: Deprecated function, use lower_bound const overload instead.
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
iterator lower_bound_dont_splay(const KeyType &key, KeyValueCompare comp) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference)
|
||||
//! Additional note: non-const function, splaying is performed for the first
|
||||
//! element of the equal range of "value"
|
||||
@ -372,10 +336,6 @@ class splaytree_impl
|
||||
//! Additional note: const function, no splaying is performed
|
||||
const_iterator upper_bound(const_reference value) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::upper_bound(const_reference)const
|
||||
//! Additional note: Deprecated function, use upper_bound const overload instead.
|
||||
const_iterator upper_bound_dont_splay(const_reference value) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare)
|
||||
//! Additional note: non-const function, splaying is performed for the first
|
||||
//! element of the equal range of "key"
|
||||
@ -387,11 +347,6 @@ class splaytree_impl
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
const_iterator upper_bound(const KeyType &key, KeyValueCompare comp) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::upper_bound(const KeyType&,KeyValueCompare)
|
||||
//! Additional note: Deprecated function, use upper_bound const overload instead.
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
const_iterator upper_bound_dont_splay(const KeyType &key, KeyValueCompare comp) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::find(const_reference)
|
||||
//! Additional note: non-const function, splaying is performed for the first
|
||||
//! element of the equal range of "value"
|
||||
@ -401,10 +356,6 @@ class splaytree_impl
|
||||
//! Additional note: const function, no splaying is performed
|
||||
const_iterator find(const_reference value) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::find(const_reference)const
|
||||
//! Additional note: Deprecated function, use find const overload instead.
|
||||
const_iterator find_dont_splay(const_reference value) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare)
|
||||
//! Additional note: non-const function, splaying is performed for the first
|
||||
//! element of the equal range of "key"
|
||||
@ -416,11 +367,6 @@ class splaytree_impl
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
const_iterator find(const KeyType &key, KeyValueCompare comp) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::find(const KeyType&,KeyValueCompare)const
|
||||
//! Additional note: Deprecated function, use find const overload instead.
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
const_iterator find_dont_splay(const KeyType &key, KeyValueCompare comp) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::equal_range(const_reference)
|
||||
//! Additional note: non-const function, splaying is performed for the first
|
||||
//! element of the equal range of "value"
|
||||
@ -430,10 +376,6 @@ class splaytree_impl
|
||||
//! Additional note: const function, no splaying is performed
|
||||
std::pair<const_iterator, const_iterator> 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<const_iterator, const_iterator> equal_range_dont_splay(const_reference value) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::equal_range(const KeyType&,KeyValueCompare)
|
||||
//! Additional note: non-const function, splaying is performed for the first
|
||||
//! element of the equal range of "key"
|
||||
@ -445,11 +387,6 @@ class splaytree_impl
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
std::pair<const_iterator, const_iterator> 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<class KeyType, class KeyValueCompare>
|
||||
std::pair<const_iterator, const_iterator> equal_range_dont_splay(const KeyType &key, KeyValueCompare comp) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::bounded_range(const_reference,const_reference,bool,bool)
|
||||
std::pair<iterator,iterator> bounded_range
|
||||
(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed);
|
||||
@ -468,17 +405,6 @@ class splaytree_impl
|
||||
std::pair<const_iterator, const_iterator> bounded_range
|
||||
(const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::bounded_range(const_reference,const_reference,bool,bool)const
|
||||
//! Additional note: Deprecated function, use bounded_range const overload instead.
|
||||
std::pair<const_iterator, const_iterator> bounded_range_dont_splay
|
||||
(const_reference lower_value, const_reference upper_value, bool left_closed, bool right_closed) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::bounded_range(const KeyType&,const KeyType&,KeyValueCompare,bool,bool)const
|
||||
//! Additional note: Deprecated function, use bounded_range const overload instead.
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
std::pair<const_iterator, const_iterator> bounded_range_dont_splay
|
||||
(const KeyType& lower_key, const KeyType& upper_key, KeyValueCompare comp, bool left_closed, bool right_closed) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::s_iterator_to(reference)
|
||||
static iterator s_iterator_to(reference value);
|
||||
|
||||
@ -529,10 +455,10 @@ class splaytree_impl
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
iterator splay_down(const KeyType &key, KeyValueCompare comp)
|
||||
{
|
||||
detail::key_nodeptr_comp<value_compare, real_value_traits>
|
||||
key_node_comp(comp, &this->get_real_value_traits());
|
||||
detail::key_nodeptr_comp<value_compare, value_traits>
|
||||
key_node_comp(comp, &this->get_value_traits());
|
||||
node_ptr r = node_algorithms::splay_down(tree_type::header_ptr(), key, key_node_comp);
|
||||
return iterator(r, this->real_value_traits_ptr());
|
||||
return iterator(r, this->value_traits_ptr());
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Rearranges the container so that if *this stores an element
|
||||
@ -644,14 +570,13 @@ class splaytree
|
||||
public:
|
||||
typedef typename Base::value_compare value_compare;
|
||||
typedef typename Base::value_traits value_traits;
|
||||
typedef typename Base::real_value_traits real_value_traits;
|
||||
typedef typename Base::iterator iterator;
|
||||
typedef typename Base::const_iterator const_iterator;
|
||||
typedef typename Base::reverse_iterator reverse_iterator;
|
||||
typedef typename Base::const_reverse_iterator const_reverse_iterator;
|
||||
|
||||
//Assert if passed value traits are compatible with the type
|
||||
BOOST_STATIC_ASSERT((detail::is_same<typename real_value_traits::value_type, T>::value));
|
||||
BOOST_STATIC_ASSERT((detail::is_same<typename value_traits::value_type, T>::value));
|
||||
|
||||
explicit splaytree( const value_compare &cmp = value_compare()
|
||||
, const value_traits &v_traits = value_traits())
|
||||
|
@ -31,8 +31,8 @@
|
||||
#define BOOST_INTRUSIVE_SPLAYTREE_ALGORITHMS_HPP
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/detail/assert.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
#include <boost/intrusive/detail/assert.hpp>
|
||||
#include <boost/intrusive/pointer_traits.hpp>
|
||||
#include <cstddef>
|
||||
#include <boost/intrusive/detail/utilities.hpp>
|
||||
@ -45,33 +45,70 @@ namespace intrusive {
|
||||
namespace detail {
|
||||
|
||||
template<class NodeTraits>
|
||||
struct splaydown_rollback
|
||||
struct splaydown_assemble_and_fix_header
|
||||
{
|
||||
typedef typename NodeTraits::node_ptr node_ptr;
|
||||
splaydown_rollback( const node_ptr *pcur_subtree, const node_ptr & header
|
||||
, const node_ptr & leftmost , const node_ptr & rightmost)
|
||||
: pcur_subtree_(pcur_subtree) , header_(header)
|
||||
, leftmost_(leftmost) , rightmost_(rightmost)
|
||||
|
||||
splaydown_assemble_and_fix_header(const node_ptr & t, const node_ptr & header, const node_ptr &leftmost, const node_ptr &rightmost)
|
||||
: t_(t)
|
||||
, null_node_(header)
|
||||
, l_(null_node_)
|
||||
, r_(null_node_)
|
||||
, leftmost_(leftmost)
|
||||
, rightmost_(rightmost)
|
||||
{}
|
||||
|
||||
void release()
|
||||
{ pcur_subtree_ = 0; }
|
||||
|
||||
~splaydown_rollback()
|
||||
~splaydown_assemble_and_fix_header()
|
||||
{
|
||||
if(pcur_subtree_){
|
||||
//Exception can only be thrown by comp, but
|
||||
//tree invariants still hold. *pcur_subtree is the current root
|
||||
//so link it to the header.
|
||||
NodeTraits::set_parent(*pcur_subtree_, header_);
|
||||
NodeTraits::set_parent(header_, *pcur_subtree_);
|
||||
//Recover leftmost/rightmost pointers
|
||||
NodeTraits::set_left (header_, leftmost_);
|
||||
NodeTraits::set_right(header_, rightmost_);
|
||||
this->assemble();
|
||||
|
||||
//Now recover the original header except for the
|
||||
//splayed root node.
|
||||
//"t_" is the current root and "null_node_" is the header node
|
||||
NodeTraits::set_parent(null_node_, t_);
|
||||
NodeTraits::set_parent(t_, null_node_);
|
||||
//Recover leftmost/rightmost pointers
|
||||
NodeTraits::set_left (null_node_, leftmost_);
|
||||
NodeTraits::set_right(null_node_, rightmost_);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void assemble()
|
||||
{
|
||||
//procedure assemble;
|
||||
// left(r), right(l) := right(t), left(t);
|
||||
// left(t), right(t) := right(null), left(null);
|
||||
//end assemble;
|
||||
{ // left(r), right(l) := right(t), left(t);
|
||||
|
||||
node_ptr const old_t_left = NodeTraits::get_left(t_);
|
||||
node_ptr const old_t_right = NodeTraits::get_right(t_);
|
||||
NodeTraits::set_right(l_, old_t_left);
|
||||
NodeTraits::set_left (r_, old_t_right);
|
||||
if(old_t_left){
|
||||
NodeTraits::set_parent(old_t_left, l_);
|
||||
}
|
||||
if(old_t_right){
|
||||
NodeTraits::set_parent(old_t_right, r_);
|
||||
}
|
||||
}
|
||||
{ // left(t), right(t) := right(null), left(null);
|
||||
node_ptr const null_right = NodeTraits::get_right(null_node_);
|
||||
node_ptr const null_left = NodeTraits::get_left(null_node_);
|
||||
NodeTraits::set_left (t_, null_right);
|
||||
NodeTraits::set_right(t_, null_left);
|
||||
if(null_right){
|
||||
NodeTraits::set_parent(null_right, t_);
|
||||
}
|
||||
if(null_left){
|
||||
NodeTraits::set_parent(null_left, t_);
|
||||
}
|
||||
}
|
||||
}
|
||||
const node_ptr *pcur_subtree_;
|
||||
node_ptr header_, leftmost_, rightmost_;
|
||||
|
||||
public:
|
||||
node_ptr t_, null_node_, l_, r_, leftmost_, rightmost_;
|
||||
};
|
||||
|
||||
} //namespace detail {
|
||||
@ -184,32 +221,28 @@ class splaytree_algorithms
|
||||
#endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree_algorithms::erase(const node_ptr&,const node_ptr&)
|
||||
//! Additional notes: the previous node of z is splayed. The "splay" parameter which indicated if splaying
|
||||
//! should be performed, it's deprecated and will disappear in future versions.
|
||||
static void erase(const node_ptr & header, const node_ptr & z, bool splay = true)
|
||||
//! Additional notes: the previous node of z is splayed to speed up range deletions.
|
||||
static void erase(const node_ptr & header, const node_ptr & z)
|
||||
{
|
||||
//posibility 1
|
||||
if(splay && NodeTraits::get_left(z)){
|
||||
if(NodeTraits::get_left(z)){
|
||||
splay_up(bstree_algo::prev_node(z), header);
|
||||
}
|
||||
/*
|
||||
//possibility 2
|
||||
if(splay && NodeTraits::get_left(z)){
|
||||
if(NodeTraits::get_left(z)){
|
||||
node_ptr l = NodeTraits::get_left(z);
|
||||
splay_up(l, header);
|
||||
}*//*
|
||||
if(splay && NodeTraits::get_left(z)){
|
||||
}*/
|
||||
/*
|
||||
if(NodeTraits::get_left(z)){
|
||||
node_ptr l = bstree_algo::prev_node(z);
|
||||
splay_up_impl(l, z);
|
||||
}*/
|
||||
/*
|
||||
//possibility 4
|
||||
if(splay){
|
||||
splay_up(z, header);
|
||||
}*/
|
||||
|
||||
//if(splay)
|
||||
//splay_up(z, header);
|
||||
splay_up(z, header);
|
||||
*/
|
||||
bstree_algo::erase(header, z);
|
||||
}
|
||||
|
||||
@ -225,7 +258,7 @@ class splaytree_algorithms
|
||||
|
||||
#endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
//! @copydoc ::boost::intrusive::bstree_algorithms::count(const const_node_ptr&,const KeyType&,KeyNodePtrCompare)
|
||||
//! Additional notes: the first node of the range is splayed.
|
||||
//! Additional notes: an element with key `key` is splayed.
|
||||
template<class KeyType, class KeyNodePtrCompare>
|
||||
static std::size_t count
|
||||
(const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp)
|
||||
@ -247,15 +280,14 @@ class splaytree_algorithms
|
||||
{ return bstree_algo::count(header, key, comp); }
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree_algorithms::lower_bound(const const_node_ptr&,const KeyType&,KeyNodePtrCompare)
|
||||
//! Additional notes: the first node of the range is splayed. The "splay" parameter which indicated if splaying
|
||||
//! should be performed, it's deprecated and will disappear in future versions.
|
||||
//! Additional notes: the first node of the range is splayed.
|
||||
template<class KeyType, class KeyNodePtrCompare>
|
||||
static node_ptr lower_bound
|
||||
(const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool splay = true)
|
||||
(const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp)
|
||||
{
|
||||
//splay_down(detail::uncast(header), key, comp);
|
||||
splay_down(detail::uncast(header), key, comp);
|
||||
node_ptr y = bstree_algo::lower_bound(header, key, comp);
|
||||
if(splay) splay_up(y, detail::uncast(header));
|
||||
//splay_up(y, detail::uncast(header));
|
||||
return y;
|
||||
}
|
||||
|
||||
@ -267,15 +299,14 @@ class splaytree_algorithms
|
||||
{ return bstree_algo::lower_bound(header, key, comp); }
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree_algorithms::upper_bound(const const_node_ptr&,const KeyType&,KeyNodePtrCompare)
|
||||
//! Additional notes: the first node of the range is splayed. The "splay" parameter which indicated if splaying
|
||||
//! should be performed, it's deprecated and will disappear in future versions.
|
||||
//! Additional notes: the first node of the range is splayed.
|
||||
template<class KeyType, class KeyNodePtrCompare>
|
||||
static node_ptr upper_bound
|
||||
(const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool splay = true)
|
||||
(const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp)
|
||||
{
|
||||
//splay_down(detail::uncast(header), key, comp);
|
||||
splay_down(detail::uncast(header), key, comp);
|
||||
node_ptr y = bstree_algo::upper_bound(header, key, comp);
|
||||
if(splay) splay_up(y, detail::uncast(header));
|
||||
//splay_up(y, detail::uncast(header));
|
||||
return y;
|
||||
}
|
||||
|
||||
@ -287,17 +318,13 @@ class splaytree_algorithms
|
||||
{ return bstree_algo::upper_bound(header, key, comp); }
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree_algorithms::find(const const_node_ptr&, const KeyType&,KeyNodePtrCompare)
|
||||
//! Additional notes: the found node of the lower bound is splayed. The "splay" parameter which indicated if splaying
|
||||
//! should be performed, it's deprecated and will disappear in future versions.
|
||||
//! Additional notes: the found node of the lower bound is splayed.
|
||||
template<class KeyType, class KeyNodePtrCompare>
|
||||
static node_ptr find
|
||||
(const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool splay = true)
|
||||
(const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp)
|
||||
{
|
||||
if(splay) splay_down(detail::uncast(header), key, comp);
|
||||
node_ptr end = detail::uncast(header);
|
||||
node_ptr y = bstree_algo::lower_bound(header, key, comp);
|
||||
node_ptr r = (y == end || comp(key, y)) ? end : y;
|
||||
return r;
|
||||
splay_down(detail::uncast(header), key, comp);
|
||||
return bstree_algo::find(header, key, comp);
|
||||
}
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree_algorithms::find(const const_node_ptr&, const KeyType&,KeyNodePtrCompare)
|
||||
@ -308,15 +335,14 @@ class splaytree_algorithms
|
||||
{ return bstree_algo::find(header, key, comp); }
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree_algorithms::equal_range(const const_node_ptr&,const KeyType&,KeyNodePtrCompare)
|
||||
//! Additional notes: the first node of the range is splayed. The "splay" parameter which indicated if splaying
|
||||
//! should be performed, it's deprecated and will disappear in future versions.
|
||||
//! Additional notes: the first node of the range is splayed.
|
||||
template<class KeyType, class KeyNodePtrCompare>
|
||||
static std::pair<node_ptr, node_ptr> equal_range
|
||||
(const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool splay = true)
|
||||
(const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp)
|
||||
{
|
||||
//splay_down(detail::uncast(header), key, comp);
|
||||
splay_down(detail::uncast(header), key, comp);
|
||||
std::pair<node_ptr, node_ptr> ret = bstree_algo::equal_range(header, key, comp);
|
||||
if(splay) splay_up(ret.first, detail::uncast(header));
|
||||
//splay_up(ret.first, detail::uncast(header));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -327,17 +353,36 @@ class splaytree_algorithms
|
||||
(const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp)
|
||||
{ return bstree_algo::equal_range(header, key, comp); }
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree_algorithms::lower_bound_range(const const_node_ptr&,const KeyType&,KeyNodePtrCompare)
|
||||
//! Additional notes: the first node of the range is splayed.
|
||||
template<class KeyType, class KeyNodePtrCompare>
|
||||
static std::pair<node_ptr, node_ptr> lower_bound_range
|
||||
(const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp)
|
||||
{
|
||||
splay_down(detail::uncast(header), key, comp);
|
||||
std::pair<node_ptr, node_ptr> ret = bstree_algo::lower_bound_range(header, key, comp);
|
||||
//splay_up(ret.first, detail::uncast(header));
|
||||
return ret;
|
||||
}
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree_algorithms::lower_bound_range(const const_node_ptr&,const KeyType&,KeyNodePtrCompare)
|
||||
//! Additional note: no splaying is performed
|
||||
template<class KeyType, class KeyNodePtrCompare>
|
||||
static std::pair<node_ptr, node_ptr> lower_bound_range
|
||||
(const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp)
|
||||
{ return bstree_algo::lower_bound_range(header, key, comp); }
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree_algorithms::bounded_range(const const_node_ptr&,const KeyType&,const KeyType&,KeyNodePtrCompare,bool,bool)
|
||||
//! Additional notes: the first node of the range is splayed. The "splay" parameter which indicated if splaying
|
||||
//! should be performed, it's deprecated and will disappear in future versions.
|
||||
//! Additional notes: the first node of the range is splayed.
|
||||
template<class KeyType, class KeyNodePtrCompare>
|
||||
static std::pair<node_ptr, node_ptr> bounded_range
|
||||
(const node_ptr & header, const KeyType &lower_key, const KeyType &upper_key, KeyNodePtrCompare comp
|
||||
, bool left_closed, bool right_closed, bool splay = true)
|
||||
, bool left_closed, bool right_closed)
|
||||
{
|
||||
splay_down(detail::uncast(header), lower_key, comp);
|
||||
std::pair<node_ptr, node_ptr> ret =
|
||||
bstree_algo::bounded_range(header, lower_key, upper_key, comp, left_closed, right_closed);
|
||||
if(splay) splay_up(ret.first, detail::uncast(header));
|
||||
//splay_up(ret.first, detail::uncast(header));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -445,6 +490,20 @@ class splaytree_algorithms
|
||||
|
||||
// bottom-up splay, use data_ as parent for n | complexity : logarithmic | exception : nothrow
|
||||
static void splay_up(const node_ptr & node, const node_ptr & header)
|
||||
{ priv_splay_up<true>(node, header); }
|
||||
|
||||
// top-down splay | complexity : logarithmic | exception : strong, note A
|
||||
template<class KeyType, class KeyNodePtrCompare>
|
||||
static node_ptr splay_down(const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool *pfound = 0)
|
||||
{ return priv_splay_down<true>(header, key, comp, pfound); }
|
||||
|
||||
private:
|
||||
|
||||
/// @cond
|
||||
|
||||
// bottom-up splay, use data_ as parent for n | complexity : logarithmic | exception : nothrow
|
||||
template<bool SimpleSplay>
|
||||
static void priv_splay_up(const node_ptr & node, const node_ptr & header)
|
||||
{
|
||||
// If (node == header) do a splay for the right most node instead
|
||||
// this is to boost performance of equal_range/count on equivalent containers in the case
|
||||
@ -470,20 +529,19 @@ class splaytree_algorithms
|
||||
rotate(p);
|
||||
rotate(n);
|
||||
}
|
||||
else{
|
||||
else {
|
||||
// zig-zag
|
||||
rotate(n);
|
||||
rotate(n);
|
||||
if(!SimpleSplay){
|
||||
rotate(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// top-down splay | complexity : logarithmic | exception : strong, note A
|
||||
template<class KeyType, class KeyNodePtrCompare>
|
||||
static node_ptr splay_down(const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp)
|
||||
template<bool SimpleSplay, class KeyType, class KeyNodePtrCompare>
|
||||
static node_ptr priv_splay_down(const node_ptr & header, const KeyType &key, KeyNodePtrCompare comp, bool *pfound = 0)
|
||||
{
|
||||
if(!NodeTraits::get_parent(header))
|
||||
return header;
|
||||
//Most splay tree implementations use a dummy/null node to implement.
|
||||
//this function. This has some problems for a generic library like Intrusive:
|
||||
//
|
||||
@ -494,118 +552,87 @@ class splaytree_algorithms
|
||||
//are not changed when splaying (because the invariants of the tree don't
|
||||
//change) We can back up them, use the header as the null node and
|
||||
//reassign old values after the function has been completed.
|
||||
node_ptr t = NodeTraits::get_parent(header);
|
||||
//Check if tree has a single node
|
||||
if(!NodeTraits::get_left(t) && !NodeTraits::get_right(t))
|
||||
return t;
|
||||
//Backup leftmost/rightmost
|
||||
node_ptr leftmost (NodeTraits::get_left(header));
|
||||
node_ptr rightmost(NodeTraits::get_right(header));
|
||||
{
|
||||
//Anti-exception rollback, recovers the original header node if an exception is thrown.
|
||||
detail::splaydown_rollback<NodeTraits> rollback(&t, header, leftmost, rightmost);
|
||||
node_ptr null_node = header;
|
||||
node_ptr l = null_node;
|
||||
node_ptr r = null_node;
|
||||
node_ptr const old_root = NodeTraits::get_parent(header);
|
||||
node_ptr const leftmost = NodeTraits::get_left(header);
|
||||
node_ptr const rightmost = NodeTraits::get_right(header);
|
||||
if(leftmost == rightmost){ //Empty or unique node
|
||||
if(pfound){
|
||||
*pfound = old_root && !comp(key, old_root) && !comp(old_root, key);
|
||||
}
|
||||
return old_root ? old_root : header;
|
||||
}
|
||||
else{
|
||||
//Initialize "null node" (the header in our case)
|
||||
NodeTraits::set_left (header, node_ptr());
|
||||
NodeTraits::set_right(header, node_ptr());
|
||||
//Class that will backup leftmost/rightmost from header, commit the assemble(),
|
||||
//and will restore leftmost/rightmost to header even if "comp" throws
|
||||
detail::splaydown_assemble_and_fix_header<NodeTraits> commit(old_root, header, leftmost, rightmost);
|
||||
bool found = false;
|
||||
|
||||
for( ;; ){
|
||||
if(comp(key, t)){
|
||||
if(NodeTraits::get_left(t) == node_ptr() )
|
||||
if(comp(key, commit.t_)){
|
||||
node_ptr const t_left = NodeTraits::get_left(commit.t_);
|
||||
if(!t_left)
|
||||
break;
|
||||
if(comp(key, NodeTraits::get_left(t))){
|
||||
t = bstree_algo::rotate_right(t);
|
||||
|
||||
if(NodeTraits::get_left(t) == node_ptr())
|
||||
if(comp(key, t_left)){
|
||||
bstree_algo::rotate_right_no_parent_fix(commit.t_, t_left);
|
||||
commit.t_ = t_left;
|
||||
if( !NodeTraits::get_left(commit.t_) )
|
||||
break;
|
||||
link_right(t, r);
|
||||
}
|
||||
else if(comp(NodeTraits::get_left(t), key)){
|
||||
link_right(t, r);
|
||||
|
||||
if(NodeTraits::get_right(t) == node_ptr() )
|
||||
break;
|
||||
link_left(t, l);
|
||||
link_right(commit.t_, commit.r_);
|
||||
}
|
||||
else{
|
||||
link_right(t, r);
|
||||
link_right(commit.t_, commit.r_);
|
||||
if(!SimpleSplay && comp(t_left, key)){
|
||||
if( !NodeTraits::get_right(commit.t_) )
|
||||
break;
|
||||
link_left(commit.t_, commit.l_);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(comp(t, key)){
|
||||
if(NodeTraits::get_right(t) == node_ptr() )
|
||||
else if(comp(commit.t_, key)){
|
||||
node_ptr const t_right = NodeTraits::get_right(commit.t_);
|
||||
if(!t_right)
|
||||
break;
|
||||
|
||||
if(comp(NodeTraits::get_right(t), key)){
|
||||
t = bstree_algo::rotate_left( t );
|
||||
|
||||
if(NodeTraits::get_right(t) == node_ptr() )
|
||||
if(comp(t_right, key)){
|
||||
bstree_algo::rotate_left_no_parent_fix(commit.t_, t_right);
|
||||
commit.t_ = t_right;
|
||||
if( !NodeTraits::get_right(commit.t_) )
|
||||
break;
|
||||
link_left(t, l);
|
||||
}
|
||||
else if(comp(key, NodeTraits::get_right(t))){
|
||||
link_left(t, l);
|
||||
|
||||
if(NodeTraits::get_left(t) == node_ptr())
|
||||
break;
|
||||
|
||||
link_right(t, r);
|
||||
link_left(commit.t_, commit.l_);
|
||||
}
|
||||
else{
|
||||
link_left(t, l);
|
||||
link_left(commit.t_, commit.l_);
|
||||
if(!SimpleSplay && comp(key, t_right)){
|
||||
if( !NodeTraits::get_left(commit.t_) )
|
||||
break;
|
||||
link_right(commit.t_, commit.r_);
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assemble(t, l, r, null_node);
|
||||
rollback.release();
|
||||
}
|
||||
|
||||
//Now recover the original header except for the
|
||||
//splayed root node.
|
||||
//t is the current root
|
||||
NodeTraits::set_parent(header, t);
|
||||
NodeTraits::set_parent(t, header);
|
||||
//Recover leftmost/rightmost pointers
|
||||
NodeTraits::set_left (header, leftmost);
|
||||
NodeTraits::set_right(header, rightmost);
|
||||
return t;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/// @cond
|
||||
|
||||
// assemble the three sub-trees into new tree pointed to by t | complexity : constant | exception : nothrow
|
||||
static void assemble(const node_ptr &t, const node_ptr & l, const node_ptr & r, const const_node_ptr & null_node )
|
||||
{
|
||||
NodeTraits::set_right(l, NodeTraits::get_left(t));
|
||||
NodeTraits::set_left(r, NodeTraits::get_right(t));
|
||||
|
||||
if(NodeTraits::get_right(l) != node_ptr()){
|
||||
NodeTraits::set_parent(NodeTraits::get_right(l), l);
|
||||
}
|
||||
|
||||
if(NodeTraits::get_left(r) != node_ptr()){
|
||||
NodeTraits::set_parent(NodeTraits::get_left(r), r);
|
||||
}
|
||||
|
||||
NodeTraits::set_left (t, NodeTraits::get_right(null_node));
|
||||
NodeTraits::set_right(t, NodeTraits::get_left(null_node));
|
||||
|
||||
if( NodeTraits::get_left(t) != node_ptr() ){
|
||||
NodeTraits::set_parent(NodeTraits::get_left(t), t);
|
||||
}
|
||||
|
||||
if( NodeTraits::get_right(t) ){
|
||||
NodeTraits::set_parent(NodeTraits::get_right(t), t);
|
||||
//commit.~splaydown_assemble_and_fix_header<NodeTraits>() will first
|
||||
//"assemble()" + link the new root & recover header's leftmost & rightmost
|
||||
if(pfound){
|
||||
*pfound = found;
|
||||
}
|
||||
return commit.t_;
|
||||
}
|
||||
}
|
||||
|
||||
// break link to left child node and attach it to left tree pointed to by l | complexity : constant | exception : nothrow
|
||||
static void link_left(node_ptr & t, node_ptr & l)
|
||||
{
|
||||
//procedure link_left;
|
||||
// t, l, right(l) := right(t), t, t
|
||||
//end link_left
|
||||
NodeTraits::set_right(l, t);
|
||||
NodeTraits::set_parent(t, l);
|
||||
l = t;
|
||||
@ -615,6 +642,9 @@ class splaytree_algorithms
|
||||
// break link to right child node and attach it to right tree pointed to by r | complexity : constant | exception : nothrow
|
||||
static void link_right(node_ptr & t, node_ptr & r)
|
||||
{
|
||||
//procedure link_right;
|
||||
// t, r, left(r) := left(t), t, t
|
||||
//end link_right;
|
||||
NodeTraits::set_left(r, t);
|
||||
NodeTraits::set_parent(t, r);
|
||||
r = t;
|
||||
@ -624,6 +654,9 @@ class splaytree_algorithms
|
||||
// rotate n with its parent | complexity : constant | exception : nothrow
|
||||
static void rotate(const node_ptr & n)
|
||||
{
|
||||
//procedure rotate_left;
|
||||
// t, right(t), left(right(t)) := right(t), left(right(t)), t
|
||||
//end rotate_left;
|
||||
node_ptr p = NodeTraits::get_parent(n);
|
||||
node_ptr g = NodeTraits::get_parent(p);
|
||||
//Test if g is header before breaking tree
|
||||
@ -632,13 +665,13 @@ class splaytree_algorithms
|
||||
|
||||
if(NodeTraits::get_left(p) == n){
|
||||
NodeTraits::set_left(p, NodeTraits::get_right(n));
|
||||
if(NodeTraits::get_left(p) != node_ptr())
|
||||
if(NodeTraits::get_left(p))
|
||||
NodeTraits::set_parent(NodeTraits::get_left(p), p);
|
||||
NodeTraits::set_right(n, p);
|
||||
}
|
||||
else{ // must be ( p->right == n )
|
||||
NodeTraits::set_right(p, NodeTraits::get_left(n));
|
||||
if(NodeTraits::get_right(p) != node_ptr())
|
||||
if(NodeTraits::get_right(p))
|
||||
NodeTraits::set_parent(NodeTraits::get_right(p), p);
|
||||
NodeTraits::set_left(n, p);
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
#define BOOST_INTRUSIVE_TREAP_HPP
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
@ -21,7 +22,6 @@
|
||||
|
||||
#include <boost/intrusive/detail/assert.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
#include <boost/intrusive/bs_set_hook.hpp>
|
||||
#include <boost/intrusive/bstree.hpp>
|
||||
#include <boost/intrusive/detail/tree_node.hpp>
|
||||
@ -72,8 +72,8 @@ template<class ValueTraits, class VoidOrKeyComp, class VoidOrPrioComp, class Siz
|
||||
#endif
|
||||
class treap_impl
|
||||
/// @cond
|
||||
: public bstree_impl<ValueTraits, VoidOrKeyComp, SizeType, ConstantTimeSize, BsTreeAlgorithms>
|
||||
, public detail::ebo_functor_holder
|
||||
: public bstree_impl<ValueTraits, VoidOrKeyComp, SizeType, ConstantTimeSize, BsTreeAlgorithms>
|
||||
, public detail::ebo_functor_holder
|
||||
< typename get_prio
|
||||
< VoidOrPrioComp
|
||||
, typename bstree_impl
|
||||
@ -87,7 +87,6 @@ class treap_impl
|
||||
typedef bstree_impl< ValueTraits, VoidOrKeyComp, SizeType
|
||||
, ConstantTimeSize, BsTreeAlgorithms> tree_type;
|
||||
typedef tree_type implementation_defined;
|
||||
typedef typename tree_type::real_value_traits real_value_traits;
|
||||
typedef get_prio
|
||||
< VoidOrPrioComp
|
||||
, typename tree_type::value_type> get_prio_type;
|
||||
@ -96,7 +95,7 @@ class treap_impl
|
||||
<typename get_prio_type::type> prio_base;
|
||||
|
||||
/// @endcond
|
||||
|
||||
|
||||
typedef typename implementation_defined::pointer pointer;
|
||||
typedef typename implementation_defined::const_pointer const_pointer;
|
||||
typedef typename implementation_defined::value_type value_type;
|
||||
@ -120,7 +119,7 @@ class treap_impl
|
||||
|
||||
static const bool constant_time_size = implementation_defined::constant_time_size;
|
||||
static const bool stateful_value_traits = implementation_defined::stateful_value_traits;
|
||||
static const bool safemode_or_autounlink = is_safe_autounlink<real_value_traits::link_mode>::value;
|
||||
static const bool safemode_or_autounlink = is_safe_autounlink<value_traits::link_mode>::value;
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
@ -217,7 +216,7 @@ class treap_impl
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
iterator top()
|
||||
{ return this->empty() ? this->end() : iterator(node_traits::get_parent(this->tree_type::header_ptr()), this); }
|
||||
{ return this->tree_type::root(); }
|
||||
|
||||
//! <b>Effects</b>: Returns a const_iterator pointing to the highest priority object of the treap..
|
||||
//!
|
||||
@ -233,7 +232,7 @@ class treap_impl
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
const_iterator ctop() const
|
||||
{ return this->empty() ? this->cend() : const_iterator(node_traits::get_parent(this->tree_type::header_ptr()), this); }
|
||||
{ return this->tree_type::root(); }
|
||||
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
//! @copydoc ::boost::intrusive::bstree::rbegin()
|
||||
@ -363,15 +362,15 @@ class treap_impl
|
||||
//! No copy-constructors are called.
|
||||
iterator insert_equal(reference value)
|
||||
{
|
||||
detail::key_nodeptr_comp<value_compare, real_value_traits>
|
||||
key_node_comp(this->value_comp(), &this->get_real_value_traits());
|
||||
detail::key_nodeptr_comp<priority_compare, real_value_traits>
|
||||
key_node_pcomp(this->priv_pcomp(), &this->get_real_value_traits());
|
||||
node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value));
|
||||
detail::key_nodeptr_comp<value_compare, value_traits>
|
||||
key_node_comp(this->value_comp(), &this->get_value_traits());
|
||||
detail::key_nodeptr_comp<priority_compare, value_traits>
|
||||
key_node_pcomp(this->priv_pcomp(), &this->get_value_traits());
|
||||
node_ptr to_insert(this->get_value_traits().to_node_ptr(value));
|
||||
if(safemode_or_autounlink)
|
||||
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert));
|
||||
iterator ret(node_algorithms::insert_equal_upper_bound
|
||||
(this->tree_type::header_ptr(), to_insert, key_node_comp, key_node_pcomp), this->real_value_traits_ptr());
|
||||
(this->tree_type::header_ptr(), to_insert, key_node_comp, key_node_pcomp), this->value_traits_ptr());
|
||||
this->tree_type::sz_traits().increment();
|
||||
return ret;
|
||||
}
|
||||
@ -392,15 +391,15 @@ class treap_impl
|
||||
//! No copy-constructors are called.
|
||||
iterator insert_equal(const_iterator hint, reference value)
|
||||
{
|
||||
detail::key_nodeptr_comp<value_compare, real_value_traits>
|
||||
key_node_comp(this->value_comp(), &this->get_real_value_traits());
|
||||
detail::key_nodeptr_comp<priority_compare, real_value_traits>
|
||||
key_node_pcomp(this->priv_pcomp(), &this->get_real_value_traits());
|
||||
node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value));
|
||||
detail::key_nodeptr_comp<value_compare, value_traits>
|
||||
key_node_comp(this->value_comp(), &this->get_value_traits());
|
||||
detail::key_nodeptr_comp<priority_compare, value_traits>
|
||||
key_node_pcomp(this->priv_pcomp(), &this->get_value_traits());
|
||||
node_ptr to_insert(this->get_value_traits().to_node_ptr(value));
|
||||
if(safemode_or_autounlink)
|
||||
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert));
|
||||
iterator ret (node_algorithms::insert_equal
|
||||
(this->tree_type::header_ptr(), hint.pointed_node(), to_insert, key_node_comp, key_node_pcomp), this->real_value_traits_ptr());
|
||||
(this->tree_type::header_ptr(), hint.pointed_node(), to_insert, key_node_comp, key_node_pcomp), this->value_traits_ptr());
|
||||
this->tree_type::sz_traits().increment();
|
||||
return ret;
|
||||
}
|
||||
@ -540,14 +539,14 @@ class treap_impl
|
||||
( const KeyType &key, KeyValueCompare key_value_comp
|
||||
, KeyValuePrioCompare key_value_pcomp, insert_commit_data &commit_data)
|
||||
{
|
||||
detail::key_nodeptr_comp<KeyValueCompare, real_value_traits>
|
||||
ocomp(key_value_comp, &this->get_real_value_traits());
|
||||
detail::key_nodeptr_comp<KeyValuePrioCompare, real_value_traits>
|
||||
pcomp(key_value_pcomp, &this->get_real_value_traits());
|
||||
detail::key_nodeptr_comp<KeyValueCompare, value_traits>
|
||||
ocomp(key_value_comp, &this->get_value_traits());
|
||||
detail::key_nodeptr_comp<KeyValuePrioCompare, value_traits>
|
||||
pcomp(key_value_pcomp, &this->get_value_traits());
|
||||
std::pair<node_ptr, bool> ret =
|
||||
(node_algorithms::insert_unique_check
|
||||
(this->tree_type::header_ptr(), key, ocomp, pcomp, commit_data));
|
||||
return std::pair<iterator, bool>(iterator(ret.first, this->real_value_traits_ptr()), ret.second);
|
||||
return std::pair<iterator, bool>(iterator(ret.first, this->value_traits_ptr()), ret.second);
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: key_value_comp must be a comparison function that induces
|
||||
@ -592,14 +591,14 @@ class treap_impl
|
||||
, KeyValuePrioCompare key_value_pcomp
|
||||
, insert_commit_data &commit_data)
|
||||
{
|
||||
detail::key_nodeptr_comp<KeyValueCompare, real_value_traits>
|
||||
ocomp(key_value_comp, &this->get_real_value_traits());
|
||||
detail::key_nodeptr_comp<KeyValuePrioCompare, real_value_traits>
|
||||
pcomp(key_value_pcomp, &this->get_real_value_traits());
|
||||
detail::key_nodeptr_comp<KeyValueCompare, value_traits>
|
||||
ocomp(key_value_comp, &this->get_value_traits());
|
||||
detail::key_nodeptr_comp<KeyValuePrioCompare, value_traits>
|
||||
pcomp(key_value_pcomp, &this->get_value_traits());
|
||||
std::pair<node_ptr, bool> ret =
|
||||
(node_algorithms::insert_unique_check
|
||||
(this->tree_type::header_ptr(), hint.pointed_node(), key, ocomp, pcomp, commit_data));
|
||||
return std::pair<iterator, bool>(iterator(ret.first, this->real_value_traits_ptr()), ret.second);
|
||||
return std::pair<iterator, bool>(iterator(ret.first, this->value_traits_ptr()), ret.second);
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: value must be an lvalue of type value_type. commit_data
|
||||
@ -621,12 +620,12 @@ class treap_impl
|
||||
//! erased between the "insert_check" and "insert_commit" calls.
|
||||
iterator insert_unique_commit(reference value, const insert_commit_data &commit_data)
|
||||
{
|
||||
node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value));
|
||||
node_ptr to_insert(this->get_value_traits().to_node_ptr(value));
|
||||
if(safemode_or_autounlink)
|
||||
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert));
|
||||
node_algorithms::insert_unique_commit(this->tree_type::header_ptr(), to_insert, commit_data);
|
||||
this->tree_type::sz_traits().increment();
|
||||
return iterator(to_insert, this->real_value_traits_ptr());
|
||||
return iterator(to_insert, this->value_traits_ptr());
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: value must be an lvalue, "pos" must be
|
||||
@ -645,13 +644,13 @@ class treap_impl
|
||||
//! by advanced users.
|
||||
iterator insert_before(const_iterator pos, reference value)
|
||||
{
|
||||
node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value));
|
||||
node_ptr to_insert(this->get_value_traits().to_node_ptr(value));
|
||||
if(safemode_or_autounlink)
|
||||
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert));
|
||||
detail::key_nodeptr_comp<priority_compare, real_value_traits>
|
||||
pcomp(this->priv_pcomp(), &this->get_real_value_traits());
|
||||
detail::key_nodeptr_comp<priority_compare, value_traits>
|
||||
pcomp(this->priv_pcomp(), &this->get_value_traits());
|
||||
iterator ret (node_algorithms::insert_before
|
||||
(this->tree_type::header_ptr(), pos.pointed_node(), to_insert, pcomp), this->real_value_traits_ptr());
|
||||
(this->tree_type::header_ptr(), pos.pointed_node(), to_insert, pcomp), this->value_traits_ptr());
|
||||
this->tree_type::sz_traits().increment();
|
||||
return ret;
|
||||
}
|
||||
@ -672,11 +671,11 @@ class treap_impl
|
||||
//! by advanced users.
|
||||
void push_back(reference value)
|
||||
{
|
||||
node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value));
|
||||
node_ptr to_insert(this->get_value_traits().to_node_ptr(value));
|
||||
if(safemode_or_autounlink)
|
||||
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert));
|
||||
detail::key_nodeptr_comp<priority_compare, real_value_traits>
|
||||
pcomp(this->priv_pcomp(), &this->get_real_value_traits());
|
||||
detail::key_nodeptr_comp<priority_compare, value_traits>
|
||||
pcomp(this->priv_pcomp(), &this->get_value_traits());
|
||||
node_algorithms::push_back(this->tree_type::header_ptr(), to_insert, pcomp);
|
||||
this->tree_type::sz_traits().increment();
|
||||
}
|
||||
@ -697,11 +696,11 @@ class treap_impl
|
||||
//! by advanced users.
|
||||
void push_front(reference value)
|
||||
{
|
||||
node_ptr to_insert(this->get_real_value_traits().to_node_ptr(value));
|
||||
node_ptr to_insert(this->get_value_traits().to_node_ptr(value));
|
||||
if(safemode_or_autounlink)
|
||||
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert));
|
||||
detail::key_nodeptr_comp<priority_compare, real_value_traits>
|
||||
pcomp(this->priv_pcomp(), &this->get_real_value_traits());
|
||||
detail::key_nodeptr_comp<priority_compare, value_traits>
|
||||
pcomp(this->priv_pcomp(), &this->get_value_traits());
|
||||
node_algorithms::push_front(this->tree_type::header_ptr(), to_insert, pcomp);
|
||||
this->tree_type::sz_traits().increment();
|
||||
}
|
||||
@ -721,8 +720,8 @@ class treap_impl
|
||||
node_ptr to_erase(i.pointed_node());
|
||||
if(safemode_or_autounlink)
|
||||
BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!node_algorithms::unique(to_erase));
|
||||
detail::key_nodeptr_comp<priority_compare, real_value_traits>
|
||||
key_node_pcomp(this->priv_pcomp(), &this->get_real_value_traits());
|
||||
detail::key_nodeptr_comp<priority_compare, value_traits>
|
||||
key_node_pcomp(this->priv_pcomp(), &this->get_value_traits());
|
||||
node_algorithms::erase(this->tree_type::header_ptr(), to_erase, key_node_pcomp);
|
||||
this->tree_type::sz_traits().decrement();
|
||||
if(safemode_or_autounlink)
|
||||
@ -796,7 +795,7 @@ class treap_impl
|
||||
{
|
||||
node_ptr to_erase(i.pointed_node());
|
||||
iterator ret(this->erase(i));
|
||||
disposer(this->get_real_value_traits().to_value_ptr(to_erase));
|
||||
disposer(this->get_value_traits().to_value_ptr(to_erase));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -898,7 +897,7 @@ class treap_impl
|
||||
void clear_and_dispose(Disposer disposer)
|
||||
{
|
||||
node_algorithms::clear_and_dispose(this->tree_type::header_ptr()
|
||||
, detail::node_disposer<Disposer, real_value_traits, TreapAlgorithms>(disposer, &this->get_real_value_traits()));
|
||||
, detail::node_disposer<Disposer, value_traits, TreapAlgorithms>(disposer, &this->get_value_traits()));
|
||||
node_algorithms::init_header(this->tree_type::header_ptr());
|
||||
this->tree_type::sz_traits().set_size(0);
|
||||
}
|
||||
@ -910,7 +909,7 @@ class treap_impl
|
||||
//! @copydoc ::boost::intrusive::bstree::count(const KeyType&,KeyValueCompare)const
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
size_type count(const KeyType& key, KeyValueCompare comp) const;
|
||||
|
||||
|
||||
//! @copydoc ::boost::intrusive::bstree::lower_bound(const_reference)
|
||||
iterator lower_bound(const_reference value);
|
||||
|
||||
@ -1120,14 +1119,13 @@ class treap
|
||||
typedef typename Base::value_compare value_compare;
|
||||
typedef typename Base::priority_compare priority_compare;
|
||||
typedef typename Base::value_traits value_traits;
|
||||
typedef typename Base::real_value_traits real_value_traits;
|
||||
typedef typename Base::iterator iterator;
|
||||
typedef typename Base::const_iterator const_iterator;
|
||||
typedef typename Base::reverse_iterator reverse_iterator;
|
||||
typedef typename Base::const_reverse_iterator const_reverse_iterator;
|
||||
|
||||
//Assert if passed value traits are compatible with the type
|
||||
BOOST_STATIC_ASSERT((detail::is_same<typename real_value_traits::value_type, T>::value));
|
||||
BOOST_STATIC_ASSERT((detail::is_same<typename value_traits::value_type, T>::value));
|
||||
|
||||
explicit treap( const value_compare &cmp = value_compare()
|
||||
, const priority_compare &pcmp = priority_compare()
|
||||
|
@ -14,9 +14,9 @@
|
||||
#define BOOST_INTRUSIVE_TREAP_ALGORITHMS_HPP
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
|
||||
#include <boost/intrusive/detail/assert.hpp>
|
||||
#include <boost/intrusive/pointer_traits.hpp>
|
||||
@ -110,16 +110,17 @@ class treap_algorithms
|
||||
|
||||
static void rotate_up_n(const node_ptr header, const node_ptr p, std::size_t n)
|
||||
{
|
||||
for( node_ptr p_parent = NodeTraits::get_parent(p)
|
||||
; n--
|
||||
; p_parent = NodeTraits::get_parent(p)){
|
||||
//Check if left child
|
||||
if(p == NodeTraits::get_left(p_parent)){
|
||||
bstree_algo::rotate_right(p_parent, header);
|
||||
node_ptr p_parent(NodeTraits::get_parent(p));
|
||||
node_ptr p_grandparent(NodeTraits::get_parent(p_parent));
|
||||
while(n--){
|
||||
if(p == NodeTraits::get_left(p_parent)){ //p is left child
|
||||
bstree_algo::rotate_right(p_parent, p, p_grandparent, header);
|
||||
}
|
||||
else{ //Right child
|
||||
bstree_algo::rotate_left(p_parent, header);
|
||||
else{ //p is right child
|
||||
bstree_algo::rotate_left(p_parent, p, p_grandparent, header);
|
||||
}
|
||||
p_parent = p_grandparent;
|
||||
p_grandparent = NodeTraits::get_parent(p_parent);
|
||||
}
|
||||
}
|
||||
|
||||
@ -248,6 +249,7 @@ class treap_algorithms
|
||||
//! @copydoc ::boost::intrusive::bstree_algorithms::count(const const_node_ptr&,const KeyType&,KeyNodePtrCompare)
|
||||
template<class KeyType, class KeyNodePtrCompare>
|
||||
static std::size_t count(const const_node_ptr & header, const KeyType &key, KeyNodePtrCompare comp);
|
||||
|
||||
#endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
|
||||
//! <b>Requires</b>: "h" must be the header node of a tree.
|
||||
@ -525,7 +527,7 @@ class treap_algorithms
|
||||
(const node_ptr & header, const node_ptr & new_node, const insert_commit_data &commit_data)
|
||||
{
|
||||
bstree_algo::insert_unique_commit(header, new_node, commit_data);
|
||||
rebalance_after_insertion_commit(header, new_node, commit_data.rotations);
|
||||
rotate_up_n(header, new_node, commit_data.rotations);
|
||||
}
|
||||
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
@ -546,11 +548,12 @@ class treap_algorithms
|
||||
node_ptr z_left = NodeTraits::get_left(z);
|
||||
node_ptr z_right = NodeTraits::get_right(z);
|
||||
while(z_left || z_right){
|
||||
const node_ptr z_parent(NodeTraits::get_parent(z));
|
||||
if(!z_right || (z_left && pcomp(z_left, z_right))){
|
||||
bstree_algo::rotate_right(z, header);
|
||||
bstree_algo::rotate_right(z, z_left, z_parent, header);
|
||||
}
|
||||
else{
|
||||
bstree_algo::rotate_left(z, header);
|
||||
bstree_algo::rotate_left(z, z_right, z_parent, header);
|
||||
}
|
||||
++n;
|
||||
z_left = NodeTraits::get_left(z);
|
||||
@ -566,10 +569,9 @@ class treap_algorithms
|
||||
rebalance_after_insertion_check(h, commit_data.node, new_node, pcomp, commit_data.rotations);
|
||||
//No-throw
|
||||
bstree_algo::insert_unique_commit(h, new_node, commit_data);
|
||||
rebalance_after_insertion_commit(h, new_node, commit_data.rotations);
|
||||
rotate_up_n(h, new_node, commit_data.rotations);
|
||||
}
|
||||
|
||||
|
||||
template<class Key, class KeyNodePriorityCompare>
|
||||
static void rebalance_after_insertion_check
|
||||
(const const_node_ptr &header, const const_node_ptr & up, const Key &k
|
||||
@ -586,22 +588,6 @@ class treap_algorithms
|
||||
num_rotations = n;
|
||||
}
|
||||
|
||||
static void rebalance_after_insertion_commit(const node_ptr & header, const node_ptr & p, std::size_t n)
|
||||
{
|
||||
// Now execute n rotations
|
||||
for( node_ptr p_parent = NodeTraits::get_parent(p)
|
||||
; n--
|
||||
; p_parent = NodeTraits::get_parent(p)){
|
||||
//Check if left child
|
||||
if(p == NodeTraits::get_left(p_parent)){
|
||||
bstree_algo::rotate_right(p_parent, header);
|
||||
}
|
||||
else{ //Right child
|
||||
bstree_algo::rotate_left(p_parent, header);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class NodePtrPriorityCompare>
|
||||
static bool check_invariant(const const_node_ptr & header, NodePtrPriorityCompare pcomp)
|
||||
{
|
||||
|
@ -44,6 +44,7 @@ class treap_set_impl
|
||||
#endif
|
||||
{
|
||||
/// @cond
|
||||
public:
|
||||
typedef treap_impl<ValueTraits, VoidOrKeyComp, VoidOrPrioComp, SizeType, ConstantTimeSize> tree_type;
|
||||
BOOST_MOVABLE_BUT_NOT_COPYABLE(treap_set_impl)
|
||||
|
||||
@ -291,13 +292,19 @@ class treap_set_impl
|
||||
template<class Disposer>
|
||||
void clear_and_dispose(Disposer disposer);
|
||||
|
||||
#endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
|
||||
//! @copydoc ::boost::intrusive::treap::count(const_reference)const
|
||||
size_type count(const_reference value) const;
|
||||
size_type count(const_reference value) const
|
||||
{ return static_cast<size_type>(this->tree_type::find(value) != this->tree_type::cend()); }
|
||||
|
||||
//! @copydoc ::boost::intrusive::treap::count(const KeyType&,KeyValueCompare)const
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
size_type count(const KeyType& key, KeyValueCompare comp) const;
|
||||
|
||||
size_type count(const KeyType& key, KeyValueCompare comp) const
|
||||
{ return static_cast<size_type>(this->tree_type::find(key, comp) != this->tree_type::cend()); }
|
||||
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
|
||||
//! @copydoc ::boost::intrusive::treap::lower_bound(const_reference)
|
||||
iterator lower_bound(const_reference value);
|
||||
|
||||
@ -340,21 +347,29 @@ class treap_set_impl
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
const_iterator find(const KeyType& key, KeyValueCompare comp) const;
|
||||
|
||||
//! @copydoc ::boost::intrusive::treap::equal_range(const_reference)
|
||||
std::pair<iterator,iterator> equal_range(const_reference value);
|
||||
#endif // #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
|
||||
//! @copydoc ::boost::intrusive::treap::equal_range(const KeyType&,KeyValueCompare)
|
||||
//! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference)
|
||||
std::pair<iterator,iterator> equal_range(const_reference value)
|
||||
{ return this->tree_type::lower_bound_range(value); }
|
||||
|
||||
//! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare)
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
std::pair<iterator,iterator> equal_range(const KeyType& key, KeyValueCompare comp);
|
||||
std::pair<iterator,iterator> equal_range(const KeyType& key, KeyValueCompare comp)
|
||||
{ return this->tree_type::lower_bound_range(key, comp); }
|
||||
|
||||
//! @copydoc ::boost::intrusive::treap::equal_range(const_reference)const
|
||||
//! @copydoc ::boost::intrusive::rbtree::equal_range(const_reference)const
|
||||
std::pair<const_iterator, const_iterator>
|
||||
equal_range(const_reference value) const;
|
||||
equal_range(const_reference value) const
|
||||
{ return this->tree_type::lower_bound_range(value); }
|
||||
|
||||
//! @copydoc ::boost::intrusive::treap::equal_range(const KeyType&,KeyValueCompare)const
|
||||
//! @copydoc ::boost::intrusive::rbtree::equal_range(const KeyType&,KeyValueCompare)const
|
||||
template<class KeyType, class KeyValueCompare>
|
||||
std::pair<const_iterator, const_iterator>
|
||||
equal_range(const KeyType& key, KeyValueCompare comp) const;
|
||||
equal_range(const KeyType& key, KeyValueCompare comp) const
|
||||
{ return this->tree_type::lower_bound_range(key, comp); }
|
||||
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
|
||||
//! @copydoc ::boost::intrusive::treap::bounded_range(const_reference,const_reference,bool,bool)
|
||||
std::pair<iterator,iterator> bounded_range
|
||||
|
@ -13,6 +13,9 @@
|
||||
#ifndef BOOST_INTRUSIVE_TRIVIAL_VALUE_TRAITS_HPP
|
||||
#define BOOST_INTRUSIVE_TRIVIAL_VALUE_TRAITS_HPP
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/intrusive_fwd.hpp>
|
||||
|
||||
#include <boost/intrusive/link_mode.hpp>
|
||||
#include <boost/intrusive/pointer_traits.hpp>
|
||||
|
||||
@ -22,7 +25,11 @@ namespace intrusive {
|
||||
//!This value traits template is used to create value traits
|
||||
//!from user defined node traits where value_traits::value_type and
|
||||
//!node_traits::node should be equal
|
||||
template<class NodeTraits, link_mode_type LinkMode = normal_link>
|
||||
template<class NodeTraits, link_mode_type LinkMode
|
||||
#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
||||
= safe_link
|
||||
#endif
|
||||
>
|
||||
struct trivial_value_traits
|
||||
{
|
||||
typedef NodeTraits node_traits;
|
||||
@ -43,4 +50,6 @@ struct trivial_value_traits
|
||||
} //namespace intrusive
|
||||
} //namespace boost
|
||||
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTRUSIVE_TRIVIAL_VALUE_TRAITS_HPP
|
||||
|
@ -1029,15 +1029,15 @@ struct make_unordered_set
|
||||
typedef typename detail::get_value_traits
|
||||
<T, typename packed_options::proto_value_traits>::type value_traits;
|
||||
|
||||
typedef typename make_real_bucket_traits
|
||||
<T, true, packed_options>::type real_bucket_traits;
|
||||
typedef typename make_bucket_traits
|
||||
<T, true, packed_options>::type bucket_traits;
|
||||
|
||||
typedef unordered_set_impl
|
||||
< value_traits
|
||||
, typename packed_options::hash
|
||||
, typename packed_options::equal
|
||||
, typename packed_options::size_type
|
||||
, real_bucket_traits
|
||||
, bucket_traits
|
||||
, (std::size_t(true)*hash_bool_flags::unique_keys_pos)
|
||||
| (std::size_t(packed_options::constant_time_size)*hash_bool_flags::constant_time_size_pos)
|
||||
| (std::size_t(packed_options::power_2_buckets)*hash_bool_flags::power_2_buckets_pos)
|
||||
@ -2066,15 +2066,15 @@ struct make_unordered_multiset
|
||||
typedef typename detail::get_value_traits
|
||||
<T, typename packed_options::proto_value_traits>::type value_traits;
|
||||
|
||||
typedef typename make_real_bucket_traits
|
||||
<T, true, packed_options>::type real_bucket_traits;
|
||||
typedef typename make_bucket_traits
|
||||
<T, true, packed_options>::type bucket_traits;
|
||||
|
||||
typedef unordered_multiset_impl
|
||||
< value_traits
|
||||
, typename packed_options::hash
|
||||
, typename packed_options::equal
|
||||
, typename packed_options::size_type
|
||||
, real_bucket_traits
|
||||
, bucket_traits
|
||||
, (std::size_t(false)*hash_bool_flags::unique_keys_pos)
|
||||
| (std::size_t(packed_options::constant_time_size)*hash_bool_flags::constant_time_size_pos)
|
||||
| (std::size_t(packed_options::power_2_buckets)*hash_bool_flags::power_2_buckets_pos)
|
||||
|
@ -207,7 +207,7 @@ struct make_unordered_set_base_hook
|
||||
//! unique tag.
|
||||
//!
|
||||
//! \c void_pointer<> is the pointer type that will be used internally in the hook
|
||||
//! and the the container configured to use this hook.
|
||||
//! and the container configured to use this hook.
|
||||
//!
|
||||
//! \c link_mode<> will specify the linking mode of the hook (\c normal_link,
|
||||
//! \c auto_unlink or \c safe_link).
|
||||
@ -341,7 +341,7 @@ struct make_unordered_set_member_hook
|
||||
//! \c link_mode<> and \c store_hash<>.
|
||||
//!
|
||||
//! \c void_pointer<> is the pointer type that will be used internally in the hook
|
||||
//! and the the container configured to use this hook.
|
||||
//! and the container configured to use this hook.
|
||||
//!
|
||||
//! \c link_mode<> will specify the linking mode of the hook (\c normal_link,
|
||||
//! \c auto_unlink or \c safe_link).
|
||||
|
@ -31,10 +31,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "custom_bucket_traits", "cus
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "external_value_traits", "external_value_traits\external_value_traits.vcproj", "{97B69A72-B9D3-7389-17FB-74612F4A9543}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "splay_multiset", "splay_multiset\splay_multiset.vcproj", "{01E70176-B6C5-BF47-2C91-A949077BA323}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
@ -115,6 +111,14 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "scary_iterators", "scary_it
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pack_options", "pack_options\pack_options.vcproj", "{77F4139B-281B-F694-7CB1-3495467B4D35}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "container_size_test", "container_size_test\container_size_test.vcproj", "{9E721E26-45AF-192C-AD67-A4CC7D096497}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfiguration) = preSolution
|
||||
Debug = Debug
|
||||
@ -155,10 +159,6 @@ Global
|
||||
{31C77B84-0B2C-9481-CB81-27A149F33825}.Debug.Build.0 = Debug|Win32
|
||||
{31C77B84-0B2C-9481-CB81-27A149F33825}.Release.ActiveCfg = Release|Win32
|
||||
{31C77B84-0B2C-9481-CB81-27A149F33825}.Release.Build.0 = Release|Win32
|
||||
{97B69A72-B9D3-7389-17FB-74612F4A9543}.Debug.ActiveCfg = Debug|Win32
|
||||
{97B69A72-B9D3-7389-17FB-74612F4A9543}.Debug.Build.0 = Debug|Win32
|
||||
{97B69A72-B9D3-7389-17FB-74612F4A9543}.Release.ActiveCfg = Release|Win32
|
||||
{97B69A72-B9D3-7389-17FB-74612F4A9543}.Release.Build.0 = Release|Win32
|
||||
{01E70176-B6C5-BF47-2C91-A949077BA323}.Debug.ActiveCfg = Debug|Win32
|
||||
{01E70176-B6C5-BF47-2C91-A949077BA323}.Debug.Build.0 = Debug|Win32
|
||||
{01E70176-B6C5-BF47-2C91-A949077BA323}.Release.ActiveCfg = Release|Win32
|
||||
@ -239,6 +239,14 @@ Global
|
||||
{7679B41B-C1C5-FA34-9614-3547B3140346}.Debug.Build.0 = Debug|Win32
|
||||
{7679B41B-C1C5-FA34-9614-3547B3140346}.Release.ActiveCfg = Release|Win32
|
||||
{7679B41B-C1C5-FA34-9614-3547B3140346}.Release.Build.0 = Release|Win32
|
||||
{77F4139B-281B-F694-7CB1-3495467B4D35}.Debug.ActiveCfg = Debug|Win32
|
||||
{77F4139B-281B-F694-7CB1-3495467B4D35}.Debug.Build.0 = Debug|Win32
|
||||
{77F4139B-281B-F694-7CB1-3495467B4D35}.Release.ActiveCfg = Release|Win32
|
||||
{77F4139B-281B-F694-7CB1-3495467B4D35}.Release.Build.0 = Release|Win32
|
||||
{9E721E26-45AF-192C-AD67-A4CC7D096497}.Debug.ActiveCfg = Debug|Win32
|
||||
{9E721E26-45AF-192C-AD67-A4CC7D096497}.Debug.Build.0 = Debug|Win32
|
||||
{9E721E26-45AF-192C-AD67-A4CC7D096497}.Release.ActiveCfg = Release|Win32
|
||||
{9E721E26-45AF-192C-AD67-A4CC7D096497}.Release.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
EndGlobalSection
|
||||
|
@ -157,6 +157,9 @@
|
||||
<File
|
||||
RelativePath="..\..\..\..\..\boost\intrusive\options.hpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\..\..\boost\intrusive\pack_options.hpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\..\..\boost\intrusive\parent_from_member.hpp">
|
||||
</File>
|
||||
@ -361,9 +364,6 @@
|
||||
<File
|
||||
RelativePath="..\..\..\example\doc_erasing_and_disposing.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\example\doc_external_value_traits.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\example\doc_function_hooks.cpp">
|
||||
</File>
|
||||
|
@ -1,133 +0,0 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="external_value_traits"
|
||||
ProjectGUID="{97B69A72-B9D3-7389-17FB-74612F4A9543}"
|
||||
RootNamespace="external_value_traits"
|
||||
Keyword="Win32Proj">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="Debug"
|
||||
IntermediateDirectory="Debug"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="../../../../../"
|
||||
PreprocessorDefinitions="BOOST_DATE_TIME_NO_LIB"
|
||||
GeneratePreprocessedFile="0"
|
||||
KeepComments="FALSE"
|
||||
MinimalRebuild="TRUE"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="5"
|
||||
DisableLanguageExtensions="FALSE"
|
||||
TreatWChar_tAsBuiltInType="TRUE"
|
||||
ForceConformanceInForLoopScope="TRUE"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="4"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="4"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)/external_value_traits.exe"
|
||||
LinkIncremental="2"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="$(OutDir)/external_value_traits.pdb"
|
||||
GenerateMapFile="TRUE"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="Release"
|
||||
IntermediateDirectory="Release"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="../../../../../"
|
||||
PreprocessorDefinitions="BOOST_DATE_TIME_NO_LIB"
|
||||
RuntimeLibrary="4"
|
||||
DisableLanguageExtensions="FALSE"
|
||||
ForceConformanceInForLoopScope="TRUE"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)/external_value_traits.exe"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="TRUE"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{7FAFEA31-6364-FB35-16A6-77AF315C236A}">
|
||||
<File
|
||||
RelativePath="..\..\..\test\external_value_traits_test.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
@ -21,6 +21,7 @@
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="../../../../../"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
||||
GeneratePreprocessedFile="0"
|
||||
MinimalRebuild="TRUE"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="5"
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include<boost/intrusive/detail/utilities.hpp>
|
||||
#include<boost/intrusive/detail/mpl.hpp>
|
||||
#include<boost/static_assert.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
@ -28,7 +29,7 @@ class delete_disposer
|
||||
void operator()(Pointer p)
|
||||
{
|
||||
typedef typename std::iterator_traits<Pointer>::value_type value_type;
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(( detail::is_same<T, value_type>::value ));
|
||||
BOOST_STATIC_ASSERT(( detail::is_same<T, value_type>::value ));
|
||||
delete boost::intrusive::detail::to_raw_pointer(p);
|
||||
}
|
||||
};
|
||||
|
@ -1,241 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2007-2013
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/intrusive for documentation.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#include <boost/intrusive/list.hpp>
|
||||
#include <boost/intrusive/slist.hpp>
|
||||
#include <boost/intrusive/rbtree.hpp>
|
||||
#include <boost/intrusive/hashtable.hpp>
|
||||
#include <boost/intrusive/pointer_traits.hpp>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
using namespace boost::intrusive;
|
||||
|
||||
class MyClass
|
||||
{
|
||||
public:
|
||||
int int_;
|
||||
|
||||
MyClass(int i = 0)
|
||||
: int_(i)
|
||||
{}
|
||||
friend bool operator > (const MyClass &l, const MyClass &r)
|
||||
{ return l.int_ > r.int_; }
|
||||
friend bool operator == (const MyClass &l, const MyClass &r)
|
||||
{ return l.int_ == r.int_; }
|
||||
friend std::size_t hash_value(const MyClass &v)
|
||||
{ return boost::hash_value(v.int_); }
|
||||
};
|
||||
|
||||
const int NumElements = 100;
|
||||
|
||||
template<class NodeTraits>
|
||||
struct external_traits
|
||||
{
|
||||
typedef NodeTraits node_traits;
|
||||
typedef typename node_traits::node node;
|
||||
typedef typename node_traits::node_ptr node_ptr;
|
||||
typedef typename node_traits::const_node_ptr const_node_ptr;
|
||||
typedef MyClass value_type;
|
||||
typedef typename pointer_traits<node_ptr>::
|
||||
template rebind_pointer<MyClass>::type pointer;
|
||||
typedef typename pointer_traits<node_ptr>::
|
||||
template rebind_pointer
|
||||
<const MyClass>::type const_pointer;
|
||||
static const link_mode_type link_mode = normal_link;
|
||||
|
||||
external_traits(pointer values, std::size_t NumElem)
|
||||
: values_(values), node_array_(NumElem)
|
||||
{}
|
||||
|
||||
node_ptr to_node_ptr (value_type &value)
|
||||
{ return (&node_array_[0]) + (&value - values_); }
|
||||
|
||||
const_node_ptr to_node_ptr (const value_type &value) const
|
||||
{ return &node_array_[0] + (&value - values_); }
|
||||
|
||||
pointer to_value_ptr(node_ptr n)
|
||||
{ return values_ + (n - &node_array_[0]); }
|
||||
|
||||
const_pointer to_value_ptr(const_node_ptr n) const
|
||||
{ return values_ + (n - &node_array_[0]); }
|
||||
|
||||
pointer values_;
|
||||
std::vector<node> node_array_;
|
||||
};
|
||||
|
||||
template<class NodeTraits>
|
||||
struct value_traits_proxy;
|
||||
|
||||
template<class T>
|
||||
struct traits_holder
|
||||
: public T
|
||||
{};
|
||||
|
||||
typedef value_traits_proxy<list_node_traits<void*> > list_value_traits_proxy;
|
||||
typedef value_traits_proxy<slist_node_traits<void*> > slist_value_traits_proxy;
|
||||
typedef value_traits_proxy<rbtree_node_traits<void*> > rbtree_value_traits_proxy;
|
||||
typedef value_traits_proxy<traits_holder<slist_node_traits<void*> > > hash_value_traits_proxy;
|
||||
|
||||
struct uset_bucket_traits
|
||||
{
|
||||
private:
|
||||
typedef unordered_bucket<value_traits<external_traits
|
||||
<traits_holder<slist_node_traits<void*> > > > >::type bucket_type;
|
||||
|
||||
//Non-copyable
|
||||
uset_bucket_traits(const uset_bucket_traits &other);
|
||||
uset_bucket_traits & operator=(const uset_bucket_traits &other);
|
||||
|
||||
public:
|
||||
static const std::size_t NumBuckets = 100;
|
||||
|
||||
uset_bucket_traits(){}
|
||||
|
||||
bucket_type * bucket_begin() const
|
||||
{ return buckets_; }
|
||||
|
||||
std::size_t bucket_count() const
|
||||
{ return NumBuckets; }
|
||||
|
||||
mutable bucket_type buckets_[NumBuckets];
|
||||
};
|
||||
|
||||
struct bucket_traits_proxy
|
||||
{
|
||||
static const bool external_bucket_traits = true;
|
||||
typedef uset_bucket_traits bucket_traits;
|
||||
|
||||
template<class Container>
|
||||
bucket_traits &get_bucket_traits(Container &cont);
|
||||
|
||||
template<class Container>
|
||||
const bucket_traits &get_bucket_traits(const Container &cont) const;
|
||||
};
|
||||
|
||||
//Define a list that will store MyClass using the external hook
|
||||
typedef list<MyClass, value_traits<list_value_traits_proxy> > List;
|
||||
//Define a slist that will store MyClass using the external hook
|
||||
typedef slist<MyClass, value_traits<slist_value_traits_proxy> > Slist;
|
||||
//Define a rbtree that will store MyClass using the external hook
|
||||
typedef rbtree< MyClass
|
||||
, value_traits<rbtree_value_traits_proxy>
|
||||
, compare<std::greater<MyClass> > > Rbtree;
|
||||
//Define a hashtable that will store MyClass using the external hook
|
||||
|
||||
typedef hashtable< MyClass
|
||||
, value_traits<hash_value_traits_proxy>
|
||||
, bucket_traits<bucket_traits_proxy>
|
||||
> Hash;
|
||||
|
||||
template<class NodeTraits>
|
||||
struct value_traits_proxy
|
||||
{
|
||||
static const bool external_value_traits = true;
|
||||
typedef external_traits<NodeTraits> value_traits;
|
||||
|
||||
template<class Container>
|
||||
const value_traits &get_value_traits(const Container &cont) const;
|
||||
|
||||
template<class Container>
|
||||
value_traits &get_value_traits(Container &cont);
|
||||
};
|
||||
|
||||
struct ContainerHolder
|
||||
: public uset_bucket_traits
|
||||
, public List
|
||||
, public external_traits<list_node_traits<void*> >
|
||||
, public Slist
|
||||
, public external_traits<slist_node_traits<void*> >
|
||||
, public Rbtree
|
||||
, public external_traits<rbtree_node_traits<void*> >
|
||||
, public Hash
|
||||
, public external_traits<traits_holder<slist_node_traits<void*> > >
|
||||
{
|
||||
static const std::size_t NumBucket = 100;
|
||||
ContainerHolder(MyClass *values, std::size_t num_elem)
|
||||
: uset_bucket_traits()
|
||||
, List()
|
||||
, external_traits<list_node_traits<void*> >(values, num_elem)
|
||||
, Slist()
|
||||
, external_traits<slist_node_traits<void*> >(values, num_elem)
|
||||
, Rbtree()
|
||||
, external_traits<rbtree_node_traits<void*> >(values, num_elem)
|
||||
, Hash(Hash::bucket_traits())
|
||||
, external_traits<traits_holder<slist_node_traits<void*> > >(values, num_elem)
|
||||
{}
|
||||
};
|
||||
|
||||
template<class NodeTraits>
|
||||
template<class Container>
|
||||
typename value_traits_proxy<NodeTraits>::value_traits &
|
||||
value_traits_proxy<NodeTraits>::get_value_traits(Container &cont)
|
||||
{ return static_cast<value_traits&>(static_cast<ContainerHolder&>(cont)); }
|
||||
|
||||
template<class NodeTraits>
|
||||
template<class Container>
|
||||
const typename value_traits_proxy<NodeTraits>::value_traits &
|
||||
value_traits_proxy<NodeTraits>::get_value_traits(const Container &cont) const
|
||||
{ return static_cast<const value_traits&>(static_cast<const ContainerHolder&>(cont)); }
|
||||
|
||||
template<class Container>
|
||||
typename bucket_traits_proxy::bucket_traits &
|
||||
bucket_traits_proxy::get_bucket_traits(Container &cont)
|
||||
{ return static_cast<bucket_traits&>(static_cast<ContainerHolder&>(cont)); }
|
||||
|
||||
template<class Container>
|
||||
const typename bucket_traits_proxy::bucket_traits &
|
||||
bucket_traits_proxy::get_bucket_traits(const Container &cont) const
|
||||
{ return static_cast<const bucket_traits&>(static_cast<const ContainerHolder&>(cont)); }
|
||||
|
||||
int main()
|
||||
{
|
||||
MyClass values [NumElements];
|
||||
//Create several MyClass objects, each one with a different value
|
||||
for(int i = 0; i < NumElements; ++i)
|
||||
values[i].int_ = i;
|
||||
|
||||
ContainerHolder cont_holder(values, NumElements);
|
||||
List &my_list = static_cast<List &> (cont_holder);
|
||||
Slist &my_slist = static_cast<Slist &> (cont_holder);
|
||||
Rbtree &my_rbtree = static_cast<Rbtree &> (cont_holder);
|
||||
Hash &my_hash = static_cast<Hash &> (cont_holder);
|
||||
|
||||
//Now insert them in containers
|
||||
for(MyClass * it(&values[0]), *itend(&values[NumElements])
|
||||
; it != itend; ++it){
|
||||
my_list.push_front(*it);
|
||||
my_slist.push_front(*it);
|
||||
my_rbtree.insert_unique(*it);
|
||||
my_hash.insert_unique(*it);
|
||||
}
|
||||
|
||||
//Now test containers
|
||||
{
|
||||
List::const_iterator list_it (my_list.cbegin());
|
||||
Slist::const_iterator slist_it (my_slist.cbegin());
|
||||
Rbtree::const_iterator rbtree_it (my_rbtree.cbegin());
|
||||
Hash::const_iterator hash_it (my_hash.cbegin());
|
||||
MyClass *it_val(&values[NumElements] - 1), *it_rbeg_val(&values[0]-1);
|
||||
|
||||
//Test inserted objects
|
||||
for(; it_val != it_rbeg_val; --it_val, ++list_it, ++slist_it, ++rbtree_it){
|
||||
if(&*list_it != &*it_val) return 1;
|
||||
if(&*slist_it != &*it_val) return 1;
|
||||
if(&*rbtree_it != &*it_val) return 1;
|
||||
hash_it = my_hash.find(*it_val);
|
||||
if(hash_it == my_hash.cend() || &*hash_it != &*it_val)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -68,7 +68,7 @@ class has_member_function_named_func
|
||||
|
||||
}}}
|
||||
|
||||
#if !defined(BOOST_CONTAINER_PERFECT_FORWARDING)
|
||||
#if !defined(BOOST_INTRUSIVE_PERFECT_FORWARDING)
|
||||
|
||||
namespace boost{
|
||||
namespace intrusive{
|
||||
@ -147,7 +147,7 @@ class has_member_function_named_func
|
||||
<Fun, true , void , void , void>
|
||||
{
|
||||
template<class U>
|
||||
static decltype(boost::move_detail::declval<Fun>().func(), has_member_function_callable_with::yes_type()) Test(Fun* f);
|
||||
static decltype(boost::move_detail::declval<U>().func(), has_member_function_callable_with::yes_type()) Test(U* f);
|
||||
|
||||
template<class U>
|
||||
static has_member_function_callable_with::no_type Test(...);
|
||||
@ -259,7 +259,7 @@ class has_member_function_named_func
|
||||
|
||||
}}}
|
||||
|
||||
#else
|
||||
#else //#if !defined(BOOST_INTRUSIVE_PERFECT_FORWARDING)
|
||||
|
||||
namespace boost{
|
||||
namespace intrusive{
|
||||
@ -283,6 +283,7 @@ class has_member_function_named_func
|
||||
namespace intrusive{
|
||||
namespace intrusive_detail{
|
||||
|
||||
#ifdef BOOST_NO_CXX11_DECLTYPE
|
||||
template<class F, std::size_t N = sizeof(boost::move_detail::declval<F>().func(), 0)>
|
||||
struct zeroarg_checker_func
|
||||
{
|
||||
@ -299,12 +300,19 @@ class has_member_function_named_func
|
||||
zeroarg_checker_func(int);
|
||||
};
|
||||
|
||||
#endif //BOOST_NO_CXX11_DECLTYPE
|
||||
|
||||
template<typename Fun>
|
||||
struct has_member_function_callable_with_func_impl
|
||||
<Fun, true>
|
||||
{
|
||||
template<class U>
|
||||
static zeroarg_checker_func<U> Test(zeroarg_checker_func<U>*);
|
||||
#ifndef BOOST_NO_CXX11_DECLTYPE
|
||||
template<class U, class V = decltype(boost::move_detail::declval<U>().func()) >
|
||||
static boost_intrusive_has_member_function_callable_with::yes_type Test(U*);
|
||||
#else
|
||||
template<class U>
|
||||
static zeroarg_checker_func<U> Test(zeroarg_checker_func<U>*);
|
||||
#endif
|
||||
|
||||
template <class U>
|
||||
static has_member_function_callable_with::no_type Test(...);
|
||||
@ -356,7 +364,7 @@ class has_member_function_named_func
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
#endif //#if !defined(BOOST_INTRUSIVE_PERFECT_FORWARDING)
|
||||
|
||||
struct functor
|
||||
{
|
||||
|
@ -183,12 +183,6 @@ int main()
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(detail::is_same<make_splay_set_base_hook<void_pointer<void*>, link_mode<safe_link> >::type
|
||||
,make_splay_set_base_hook<>::type
|
||||
>::value == false){
|
||||
return 1;
|
||||
}
|
||||
|
||||
//Check defined types and implicitly defined types are unequal
|
||||
if(detail::is_same<make_list_base_hook<void_pointer<void*>, link_mode<normal_link> >::type
|
||||
,make_list_base_hook<>::type
|
||||
@ -220,12 +214,6 @@ int main()
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(detail::is_same<make_splay_set_base_hook<void_pointer<void*>, link_mode<normal_link> >::type
|
||||
,make_splay_set_base_hook<>::type
|
||||
>::value == true){
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(detail::is_same<make_bs_set_base_hook<void_pointer<void*>, link_mode<normal_link> >::type
|
||||
,make_bs_set_base_hook<>::type
|
||||
>::value == true){
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include <boost/pointer_cast.hpp>
|
||||
#include <boost/intrusive/pointer_traits.hpp>
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
#if (defined _MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
|
@ -77,15 +77,15 @@ struct my_tag;
|
||||
template<class VoidPointer>
|
||||
struct hooks
|
||||
{
|
||||
typedef splay_set_base_hook<void_pointer<VoidPointer> > base_hook_type;
|
||||
typedef splay_set_base_hook
|
||||
typedef bs_set_base_hook<void_pointer<VoidPointer> > base_hook_type;
|
||||
typedef bs_set_base_hook
|
||||
< link_mode<auto_unlink>
|
||||
, void_pointer<VoidPointer>
|
||||
, tag<my_tag> > auto_base_hook_type;
|
||||
typedef splay_set_member_hook<void_pointer<VoidPointer> > member_hook_type;
|
||||
typedef splay_set_member_hook
|
||||
, tag<my_tag> > auto_base_hook_type;
|
||||
typedef bs_set_member_hook<void_pointer<VoidPointer> > member_hook_type;
|
||||
typedef bs_set_member_hook
|
||||
< link_mode<auto_unlink>
|
||||
, void_pointer<VoidPointer> > auto_member_hook_type;
|
||||
, void_pointer<VoidPointer> > auto_member_hook_type;
|
||||
};
|
||||
|
||||
template< class ValueType
|
||||
|
@ -74,15 +74,15 @@ struct my_tag;
|
||||
template<class VoidPointer>
|
||||
struct hooks
|
||||
{
|
||||
typedef splay_set_base_hook<void_pointer<VoidPointer> > base_hook_type;
|
||||
typedef splay_set_base_hook
|
||||
typedef bs_set_base_hook<void_pointer<VoidPointer> > base_hook_type;
|
||||
typedef bs_set_base_hook
|
||||
< link_mode<auto_unlink>
|
||||
, void_pointer<VoidPointer>
|
||||
, tag<my_tag> > auto_base_hook_type;
|
||||
typedef splay_set_member_hook<void_pointer<VoidPointer> > member_hook_type;
|
||||
typedef splay_set_member_hook
|
||||
, tag<my_tag> > auto_base_hook_type;
|
||||
typedef bs_set_member_hook<void_pointer<VoidPointer> > member_hook_type;
|
||||
typedef bs_set_member_hook
|
||||
< link_mode<auto_unlink>
|
||||
, void_pointer<VoidPointer> > auto_member_hook_type;
|
||||
, void_pointer<VoidPointer> > auto_member_hook_type;
|
||||
};
|
||||
|
||||
template< class ValueType
|
||||
|
@ -219,7 +219,7 @@ void test_common_unordered_and_associative_container(Container & c, Data & d, bo
|
||||
|
||||
c.erase(*da, c.key_comp());
|
||||
BOOST_TEST( c.size() == old_size-1 );
|
||||
//This should not eras anyone
|
||||
//This should not erase any
|
||||
size_type second_erase = c.erase_and_dispose( *da, c.key_comp(), detail::null_disposer() );
|
||||
BOOST_TEST( second_erase == 0 );
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user