Added avl trees

[SVN r40598]
This commit is contained in:
Ion Gaztañaga
2007-10-30 07:02:10 +00:00
parent 5d9b85323a
commit ab9959fc4e
13 changed files with 1628 additions and 20 deletions

View File

@@ -32,7 +32,10 @@ doxygen autodoc
"hashtable_impl=hashtable" \\ "hashtable_impl=hashtable" \\
"splay_set_impl=splay_set" \\ "splay_set_impl=splay_set" \\
"splay_multiset_impl=splay_multiset" \\ "splay_multiset_impl=splay_multiset" \\
"splaytree_impl=splaytree"" "splaytree_impl=splaytree" \\
"avl_set_impl=avl_set" \\
"avl_multiset_impl=avl_multiset" \\
"avltree_impl=avltree""
; ;
xml intrusive : intrusive.qbk ; xml intrusive : intrusive.qbk ;

View File

@@ -928,7 +928,8 @@ one or more indices with different sorting semantics. Boost.Intrusive associativ
containers, like most STL associative container implemenatations are based on containers, like most STL associative container implemenatations are based on
red-black trees. red-black trees.
The memory overhead of these containers is usually 3 pointers and an integer. The memory overhead of these containers is usually 3 pointers and a bit (with
alignment issues, this means 3 pointers and an integer).
This size can be reduced to 3 pointers if pointers have even alignment This size can be reduced to 3 pointers if pointers have even alignment
(which is usually true in most systems). (which is usually true in most systems).
@@ -1259,11 +1260,11 @@ the unordered container:
[endsect] [endsect]
[section:splay_set_multiset Intrusive splay tree-based associative containers: splay_set, splay_multiset] [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, 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 Boost.Intrusive associative containers). However, there are other interesting data
that offer some advantages (and also disadvantages). structures that offer some advantages (and also disadvantages).
Splay trees are self-adjusting binary search trees used tipically in caches, memory Splay trees are self-adjusting binary search trees used tipically in caches, memory
allocators and other applications, because splay trees have a "caching effect": recently allocators and other applications, because splay trees have a "caching effect": recently
@@ -1305,8 +1306,8 @@ performance than other balanced trees for some search patterns.
[section:splay_set_multiset_hooks splay_set, splay_multiset and splaytree hooks] [section:splay_set_multiset_hooks splay_set, splay_multiset and splaytree hooks]
[classref boost::intrusive::set set], [classref boost::intrusive::splay_set splay_set],
[classref boost::intrusive::multiset multiset] and [classref boost::intrusive::splay_multiset splay_multiset] and
[classref boost::intrusive::splaytree splaytree] [classref boost::intrusive::splaytree splaytree]
share the same hooks. share the same hooks.
@@ -1395,6 +1396,135 @@ containers:
[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.
AVL trees are often compared with red-black trees because they support the same set of operations
and because red-black trees also take O(log n) time for the basic operations.
AVL trees are more rigidly balanced than Red-Black trees, leading to slower insertion and
removal but faster retrieval, so AVL trees perform better
than red-black trees for lookup-intensive applications.
[*Boost.Intrusive] offers 3 containers based on avl trees:
[classref boost::intrusive::avl_set avl_set],
[classref boost::intrusive::avl_multiset avl_multiset] and
[classref boost::intrusive::avltree avltree]. 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 and 2 bits (due to alignment, this usually means 3 pointers plus an integer).
This size can be reduced to 3 pointers if pointers have 4 byte alignment
(which is usually true in 32 bit systems).
An empty, non constant-time size [classref boost::intrusive::avl_set avl_set],
[classref boost::intrusive::avl_multiset avl_multiset] or
[classref boost::intrusive::avltree avltree]
has also the size of 3 pointers and an integer (3 pointers when optimized for size).
[section:avl_set_multiset_hooks avl_set, avl_multiset and avltree hooks]
[classref boost::intrusive::avl_set avl_set],
[classref boost::intrusive::avl_multiset avl_multiset] and
[classref boost::intrusive::avltree avltree]
share the same hooks.
[c++]
template <class ...Options>
class avl_set_base_hook;
* [classref boost::intrusive::avl_set_base_hook avl_set_base_hook]:
the user class derives publicly from this class to make
it compatible with avl tree based containers.
[c++]
template <class ...Options>
class avl_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 avl tree based containers.
[classref boost::intrusive::avl_set_base_hook avl_set_base_hook] and
[classref boost::intrusive::avl_set_member_hook avl_set_member_hook] receive
the same options explained in the section
[link intrusive.usage How to use Boost.Intrusive] plus an option to optimize
the size of the node:
* [*`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*>`.
* [*`optimize_size<bool Enable>`]: The hook will be optimized for size
instead of speed. The hook will embed the balance bits of the AVL
tree node in the parent pointer if pointer alignment is multiple of 4.
Optimizing the size will reduce speed performance a bit since masking
operations will be needed to access parent pointer and balance factor attributes.
Default: `optimize_size<false>`.
[endsect]
[section:set_multiset_containers avl_set, avl_multiset and avltree containers]
[c++]
template <class T, class ...Options>
class avl_set;
template <class T, class ...Options>
class avl_multiset;
template <class T, class ...Options>
class avltree;
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 know about value traits go to the section
titled [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:avl_set_multiset_example Example]
Now let's see an small example using both hooks and
[classref boost::intrusive::avl_set avl_set]/
[classref boost::intrusive::avl_multiset avl_multiset]
containers:
[import ../example/doc_avl_set.cpp]
[doc_avl_set_code]
[endsect]
[endsect]
[section:advanced_lookups_insertions Advanced lookup and insertion functions for associative containers] [section:advanced_lookups_insertions Advanced lookup and insertion functions for associative containers]
[section:advanced_lookups Advanced lookups] [section:advanced_lookups Advanced lookups]
@@ -2056,7 +2186,7 @@ with our nodes:
[import ../example/doc_rbtree_algorithms.cpp] [import ../example/doc_rbtree_algorithms.cpp]
[doc_rbtree_algorithms_code] [doc_rbtree_algorithms_code]
For a complete rbtree of functions see For a complete list of functions see
[classref boost::intrusive::rbtree_algorithms rbtree_algorithms reference]. [classref boost::intrusive::rbtree_algorithms rbtree_algorithms reference].
[endsect] [endsect]
@@ -2064,7 +2194,7 @@ For a complete rbtree of functions see
[section:splaytree_algorithms Intrusive splay tree algorithms] [section:splaytree_algorithms Intrusive splay tree algorithms]
These algorithms are static These algorithms are static
members of the [classref boost::intrusive::rbtree_algorithms splaytree_algorithms] class: members of the [classref boost::intrusive::splaytree_algorithms splaytree_algorithms] class:
[c++] [c++]
@@ -2074,14 +2204,14 @@ members of the [classref boost::intrusive::rbtree_algorithms splaytree_algorithm
An empty tree is formed by a node whose pointer to the parent node is null, An empty tree is formed by a node whose pointer to the parent node is null,
the pointers to the left and right nodes to itself. the pointers to the left and right nodes to itself.
[classref boost::intrusive::splaytree_algorithms rbtree_algorithms] [classref boost::intrusive::splaytree_algorithms splaytree_algorithms]
is configured with a NodeTraits class, which encapsulates is configured with a NodeTraits class, which encapsulates
the information about the node to be manipulated. NodeTraits must support the the information about the node to be manipulated. NodeTraits must support the
following interface: following interface:
[*Typedefs]: [*Typedefs]:
* `node`: The type of the node that forms the circular rbtree * `node`: The type of the node that forms the circular splaytree
* `node_ptr`: The type of a pointer to a node (usually node*) * `node_ptr`: The type of a pointer to a node (usually node*)
@@ -2107,20 +2237,88 @@ following interface:
* `static void set_right(node_ptr n, node_ptr r);`: * `static void set_right(node_ptr n, node_ptr r);`:
Sets the pointer to the right node stored in "n" to "r". Sets the pointer to the right node stored in "n" to "r".
* `static color get_color(const_node_ptr n);`:
Returns the color stored in "n".
Once we have a node traits configuration we can use [*Boost.Intrusive] algorithms Once we have a node traits configuration we can use [*Boost.Intrusive] algorithms
with our nodes: with our nodes:
[import ../example/doc_splaytree_algorithms.cpp] [import ../example/doc_splaytree_algorithms.cpp]
[doc_splaytree_algorithms_code] [doc_splaytree_algorithms_code]
For a complete rbtree of functions see For a complete list of functions see
[classref boost::intrusive::splaytree_algorithms splaytree_algorithms reference]. [classref boost::intrusive::splaytree_algorithms splaytree_algorithms reference].
[endsect] [endsect]
[section:avltree_algorithms Intrusive avl tree algorithms]
[classref boost::intrusive::avltree_algorithms avltree_algorithms] have the same
interface as [classref boost::intrusive::rbtree_algorithms rbtree_algorithms].
[c++]
template<class NodeTraits>
struct avltree_algorithms;
[classref boost::intrusive::avltree_algorithms avltree_algorithms]
is configured with a NodeTraits class, which encapsulates
the information about the node to be manipulated. NodeTraits must support the
following interface:
[*Typedefs]:
* `node`: The type of the node that forms the circular avltree
* `node_ptr`: The type of a pointer to a node (usually node*)
* `const_node_ptr`: The type of a pointer to a const node (usually const node*)
* `balance`: A type that can represent 3 balance types (usually an integer)
[*Static functions]:
* `static node_ptr get_parent(const_node_ptr n);`:
Returns a pointer to the parent node stored in "n".
* `static void set_parent(node_ptr n, node_ptr p);`:
Sets the pointer to the parent node stored in "n" to "p".
* `static node_ptr get_left(const_node_ptr n);`:
Returns a pointer to the left node stored in "n".
* `static void set_left(node_ptr n, node_ptr l);`:
Sets the pointer to the left node stored in "n" to "l".
* `static node_ptr get_right(const_node_ptr n);`:
Returns a pointer to the right node stored in "n".
* `static void set_right(node_ptr n, node_ptr r);`:
Sets the pointer to the right node stored in "n" to "r".
* `static balance get_balance(const_node_ptr n);`:
Returns the balance factor stored in "n".
* `static void set_balance(node_ptr n, balance b);`:
Sets the balance factor stored in "n" to "b".
* `static balance negative();`:
Returns a value representing a negative balance factor.
* `static balance zero();`:
Returns a value representing a zero balance factor.
* `static balance positive();`:
Returns a value representing a positive balance factor.
Once we have a node traits configuration we can use [*Boost.Intrusive] algorithms
with our nodes:
[import ../example/doc_avltree_algorithms.cpp]
[doc_avltree_algorithms_code]
For a complete list of functions see
[classref boost::intrusive::avltree_algorithms avltree_algorithms reference].
[endsect]
[endsect] [endsect]
[section:value_traits Containers with custom ValueTraits] [section:value_traits Containers with custom ValueTraits]
@@ -2976,8 +3174,12 @@ helpful discussions.
[*Tom Brinkman] and [*Steven Watanabe] [*Tom Brinkman] and [*Steven Watanabe]
for their comments and reviews in the Boost.Intrusive formal review. for their comments and reviews in the Boost.Intrusive formal review.
* Thanks to of Julienne Walker and The EC Team ([@http://eternallyconfuzzled.com]) for their * Thanks to of [*Julienne Walker] and [*The EC Team] ([@http://eternallyconfuzzled.com])
great algorithms. for their great algorithms.
* Thanks to [*Daniel K. O.] for his AVL tree rebalancing code.
* Thanks to [*Ralf Mattethat] for his splay tree article and code.
* Special thanks to [*Steven Watanabe] and [*Tobias Schwinger] for their * Special thanks to [*Steven Watanabe] and [*Tobias Schwinger] for their
invaluable suggestions and improvements. invaluable suggestions and improvements.

88
example/doc_avl_set.cpp Normal file
View File

@@ -0,0 +1,88 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-2007
//
// 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_avl_set_code
#include <boost/intrusive/avl_set.hpp>
#include <vector>
#include <algorithm>
#include <cassert>
using namespace boost::intrusive;
//This is a base hook optimized for size
class MyClass : public avl_set_base_hook<optimize_size<true> >
{
int int_;
public:
//This is a member hook
avl_set_member_hook<> member_hook_;
MyClass(int i)
: int_(i)
{}
friend bool operator< (const MyClass &a, const MyClass &b)
{ return a.int_ < b.int_; }
friend bool operator> (const MyClass &a, const MyClass &b)
{ return a.int_ > b.int_; }
friend bool operator== (const MyClass &a, const MyClass &b)
{ return a.int_ < b.int_; }
};
//Define an avl_set using the base hook that will store values in reverse order
typedef avl_set< MyClass, compare<std::greater<MyClass> > > BaseSet;
//Define an multiset using the member hook
typedef member_hook<MyClass, avl_set_member_hook<>, &MyClass::member_hook_> MemberOption;
typedef avl_multiset< MyClass, MemberOption> MemberMultiset;
int main()
{
typedef std::vector<MyClass>::iterator VectIt;
typedef std::vector<MyClass>::reverse_iterator VectRit;
//Create several MyClass objects, each one with a different value
std::vector<MyClass> values;
for(int i = 0; i < 100; ++i) values.push_back(MyClass(i));
BaseSet baseset;
MemberMultiset membermultiset;
//Check that size optimization is activated in the base hook
assert(sizeof(avl_set_base_hook<optimize_size<true> >) == 3*sizeof(void*));
//Check that size optimization is deactivated in the member hook
assert(sizeof(avl_set_member_hook<>) > 3*sizeof(void*));
//Now insert them in the reverse order in the base hook avl_set
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it)
baseset.insert(*it);
//Now insert them in the same order as in vector in the member hook avl_set
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it)
membermultiset.insert(*it);
//Now test avl_sets
{
BaseSet::reverse_iterator rbit(baseset.rbegin()), rbitend(baseset.rend());
MemberMultiset::iterator mit(membermultiset.begin()), mitend(membermultiset.end());
VectIt it(values.begin()), itend(values.end());
//Test the objects inserted in the base hook avl_set
for(; it != itend; ++it, ++rbit)
if(&*rbit != &*it) return 1;
//Test the objects inserted in the member hook avl_set
for(it = values.begin(); it != itend; ++it, ++mit)
if(&*mit != &*it) return 1;
}
return 0;
}
//]

View File

@@ -0,0 +1,85 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007
//
// 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_avltree_algorithms_code
#include <boost/intrusive/avltree_algorithms.hpp>
#include <cassert>
struct my_node
{
my_node(int i = 0)
: int_(i)
{}
my_node *parent_, *left_, *right_;
int balance_;
//other members
int int_;
};
//Define our own avltree_node_traits
struct my_avltree_node_traits
{
typedef my_node node;
typedef my_node * node_ptr;
typedef const my_node * const_node_ptr;
typedef int balance;
static node_ptr get_parent(const_node_ptr n) { return n->parent_; }
static void set_parent(node_ptr n, node_ptr parent){ n->parent_ = parent; }
static node_ptr get_left(const_node_ptr n) { return n->left_; }
static void set_left(node_ptr n, node_ptr left) { n->left_ = left; }
static node_ptr get_right(const_node_ptr n) { return n->right_; }
static void set_right(node_ptr n, node_ptr right) { n->right_ = right; }
static balance get_balance(const_node_ptr n) { return n->balance_; }
static void set_balance(node_ptr n, balance b) { n->balance_ = b; }
static balance negative() { return -1; }
static balance zero() { return 0; }
static balance positive() { return 1; }
};
struct node_ptr_compare
{
bool operator()(my_node *a, my_node *b)
{ return a->int_ < b->int_; }
};
int main()
{
typedef boost::intrusive::avltree_algorithms<my_avltree_node_traits> algo;
my_node header, two(2), three(3);
//Create an empty avltree container:
//"header" will be the header node of the tree
algo::init_header(&header);
//Now insert node "two" in the tree using the sorting functor
algo::insert_equal_upper_bound(&header, &two, node_ptr_compare());
//Now insert node "three" in the tree using the sorting functor
algo::insert_equal_lower_bound(&header, &three, node_ptr_compare());
//Now take the first node (the left node of the header)
my_node *n = header.left_;
assert(n == &two);
//Now go to the next node
n = algo::next_node(n);
assert(n == &three);
//Erase a node just using a pointer to it
algo::unlink(&two);
//Erase a node using also the header (faster)
algo::erase(&header, &three);
return 0;
}
//]

View File

@@ -0,0 +1,78 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007
//
// 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_splaytree_algorithms_code
#include <boost/intrusive/splaytree_algorithms.hpp>
#include <cassert>
struct my_node
{
my_node(int i = 0)
: int_(i)
{}
my_node *parent_, *left_, *right_;
//other members
int int_;
};
//Define our own splaytree_node_traits
struct my_splaytree_node_traits
{
typedef my_node node;
typedef my_node * node_ptr;
typedef const my_node * const_node_ptr;
static node_ptr get_parent(const_node_ptr n) { return n->parent_; }
static void set_parent(node_ptr n, node_ptr parent){ n->parent_ = parent; }
static node_ptr get_left(const_node_ptr n) { return n->left_; }
static void set_left(node_ptr n, node_ptr left) { n->left_ = left; }
static node_ptr get_right(const_node_ptr n) { return n->right_; }
static void set_right(node_ptr n, node_ptr right) { n->right_ = right; }
};
struct node_ptr_compare
{
bool operator()(my_node *a, my_node *b)
{ return a->int_ < b->int_; }
};
int main()
{
typedef boost::intrusive::splaytree_algorithms<my_splaytree_node_traits> algo;
my_node header, two(2), three(3);
//Create an empty splaytree container:
//"header" will be the header node of the tree
algo::init_header(&header);
//Now insert node "two" in the tree using the sorting functor
algo::insert_equal_upper_bound(&header, &two, node_ptr_compare());
//Now insert node "three" in the tree using the sorting functor
algo::insert_equal_lower_bound(&header, &three, node_ptr_compare());
//Now take the first node (the left node of the header)
my_node *n = header.left_;
assert(n == &two);
//Now go to the next node
n = algo::next_node(n);
assert(n == &three);
//Erase a node just using a pointer to it
algo::unlink(&two);
//Erase a node using also the header (faster)
algo::erase(&header, &three);
return 0;
}
//]

View File

@@ -63,6 +63,14 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "splay_set", "splay_set\spla
ProjectSection(ProjectDependencies) = postProject ProjectSection(ProjectDependencies) = postProject
EndProjectSection EndProjectSection
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "avl_multiset", "avl_multiset\avl_multiset.vcproj", "{0AE70176-5B8C-4BC7-392C-A4A312B07893}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "avl_set", "avl_set\avl_set.vcproj", "{16909EE7-24AF-97C1-C76B-204B971BA959}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Global Global
GlobalSection(SolutionConfiguration) = preSolution GlobalSection(SolutionConfiguration) = preSolution
Debug = Debug Debug = Debug
@@ -135,6 +143,14 @@ Global
{1E6909E7-C971-F24A-6C7B-A92094B71B59}.Debug.Build.0 = Debug|Win32 {1E6909E7-C971-F24A-6C7B-A92094B71B59}.Debug.Build.0 = Debug|Win32
{1E6909E7-C971-F24A-6C7B-A92094B71B59}.Release.ActiveCfg = Release|Win32 {1E6909E7-C971-F24A-6C7B-A92094B71B59}.Release.ActiveCfg = Release|Win32
{1E6909E7-C971-F24A-6C7B-A92094B71B59}.Release.Build.0 = Release|Win32 {1E6909E7-C971-F24A-6C7B-A92094B71B59}.Release.Build.0 = Release|Win32
{0AE70176-5B8C-4BC7-392C-A4A312B07893}.Debug.ActiveCfg = Debug|Win32
{0AE70176-5B8C-4BC7-392C-A4A312B07893}.Debug.Build.0 = Debug|Win32
{0AE70176-5B8C-4BC7-392C-A4A312B07893}.Release.ActiveCfg = Release|Win32
{0AE70176-5B8C-4BC7-392C-A4A312B07893}.Release.Build.0 = Release|Win32
{16909EE7-24AF-97C1-C76B-204B971BA959}.Debug.ActiveCfg = Debug|Win32
{16909EE7-24AF-97C1-C76B-204B971BA959}.Debug.Build.0 = Debug|Win32
{16909EE7-24AF-97C1-C76B-204B971BA959}.Release.ActiveCfg = Release|Win32
{16909EE7-24AF-97C1-C76B-204B971BA959}.Release.Build.0 = Release|Win32
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
EndGlobalSection EndGlobalSection

View File

@@ -105,6 +105,18 @@
Name="Header Files" Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd" Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"> UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
<File
RelativePath="..\..\..\..\..\boost\intrusive\avl_set.hpp">
</File>
<File
RelativePath="..\..\..\..\..\boost\intrusive\avl_set_hook.hpp">
</File>
<File
RelativePath="..\..\..\..\..\boost\intrusive\avltree.hpp">
</File>
<File
RelativePath="..\..\..\..\..\boost\intrusive\avltree_algorithms.hpp">
</File>
<File <File
RelativePath="..\..\..\..\..\boost\intrusive\circular_list_algorithms.hpp"> RelativePath="..\..\..\..\..\boost\intrusive\circular_list_algorithms.hpp">
</File> </File>
@@ -135,6 +147,9 @@
<File <File
RelativePath="..\..\..\..\..\boost\intrusive\options.hpp"> RelativePath="..\..\..\..\..\boost\intrusive\options.hpp">
</File> </File>
<File
RelativePath="..\..\..\..\..\boost\intrusive\pointer_plus_2_bits.hpp">
</File>
<File <File
RelativePath="..\..\..\..\..\boost\intrusive\pointer_plus_bit.hpp"> RelativePath="..\..\..\..\..\boost\intrusive\pointer_plus_bit.hpp">
</File> </File>
@@ -183,6 +198,9 @@
<File <File
RelativePath="..\..\..\..\..\boost\intrusive\detail\assert.hpp"> RelativePath="..\..\..\..\..\boost\intrusive\detail\assert.hpp">
</File> </File>
<File
RelativePath="..\..\..\..\..\boost\intrusive\detail\avltree_node.hpp">
</File>
<File <File
RelativePath="..\..\..\..\..\boost\intrusive\detail\config_begin.hpp"> RelativePath="..\..\..\..\..\boost\intrusive\detail\config_begin.hpp">
</File> </File>
@@ -219,9 +237,6 @@
<File <File
RelativePath="..\..\..\..\..\boost\intrusive\detail\slist_node.hpp"> RelativePath="..\..\..\..\..\boost\intrusive\detail\slist_node.hpp">
</File> </File>
<File
RelativePath="..\..\..\..\..\boost\intrusive\detail\splaytree_node.hpp">
</File>
<File <File
RelativePath="..\..\..\..\..\boost\intrusive\detail\transform_iterator.hpp"> RelativePath="..\..\..\..\..\boost\intrusive\detail\transform_iterator.hpp">
</File> </File>
@@ -286,6 +301,12 @@
<File <File
RelativePath="..\..\..\example\doc_auto_unlink.cpp"> RelativePath="..\..\..\example\doc_auto_unlink.cpp">
</File> </File>
<File
RelativePath="..\..\..\example\doc_avl_set.cpp">
</File>
<File
RelativePath="..\..\..\example\doc_avltree_algorithms.cpp">
</File>
<File <File
RelativePath="..\..\..\example\doc_bucket_traits.cpp"> RelativePath="..\..\..\example\doc_bucket_traits.cpp">
</File> </File>
@@ -334,6 +355,9 @@
<File <File
RelativePath="..\..\..\example\doc_splay_set.cpp"> RelativePath="..\..\..\example\doc_splay_set.cpp">
</File> </File>
<File
RelativePath="..\..\..\example\doc_splaytree_algorithms.cpp">
</File>
<File <File
RelativePath="..\..\..\example\doc_stateful_value_traits.cpp"> RelativePath="..\..\..\example\doc_stateful_value_traits.cpp">
</File> </File>

View File

@@ -0,0 +1,127 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="avl_multiset"
ProjectGUID="{0AE70176-5B8C-4BC7-392C-A4A312B07893}"
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="WIN32;_DEBUG;_CONSOLE"
GeneratePreprocessedFile="0"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="5"
DisableLanguageExtensions="TRUE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/avl_multiset.exe"
LinkIncremental="2"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/avl_multiset.pdb"
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="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="4"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/avl_multiset.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="{F9A837FC-4236-A8D7-745E-2D383A2E13EA}">
<File
RelativePath="..\..\..\test\avl_multiset_test.cpp">
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,126 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="avl_set"
ProjectGUID="{16909EE7-24AF-97C1-C76B-204B971BA959}"
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="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="5"
DisableLanguageExtensions="TRUE"
ForceConformanceInForLoopScope="TRUE"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/avl_set.exe"
LinkIncremental="2"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/avl_set.pdb"
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="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="4"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/avl_set.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="{FC776C11-2A4F-326F-1E35-4C72A23B325A}">
<File
RelativePath="..\..\..\test\avl_set_test.cpp">
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

394
test/avl_multiset_test.cpp Normal file
View File

@@ -0,0 +1,394 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Olaf Krzikalla 2004-2006.
// (C) Copyright Ion Gaztanaga 2006-2007.
//
// 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/detail/config_begin.hpp>
#include <boost/intrusive/avl_set.hpp>
#include <boost/intrusive/detail/pointer_to_other.hpp>
#include "itestvalue.hpp"
#include "smart_ptr.hpp"
#include "common_functors.hpp"
#include <vector>
#include <boost/detail/lightweight_test.hpp>
#include "test_macros.hpp"
#include "test_container.hpp"
#include <set>
namespace boost { namespace intrusive { namespace test {
template<class T, class O1, class O2, class O3, class O4>
struct has_const_overloads<boost::intrusive::avl_multiset<T, O1, O2, O3, O4> >
{
static const bool value = false;
};
}}}
using namespace boost::intrusive;
template<class ValueTraits>
struct test_avl_multiset
{
typedef typename ValueTraits::value_type value_type;
static void test_all (std::vector<value_type>& values);
static void test_sort(std::vector<value_type>& values);
static void test_insert(std::vector<value_type>& values);
static void test_swap(std::vector<value_type>& values);
static void test_find(std::vector<value_type>& values);
static void test_impl();
static void test_clone(std::vector<value_type>& values);
static void test_container_from_end(std::vector<value_type>& values);
};
template<class ValueTraits>
void test_avl_multiset<ValueTraits>::test_all
(std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef avl_multiset
< value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> avl_multiset_type;
{
avl_multiset_type testset(values.begin(), values.end());
test::test_container(testset);
testset.clear();
testset.insert(values.begin(), values.end());
test::test_common_unordered_and_associative_container(testset, values);
testset.clear();
testset.insert(values.begin(), values.end());
test::test_associative_container(testset, values);
testset.clear();
testset.insert(values.begin(), values.end());
test::test_non_unique_container(testset, values);
}
test_sort(values);
test_insert(values);
test_swap(values);
test_find(values);
test_impl();
test_clone(values);
test_container_from_end(values);
}
//test case due to an error in tree implementation:
template<class ValueTraits>
void test_avl_multiset<ValueTraits>::test_impl()
{
typedef typename ValueTraits::value_type value_type;
std::vector<value_type> values (5);
for (int i = 0; i < 5; ++i)
values[i].value_ = i;
typedef typename ValueTraits::value_type value_type;
typedef avl_multiset
< value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> multiset_type;
multiset_type testset;
for (int i = 0; i < 5; ++i)
testset.insert (values[i]);
testset.erase (testset.iterator_to (values[0]));
testset.erase (testset.iterator_to (values[1]));
testset.insert (values[1]);
testset.erase (testset.iterator_to (values[2]));
testset.erase (testset.iterator_to (values[3]));
}
//test: constructor, iterator, clear, reverse_iterator, front, back, size:
template<class ValueTraits>
void test_avl_multiset<ValueTraits>::test_sort
(std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef avl_multiset
< value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> multiset_type;
multiset_type testset1 (values.begin(), values.end());
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
testset1.clear();
BOOST_TEST (testset1.empty());
typedef avl_multiset
<value_type
, compare<even_odd>
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> multiset_type2;
multiset_type2 testset2 (&values[0], &values[0] + 6);
{ int init_values [] = { 5, 3, 1, 4, 2, 2 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset2.rbegin() ); }
BOOST_TEST (testset2.begin()->value_ == 2);
BOOST_TEST (testset2.rbegin()->value_ == 5);
}
//test: insert, const_iterator, const_reverse_iterator, erase, iterator_to:
template<class ValueTraits>
void test_avl_multiset<ValueTraits>::test_insert
(std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef avl_multiset
< value_type
, value_traits<ValueTraits>
, size_type<std::size_t>
, constant_time_size<value_type::constant_time_size>
> multiset_type;
multiset_type testset;
testset.insert(&values[0] + 2, &values[0] + 5);
{ int init_values [] = { 1, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset.begin() ); }
typename multiset_type::iterator i = testset.begin();
BOOST_TEST (i->value_ == 1);
i = testset.insert (i, values[0]);
BOOST_TEST (&*i == &values[0]);
{ int init_values [] = { 5, 4, 3, 1 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset.rbegin() ); }
i = testset.iterator_to (values[2]);
BOOST_TEST (&*i == &values[2]);
i = multiset_type::s_iterator_to (values[2]);
BOOST_TEST (&*i == &values[2]);
testset.erase(i);
{ int init_values [] = { 1, 3, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset.begin() ); }
}
//test: insert (seq-version), swap, erase (seq-version), size:
template<class ValueTraits>
void test_avl_multiset<ValueTraits>::test_swap
(std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef avl_multiset
< value_type
, value_traits<ValueTraits>
, size_type<std::size_t>
, constant_time_size<value_type::constant_time_size>
> multiset_type;
multiset_type testset1 (&values[0], &values[0] + 2);
multiset_type testset2;
testset2.insert (&values[0] + 2, &values[0] + 6);
{ int init_values [] = { 1, 2, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset2.begin() ); }
{ int init_values [] = { 2, 3 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
testset1.swap (testset2);
{ int init_values [] = { 1, 2, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
{ int init_values [] = { 2, 3 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset2.begin() ); }
testset1.erase (testset1.iterator_to(values[5]), testset1.end());
BOOST_TEST (testset1.size() == 1);
BOOST_TEST (&*testset1.begin() == &values[3]);
}
//test: find, equal_range (lower_bound, upper_bound):
template<class ValueTraits>
void test_avl_multiset<ValueTraits>::test_find
(std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef avl_multiset
< value_type
, value_traits<ValueTraits>
, size_type<std::size_t>
, constant_time_size<value_type::constant_time_size>
> multiset_type;
multiset_type testset (values.begin(), values.end());
typedef typename multiset_type::iterator iterator;
value_type cmp_val;
cmp_val.value_ = 2;
iterator i = testset.find (cmp_val);
BOOST_TEST (i->value_ == 2);
BOOST_TEST ((++i)->value_ == 2);
std::pair<iterator,iterator> range = testset.equal_range (cmp_val);
BOOST_TEST (range.first->value_ == 2);
BOOST_TEST (range.second->value_ == 3);
BOOST_TEST (std::distance (range.first, range.second) == 2);
cmp_val.value_ = 7;
BOOST_TEST (testset.find (cmp_val) == testset.end());
}
template<class ValueTraits>
void test_avl_multiset<ValueTraits>::test_clone
(std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef avl_multiset
< value_type
, value_traits<ValueTraits>
, size_type<std::size_t>
, constant_time_size<value_type::constant_time_size>
> multiset_type;
multiset_type testmultiset1 (&values[0], &values[0] + values.size());
multiset_type testmultiset2;
testmultiset2.clone_from(testmultiset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
BOOST_TEST (testmultiset2 == testmultiset1);
testmultiset2.clear_and_dispose(test::delete_disposer<value_type>());
BOOST_TEST (testmultiset2.empty());
}
template<class ValueTraits>
void test_avl_multiset<ValueTraits>::test_container_from_end
(std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef avl_multiset
< value_type
, value_traits<ValueTraits>
, size_type<std::size_t>
, constant_time_size<value_type::constant_time_size>
> multiset_type;
multiset_type testmultiset (&values[0], &values[0] + values.size());
BOOST_TEST (testmultiset == multiset_type::container_from_end_iterator(testmultiset.end()));
BOOST_TEST (testmultiset == multiset_type::container_from_end_iterator(testmultiset.cend()));
}
template<class VoidPointer, bool constant_time_size>
class test_main_template
{
public:
int operator()()
{
for(int n = 0; n < 2; ++n){
typedef testvalue<VoidPointer, constant_time_size> value_type;
static const int random_init[6] = { 3, 2, 4, 1, 5, 2 };
std::vector<testvalue<VoidPointer, constant_time_size> > data (6);
for (int i = 0; i < 6; ++i)
data[i].value_ = random_init[i];
test_avl_multiset < typename detail::get_base_value_traits
< value_type
, typename value_type::avl_set_base_hook_t
>::type
>::test_all(data);
test_avl_multiset < typename detail::get_member_value_traits
< value_type
, member_hook< value_type
, typename value_type::avl_set_member_hook_t
, &value_type::avl_set_node_
>
>::type
>::test_all(data);
}
return 0;
}
};
template<class VoidPointer>
class test_main_template<VoidPointer, false>
{
public:
int operator()()
{
for(int n = 0; n < 2; ++n){
typedef testvalue<VoidPointer, false> value_type;
static const int random_init[6] = { 3, 2, 4, 1, 5, 2 };
std::vector<testvalue<VoidPointer, false> > data (6);
for (int i = 0; i < 6; ++i)
data[i].value_ = random_init[i];
test_avl_multiset < typename detail::get_base_value_traits
< value_type
, typename value_type::avl_set_base_hook_t
>::type
>::test_all(data);
test_avl_multiset < typename detail::get_member_value_traits
< value_type
, member_hook< value_type
, typename value_type::avl_set_member_hook_t
, &value_type::avl_set_node_
>
>::type
>::test_all(data);
test_avl_multiset < typename detail::get_base_value_traits
< value_type
, typename value_type::avl_set_auto_base_hook_t
>::type
>::test_all(data);
test_avl_multiset < typename detail::get_member_value_traits
< value_type
, member_hook< value_type
, typename value_type::avl_set_auto_member_hook_t
, &value_type::avl_set_auto_node_
>
>::type
>::test_all(data);
}
return 0;
}
};
//Explicit instantiations of non-counted classes
//template class multiset
// <set_base_raw, std::less<set_base_raw::value_type>, false>;
//template class multiset
// <set_member_raw, std::less<set_member_raw::value_type>, false>;
//template class multiset
// <set_auto_base_raw, std::less<set_auto_base_raw::value_type>, false>;
//template class multiset
// <set_auto_member_raw, std::less<set_auto_member_raw::value_type>, false>;
//template class multiset
// <set_base_smart, std::less<set_base_smart::value_type>, false>;
//template class multiset
// <set_member_smart, std::less<set_member_smart::value_type>, false>;
//template class multiset
// <set_auto_base_smart, std::less<set_auto_base_smart::value_type>, false>;
//template class multiset
// <set_auto_member_smart, std::less<set_auto_member_smart::value_type>, false>;
//Explicit instantiation of counted classes
//template class multiset
// <set_base_raw_t, std::less<set_base_raw_t::value_type>, true>;
//template class multiset
// <set_member_raw_t, std::less<set_member_raw_t::value_type>, true>;
//template class multiset
// <set_base_smart_t, std::less<set_base_smart_t::value_type>, true>;
//template class multiset
// <set_member_smart_t, std::less<set_member_smart_t::value_type>, true>;
int main( int, char* [] )
{
test_main_template<void*, false>()();
test_main_template<smart_ptr<void>, false>()();
test_main_template<void*, true>()();
test_main_template<smart_ptr<void>, true>()();
return boost::report_errors();
}

350
test/avl_set_test.cpp Normal file
View File

@@ -0,0 +1,350 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007.
//
// 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/detail/config_begin.hpp>
#include <boost/intrusive/avl_set.hpp>
#include <boost/intrusive/detail/pointer_to_other.hpp>
#include "itestvalue.hpp"
#include "smart_ptr.hpp"
#include "common_functors.hpp"
#include <vector>
#include <boost/detail/lightweight_test.hpp>
#include "test_macros.hpp"
#include "test_container.hpp"
#include <set>
namespace boost { namespace intrusive { namespace test {
template<class T, class O1, class O2, class O3, class O4>
struct has_const_overloads<boost::intrusive::avl_set<T, O1, O2, O3, O4> >
{
static const bool value = false;
};
}}}
using namespace boost::intrusive;
template<class ValueTraits>
struct test_avl_set
{
typedef typename ValueTraits::value_type value_type;
static void test_all(std::vector<value_type>& values);
static void test_sort(std::vector<value_type>& values);
static void test_insert(std::vector<value_type>& values);
static void test_swap(std::vector<value_type>& values);
static void test_find(std::vector<value_type>& values);
static void test_impl();
static void test_clone(std::vector<value_type>& values);
static void test_container_from_end(std::vector<value_type>& values);
};
template<class ValueTraits>
void test_avl_set<ValueTraits>::test_all(std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef avl_set
< value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> avl_set_type;
{
avl_set_type testset(values.begin(), values.end());
test::test_container(testset);
testset.clear();
testset.insert(values.begin(), values.end());
test::test_common_unordered_and_associative_container(testset, values);
testset.clear();
testset.insert(values.begin(), values.end());
test::test_associative_container(testset, values);
testset.clear();
testset.insert(values.begin(), values.end());
test::test_unique_container(testset, values);
}
test_sort(values);
test_insert(values);
test_swap(values);
test_find(values);
test_impl();
test_clone(values);
test_container_from_end(values);
}
//test case due to an error in tree implementation:
template<class ValueTraits>
void test_avl_set<ValueTraits>::test_impl()
{
typedef typename ValueTraits::value_type value_type;
std::vector<value_type> values (5);
for (int i = 0; i < 5; ++i)
values[i].value_ = i;
typedef typename ValueTraits::value_type value_type;
typedef avl_set
< value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> avl_set_type;
avl_set_type testset;
for (int i = 0; i < 5; ++i)
testset.insert (values[i]);
testset.erase (testset.iterator_to (values[0]));
testset.erase (testset.iterator_to (values[1]));
testset.insert (values[1]);
testset.erase (testset.iterator_to (values[2]));
testset.erase (testset.iterator_to (values[3]));
}
//test: constructor, iterator, clear, reverse_iterator, front, back, size:
template<class ValueTraits>
void test_avl_set<ValueTraits>::test_sort(std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef avl_set
< value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> avl_set_type;
avl_set_type testset1 (values.begin(), values.end());
{ int init_values [] = { 1, 2, 3, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
testset1.clear();
BOOST_TEST (testset1.empty());
typedef typename ValueTraits::value_type value_type;
typedef avl_set
< value_type
, compare<even_odd>
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> set_type2;
set_type2 testset2 (&values[0], &values[0] + 6);
{ int init_values [] = { 5, 3, 1, 4, 2 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset2.rbegin() ); }
BOOST_TEST (testset2.begin()->value_ == 2);
BOOST_TEST (testset2.rbegin()->value_ == 5);
}
//test: insert, const_iterator, const_reverse_iterator, erase, s_iterator_to:
template<class ValueTraits>
void test_avl_set<ValueTraits>::test_insert(std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef avl_set
< value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> avl_set_type;
avl_set_type testset;
testset.insert(&values[0] + 2, &values[0] + 5);
const avl_set_type& const_testset = testset;
{ int init_values [] = { 1, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); }
typename avl_set_type::iterator i = testset.begin();
BOOST_TEST (i->value_ == 1);
i = testset.insert (i, values[0]);
BOOST_TEST (&*i == &values[0]);
{ int init_values [] = { 5, 4, 3, 1 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset.rbegin() ); }
i = testset.iterator_to (values[2]);
BOOST_TEST (&*i == &values[2]);
i = avl_set_type::s_iterator_to(values[2]);
BOOST_TEST (&*i == &values[2]);
testset.erase (i);
{ int init_values [] = { 1, 3, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset.begin() ); }
}
//test: insert (seq-version), swap, erase (seq-version), size:
template<class ValueTraits>
void test_avl_set<ValueTraits>::test_swap(std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef avl_set
< value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> avl_set_type;
avl_set_type testset1 (&values[0], &values[0] + 2);
avl_set_type testset2;
testset2.insert (&values[0] + 2, &values[0] + 6);
testset1.swap (testset2);
{ int init_values [] = { 1, 2, 4, 5 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
{ int init_values [] = { 2, 3 };
TEST_INTRUSIVE_SEQUENCE( init_values, testset2.begin() ); }
testset1.erase (testset1.iterator_to(values[5]), testset1.end());
BOOST_TEST (testset1.size() == 1);
// BOOST_TEST (&testset1.front() == &values[3]);
BOOST_TEST (&*testset1.begin() == &values[3]);
}
//test: find, equal_range (lower_bound, upper_bound):
template<class ValueTraits>
void test_avl_set<ValueTraits>::test_find(std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef avl_set
< value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> avl_set_type;
avl_set_type testset (values.begin(), values.end());
typedef typename avl_set_type::iterator iterator;
value_type cmp_val;
cmp_val.value_ = 2;
iterator i = testset.find (cmp_val);
BOOST_TEST (i->value_ == 2);
BOOST_TEST ((++i)->value_ != 2);
std::pair<iterator,iterator> range = testset.equal_range (cmp_val);
BOOST_TEST (range.first->value_ == 2);
BOOST_TEST (range.second->value_ == 3);
BOOST_TEST (std::distance (range.first, range.second) == 1);
cmp_val.value_ = 7;
BOOST_TEST (testset.find (cmp_val) == testset.end());
}
template<class ValueTraits>
void test_avl_set<ValueTraits>
::test_clone(std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef avl_set
< value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> avl_set_type;
avl_set_type testset1 (&values[0], &values[0] + values.size());
avl_set_type testset2;
testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
BOOST_TEST (testset2 == testset1);
testset2.clear_and_dispose(test::delete_disposer<value_type>());
BOOST_TEST (testset2.empty());
}
template<class ValueTraits>
void test_avl_set<ValueTraits>
::test_container_from_end(std::vector<typename ValueTraits::value_type>& values)
{
typedef typename ValueTraits::value_type value_type;
typedef avl_set
< value_type
, value_traits<ValueTraits>
, constant_time_size<value_type::constant_time_size>
> avl_set_type;
avl_set_type testset (&values[0], &values[0] + values.size());
BOOST_TEST (testset == avl_set_type::container_from_end_iterator(testset.end()));
BOOST_TEST (testset == avl_set_type::container_from_end_iterator(testset.cend()));
}
template<class VoidPointer, bool constant_time_size>
class test_main_template
{
public:
int operator()()
{
typedef testvalue<VoidPointer, constant_time_size> value_type;
static const int random_init[6] = { 3, 2, 4, 1, 5, 2 };
std::vector<testvalue<VoidPointer, constant_time_size> > data (6);
for (int i = 0; i < 6; ++i)
data[i].value_ = random_init[i];
test_avl_set < typename detail::get_base_value_traits
< value_type
, typename value_type::avl_set_base_hook_t
>::type
>::test_all(data);
test_avl_set < typename detail::get_member_value_traits
< value_type
, member_hook< value_type
, typename value_type::avl_set_member_hook_t
, &value_type::avl_set_node_
>
>::type
>::test_all(data);
return 0;
}
};
template<class VoidPointer>
class test_main_template<VoidPointer, false>
{
public:
int operator()()
{
typedef testvalue<VoidPointer, false> value_type;
static const int random_init[6] = { 3, 2, 4, 1, 5, 2 };
std::vector<testvalue<VoidPointer, false> > data (6);
for (int i = 0; i < 6; ++i)
data[i].value_ = random_init[i];
test_avl_set < typename detail::get_base_value_traits
< value_type
, typename value_type::avl_set_base_hook_t
>::type
>::test_all(data);
test_avl_set < typename detail::get_member_value_traits
< value_type
, member_hook< value_type
, typename value_type::avl_set_member_hook_t
, &value_type::avl_set_node_
>
>::type
>::test_all(data);
test_avl_set < typename detail::get_base_value_traits
< value_type
, typename value_type::avl_set_auto_base_hook_t
>::type
>::test_all(data);
test_avl_set < typename detail::get_member_value_traits
< value_type
, member_hook< value_type
, typename value_type::avl_set_auto_member_hook_t
, &value_type::avl_set_auto_node_
>
>::type
>::test_all(data);
return 0;
}
};
int main( int, char* [] )
{
test_main_template<void*, false>()();
test_main_template<smart_ptr<void>, false>()();
test_main_template<void*, true>()();
test_main_template<smart_ptr<void>, true>()();
return boost::report_errors();
}
#include <boost/intrusive/detail/config_end.hpp>

View File

@@ -19,6 +19,7 @@
#include <boost/intrusive/slist_hook.hpp> #include <boost/intrusive/slist_hook.hpp>
#include <boost/intrusive/unordered_set_hook.hpp> #include <boost/intrusive/unordered_set_hook.hpp>
#include <boost/intrusive/splay_set_hook.hpp> #include <boost/intrusive/splay_set_hook.hpp>
#include <boost/intrusive/avl_set_hook.hpp>
#include <boost/intrusive/options.hpp> #include <boost/intrusive/options.hpp>
#include <boost/functional/hash.hpp> #include <boost/functional/hash.hpp>
#include "smart_ptr.hpp" #include "smart_ptr.hpp"
@@ -60,6 +61,22 @@ template<class VoidPointer>
struct splay_set_auto_member_hook_type struct splay_set_auto_member_hook_type
{ typedef splay_set_member_hook<link_mode<auto_unlink>, void_pointer<VoidPointer> > type; }; { typedef splay_set_member_hook<link_mode<auto_unlink>, void_pointer<VoidPointer> > type; };
template<class VoidPointer>
struct avl_set_base_hook_type
{ typedef avl_set_base_hook<void_pointer<VoidPointer> > type; };
template<class VoidPointer>
struct avl_set_auto_base_hook_type
{ typedef avl_set_base_hook<link_mode<auto_unlink>, void_pointer<VoidPointer>, tag<my_tag>, optimize_size<true> > type; };
template<class VoidPointer>
struct avl_set_member_hook_type
{ typedef avl_set_member_hook<void_pointer<VoidPointer>, optimize_size<true> > type; };
template<class VoidPointer>
struct avl_set_auto_member_hook_type
{ typedef avl_set_member_hook<link_mode<auto_unlink>, void_pointer<VoidPointer> > type; };
template<class VoidPointer> template<class VoidPointer>
struct list_base_hook_type struct list_base_hook_type
{ typedef list_base_hook<void_pointer<VoidPointer> > type; }; { typedef list_base_hook<void_pointer<VoidPointer> > type; };
@@ -114,6 +131,8 @@ struct testvalue
, set_auto_base_hook_type<VoidPointer>::type , set_auto_base_hook_type<VoidPointer>::type
, splay_set_base_hook_type<VoidPointer>::type , splay_set_base_hook_type<VoidPointer>::type
, splay_set_auto_base_hook_type<VoidPointer>::type , splay_set_auto_base_hook_type<VoidPointer>::type
, avl_set_base_hook_type<VoidPointer>::type
, avl_set_auto_base_hook_type<VoidPointer>::type
, list_base_hook_type<VoidPointer>::type , list_base_hook_type<VoidPointer>::type
, list_auto_base_hook_type<VoidPointer>::type , list_auto_base_hook_type<VoidPointer>::type
, slist_base_hook_type<VoidPointer>::type , slist_base_hook_type<VoidPointer>::type
@@ -131,6 +150,11 @@ struct testvalue
typedef typename splay_set_auto_member_hook_type<VoidPointer>::type splay_set_auto_member_hook_t; typedef typename splay_set_auto_member_hook_type<VoidPointer>::type splay_set_auto_member_hook_t;
typedef typename splay_set_member_hook_type<VoidPointer>::type splay_set_member_hook_t; typedef typename splay_set_member_hook_type<VoidPointer>::type splay_set_member_hook_t;
typedef typename avl_set_auto_base_hook_type<VoidPointer>::type avl_set_auto_base_hook_t;
typedef typename avl_set_base_hook_type<VoidPointer>::type avl_set_base_hook_t;
typedef typename avl_set_auto_member_hook_type<VoidPointer>::type avl_set_auto_member_hook_t;
typedef typename avl_set_member_hook_type<VoidPointer>::type avl_set_member_hook_t;
typedef typename uset_auto_base_hook_type<VoidPointer>::type unordered_set_auto_base_hook_t; typedef typename uset_auto_base_hook_type<VoidPointer>::type unordered_set_auto_base_hook_t;
typedef typename uset_base_hook_type<VoidPointer>::type unordered_set_base_hook_t; typedef typename uset_base_hook_type<VoidPointer>::type unordered_set_base_hook_t;
typedef typename uset_auto_member_hook_type<VoidPointer>::type unordered_set_auto_member_hook_t; typedef typename uset_auto_member_hook_type<VoidPointer>::type unordered_set_auto_member_hook_t;
@@ -154,6 +178,10 @@ struct testvalue
splay_set_member_hook_t splay_set_node_; splay_set_member_hook_t splay_set_node_;
splay_set_auto_member_hook_t splay_set_auto_node_; splay_set_auto_member_hook_t splay_set_auto_node_;
//AvlSet members
avl_set_member_hook_t avl_set_node_;
avl_set_auto_member_hook_t avl_set_auto_node_;
//Unordered set members //Unordered set members
unordered_set_member_hook_t unordered_set_node_; unordered_set_member_hook_t unordered_set_node_;
unordered_set_auto_member_hook_t unordered_set_auto_node_; unordered_set_auto_member_hook_t unordered_set_auto_node_;
@@ -196,6 +224,11 @@ struct testvalue
this->splay_set_node_ = src.splay_set_node_; this->splay_set_node_ = src.splay_set_node_;
this->splay_set_auto_node_ = src.splay_set_auto_node_; this->splay_set_auto_node_ = src.splay_set_auto_node_;
avl_set_base_hook_t::operator=(src);
avl_set_auto_base_hook_t::operator=(src);
this->avl_set_node_ = src.avl_set_node_;
this->avl_set_auto_node_ = src.avl_set_auto_node_;
unordered_set_base_hook_t::operator=(src); unordered_set_base_hook_t::operator=(src);
unordered_set_auto_base_hook_t::operator=(src); unordered_set_auto_base_hook_t::operator=(src);
this->unordered_set_node_ = src.unordered_set_node_; this->unordered_set_node_ = src.unordered_set_node_;
@@ -229,6 +262,12 @@ struct testvalue
splay_set_node_.swap_nodes(other.splay_set_node_); splay_set_node_.swap_nodes(other.splay_set_node_);
splay_set_auto_node_.swap_nodes(other.splay_set_auto_node_); splay_set_auto_node_.swap_nodes(other.splay_set_auto_node_);
//AvlSet
avl_set_base_hook_t::swap_nodes(other);
avl_set_auto_base_hook_t::swap_nodes(other);
avl_set_node_.swap_nodes(other.avl_set_node_);
avl_set_auto_node_.swap_nodes(other.avl_set_auto_node_);
//Unordered set //Unordered set
unordered_set_base_hook_t::swap_nodes(other); unordered_set_base_hook_t::swap_nodes(other);
unordered_set_auto_base_hook_t::swap_nodes(other); unordered_set_auto_base_hook_t::swap_nodes(other);

View File

@@ -12,6 +12,8 @@
#define BOOST_INTRUSIVE_SMART_PTR_HPP #define BOOST_INTRUSIVE_SMART_PTR_HPP
#include <boost/iterator.hpp> #include <boost/iterator.hpp>
#include <boost/intrusive/pointer_plus_bit.hpp>
#include <boost/intrusive/pointer_plus_2_bits.hpp>
#if (defined _MSC_VER) && (_MSC_VER >= 1200) #if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once # pragma once
@@ -343,4 +345,78 @@ inline smart_ptr<T>
} //namespace intrusive { } //namespace intrusive {
} //namespace boost { } //namespace boost {
namespace boost{
//This is to support embedding a bit in the pointer
//for intrusive containers, saving space
namespace intrusive {
template<std::size_t N>
struct has_pointer_plus_bit<smart_ptr<void>, N>
{
static const bool value = has_pointer_plus_bit<void*, N>::value;
};
//Specialization
template<class T>
struct pointer_plus_bit<smart_ptr<T> >
{
typedef smart_ptr<T> pointer;
static pointer get_pointer(const pointer &n)
{ return pointer_plus_bit<T*>::get_pointer(n.get()); }
static void set_pointer(pointer &n, pointer p)
{
T *raw_n = n.get();
pointer_plus_bit<T*>::set_pointer(raw_n, p.get());
n = raw_n;
}
static bool get_bit(const pointer &n)
{ return pointer_plus_bit<T*>::get_bit(n.get()); }
static void set_bit(pointer &n, bool c)
{
T *raw_n = n.get();
pointer_plus_bit<T*>::set_bit(raw_n, c);
n = raw_n;
}
};
template<std::size_t N>
struct has_pointer_plus_2_bits<smart_ptr<void>, N>
{
static const bool value = has_pointer_plus_2_bits<void*, N>::value;
};
template<class T>
struct pointer_plus_2_bits<smart_ptr<T> >
{
typedef smart_ptr<T> pointer;
static pointer get_pointer(const pointer &n)
{ return pointer_plus_2_bits<T*>::get_pointer(n.get()); }
static void set_pointer(pointer &n, pointer p)
{
T *raw_n = n.get();
pointer_plus_2_bits<T*>::set_pointer(raw_n, p.get());
n = raw_n;
}
static std::size_t get_bits(const pointer &n)
{ return pointer_plus_2_bits<T*>::get_bits(n.get()); }
static void set_bits(pointer &n, std::size_t c)
{
T *raw_n = n.get();
pointer_plus_2_bits<T*>::set_bits(raw_n, c);
n = raw_n;
}
};
} //namespace intrusive
} //namespace boost{
#endif //#ifndef BOOST_INTRUSIVE_SMART_PTR_HPP #endif //#ifndef BOOST_INTRUSIVE_SMART_PTR_HPP