Reverted git mess.

This commit is contained in:
Ion Gaztañaga 2014-02-15 00:28:41 +01:00
parent 27e5ad9183
commit 68fa82e5e8
59 changed files with 1937 additions and 3049 deletions

View File

@ -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

View File

@ -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

View File

@ -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(); }
};

View File

@ -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;
}
//]

View File

@ -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;
}
}

View File

@ -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

View File

@ -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);

View File

@ -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).

View File

@ -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())

View File

@ -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());
}
}

View File

@ -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

View File

@ -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).

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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; };

View File

@ -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

View File

@ -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 {

View File

@ -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_;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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 {

View File

@ -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

View File

@ -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>

View File

@ -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);

View File

@ -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())

View File

@ -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());

View File

@ -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);

View File

@ -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).

View File

@ -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

View File

@ -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())

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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())

View File

@ -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);
}

View File

@ -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()

View File

@ -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)
{

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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).

View File

@ -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

View File

@ -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>

View 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>

View File

@ -21,6 +21,7 @@
Optimization="0"
AdditionalIncludeDirectories="../../../../../"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
GeneratePreprocessedFile="0"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="5"

View File

@ -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);
}
};

View File

@ -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;
}

View File

@ -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
{

View File

@ -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){

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 );