forked from boostorg/intrusive
Changes introduced by the new intrusive version.
[SVN r39550]
This commit is contained in:
@ -10,7 +10,7 @@
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//[doc_advanced_value_traits_code
|
||||
#include <boost/intrusive/linking_policy.hpp>
|
||||
#include <boost/intrusive/link_mode.hpp>
|
||||
#include <boost/intrusive/list.hpp>
|
||||
#include <vector>
|
||||
|
||||
@ -46,7 +46,7 @@ struct simple_node_traits
|
||||
|
||||
//A templatized value traits for value_1 and value_2
|
||||
template<class ValueType>
|
||||
struct value_traits
|
||||
struct simple_value_traits
|
||||
{
|
||||
typedef simple_node_traits node_traits;
|
||||
typedef node_traits::node_ptr node_ptr;
|
||||
@ -54,7 +54,7 @@ struct value_traits
|
||||
typedef ValueType value_type;
|
||||
typedef ValueType * pointer;
|
||||
typedef const ValueType * const_pointer;
|
||||
enum { linking_policy = boost::intrusive::normal_link };
|
||||
static const boost::intrusive::link_mode_type link_mode = boost::intrusive::normal_link;
|
||||
static node_ptr to_node_ptr (value_type &value) { return node_ptr(&value); }
|
||||
static const_node_ptr to_node_ptr (const value_type &value) { return const_node_ptr(&value); }
|
||||
static pointer to_value_ptr(node_ptr n) { return static_cast<value_type*>(n); }
|
||||
@ -65,8 +65,10 @@ struct value_traits
|
||||
//[doc_advanced_value_traits_containers
|
||||
//Now define two intrusive lists. Both lists will use the same algorithms:
|
||||
// circular_list_algorithms<simple_node_traits>
|
||||
typedef boost::intrusive::list <value_traits<value_1> > Value1List;
|
||||
typedef boost::intrusive::list <value_traits<value_2> > Value2List;
|
||||
|
||||
using namespace boost::intrusive;
|
||||
typedef list <value_1, value_traits<simple_value_traits<value_1> > > Value1List;
|
||||
typedef list <value_2, value_traits<simple_value_traits<value_2> > > Value2List;
|
||||
//]
|
||||
|
||||
//[doc_advanced_value_traits_test
|
||||
|
@ -9,7 +9,7 @@
|
||||
// See http://www.boost.org/libs/intrusive for documentation.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#include <boost/intrusive/linking_policy.hpp>
|
||||
#include <boost/intrusive/link_mode.hpp>
|
||||
#include <boost/intrusive/list.hpp>
|
||||
#include <boost/intrusive/member_value_traits.hpp>
|
||||
#include <vector>
|
||||
@ -57,8 +57,8 @@ typedef member_value_traits
|
||||
|
||||
//Now define two intrusive lists. Both lists will use the same algorithms:
|
||||
// circular_list_algorithms<simple_node_traits>
|
||||
typedef boost::intrusive::list <ValueTraits1> Value1List;
|
||||
typedef boost::intrusive::list <ValueTraits2> Value2List;
|
||||
typedef list <value_1, value_traits<ValueTraits1> > Value1List;
|
||||
typedef list <value_2, value_traits<ValueTraits2> > Value2List;
|
||||
//]
|
||||
|
||||
//[doc_advanced_value_traits2_test
|
||||
|
@ -51,24 +51,21 @@ class Expensive : public set_base_hook<>, public unordered_set_base_hook<>
|
||||
};
|
||||
|
||||
// A set and unordered_set that store Expensive objects
|
||||
typedef set<set_base_hook<>::value_traits<Expensive> > Set;
|
||||
typedef unordered_set<unordered_set_base_hook<>::
|
||||
value_traits<Expensive> > UnorderedSet;
|
||||
typedef set<Expensive> Set;
|
||||
typedef unordered_set<Expensive> UnorderedSet;
|
||||
|
||||
// Search functions
|
||||
Expensive *get_from_set(const char* key, Set &set)
|
||||
Expensive *get_from_set(const char* key, Set &set_object)
|
||||
{
|
||||
Set::iterator it = set.find(Expensive(key));
|
||||
if( it == set.end() ) return 0;
|
||||
Set::iterator it = set_object.find(Expensive(key));
|
||||
if( it == set_object.end() ) return 0;
|
||||
return &*it;
|
||||
}
|
||||
|
||||
Expensive *get_from_unordered_set
|
||||
(const char* key, UnorderedSet &unordered_set)
|
||||
Expensive *get_from_uset(const char* key, UnorderedSet &uset_object)
|
||||
{
|
||||
UnorderedSet::iterator it =
|
||||
unordered_set.find(Expensive (key));
|
||||
if( it == unordered_set.end() ) return 0;
|
||||
UnorderedSet::iterator it = uset_object.find(Expensive (key));
|
||||
if( it == uset_object.end() ) return 0;
|
||||
return &*it;
|
||||
}
|
||||
//]
|
||||
@ -94,38 +91,35 @@ struct StrExpEqual
|
||||
};
|
||||
|
||||
// Optimized search functions
|
||||
Expensive *get_from_set_optimized(const char* key, Set &set)
|
||||
Expensive *get_from_set_optimized(const char* key, Set &set_object)
|
||||
{
|
||||
Set::iterator it = set.find(key, StrExpComp());
|
||||
if( it == set.end() ) return 0;
|
||||
Set::iterator it = set_object.find(key, StrExpComp());
|
||||
if( it == set_object.end() ) return 0;
|
||||
return &*it;
|
||||
}
|
||||
|
||||
Expensive *get_from_unordered_set_optimized
|
||||
(const char* key, UnorderedSet &unordered_set)
|
||||
Expensive *get_from_uset_optimized(const char* key, UnorderedSet &uset_object)
|
||||
{
|
||||
UnorderedSet::iterator it =
|
||||
unordered_set.find(key, StrHasher(), StrExpEqual());
|
||||
if( it == unordered_set.end() ) return 0;
|
||||
UnorderedSet::iterator it = uset_object.find(key, StrHasher(), StrExpEqual());
|
||||
if( it == uset_object.end() ) return 0;
|
||||
return &*it;
|
||||
}
|
||||
//]
|
||||
|
||||
//[doc_assoc_optimized_code_normal_insert
|
||||
// Insertion functions
|
||||
bool insert_to_set(const char* key, Set &set)
|
||||
bool insert_to_set(const char* key, Set &set_object)
|
||||
{
|
||||
Expensive *pobject = new Expensive(key);
|
||||
bool success = set.insert(*pobject).second;
|
||||
bool success = set_object.insert(*pobject).second;
|
||||
if(!success) delete pobject;
|
||||
return success;
|
||||
}
|
||||
|
||||
bool insert_to_unordered_set
|
||||
(const char* key, UnorderedSet &unordered_set)
|
||||
bool insert_to_uset(const char* key, UnorderedSet &uset_object)
|
||||
{
|
||||
Expensive *pobject = new Expensive(key);
|
||||
bool success = unordered_set.insert(*pobject).second;
|
||||
bool success = uset_object.insert(*pobject).second;
|
||||
if(!success) delete pobject;
|
||||
return success;
|
||||
}
|
||||
@ -133,24 +127,20 @@ bool insert_to_unordered_set
|
||||
|
||||
//[doc_assoc_optimized_code_optimized_insert
|
||||
// Optimized insertion functions
|
||||
bool insert_to_set_optimized(const char* key, Set &set)
|
||||
bool insert_to_set_optimized(const char* key, Set &set_object)
|
||||
{
|
||||
Set::insert_commit_data insert_data;
|
||||
bool success = set.insert_check
|
||||
(key, StrExpComp(), insert_data).second;
|
||||
if(success)
|
||||
set.insert_commit(*new Expensive(key), insert_data);
|
||||
bool success = set_object.insert_check(key, StrExpComp(), insert_data).second;
|
||||
if(success) set_object.insert_commit(*new Expensive(key), insert_data);
|
||||
return success;
|
||||
}
|
||||
|
||||
bool insert_to_unordered_set_optimized
|
||||
(const char* key, UnorderedSet &unordered_set)
|
||||
bool insert_to_uset_optimized(const char* key, UnorderedSet &uset_object)
|
||||
{
|
||||
UnorderedSet::insert_commit_data insert_data;
|
||||
bool success = unordered_set.insert_check
|
||||
bool success = uset_object.insert_check
|
||||
(key, StrHasher(), StrExpEqual(), insert_data).second;
|
||||
if(success)
|
||||
unordered_set.insert_commit(*new Expensive(key), insert_data);
|
||||
if(success) uset_object.insert_commit(*new Expensive(key), insert_data);
|
||||
return success;
|
||||
}
|
||||
//]
|
||||
@ -159,7 +149,7 @@ int main()
|
||||
{
|
||||
Set set;
|
||||
UnorderedSet::bucket_type buckets[10];
|
||||
UnorderedSet unordered_set(buckets, 10);
|
||||
UnorderedSet unordered_set(UnorderedSet::bucket_traits(buckets, 10));
|
||||
|
||||
const char * const expensive_key
|
||||
= "A long string that avoids small string optimization";
|
||||
@ -170,7 +160,7 @@ int main()
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(get_from_unordered_set(expensive_key, unordered_set)){
|
||||
if(get_from_uset(expensive_key, unordered_set)){
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -178,7 +168,7 @@ int main()
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(get_from_unordered_set_optimized(expensive_key, unordered_set)){
|
||||
if(get_from_uset_optimized(expensive_key, unordered_set)){
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -189,7 +179,7 @@ int main()
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(!get_from_unordered_set(expensive_key, unordered_set)){
|
||||
if(!get_from_uset(expensive_key, unordered_set)){
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -197,7 +187,7 @@ int main()
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(!get_from_unordered_set_optimized(expensive_key, unordered_set)){
|
||||
if(!get_from_uset_optimized(expensive_key, unordered_set)){
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -208,7 +198,7 @@ int main()
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(!insert_to_unordered_set(expensive_key, unordered_set)){
|
||||
if(!insert_to_uset(expensive_key, unordered_set)){
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -228,7 +218,7 @@ int main()
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(!insert_to_unordered_set_optimized(expensive_key, unordered_set)){
|
||||
if(!insert_to_uset_optimized(expensive_key, unordered_set)){
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -251,7 +241,7 @@ int main()
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(insert_to_unordered_set(expensive_key, unordered_set)){
|
||||
if(insert_to_uset(expensive_key, unordered_set)){
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -259,7 +249,7 @@ int main()
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(insert_to_unordered_set_optimized(expensive_key, unordered_set)){
|
||||
if(insert_to_uset_optimized(expensive_key, unordered_set)){
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -15,39 +15,38 @@
|
||||
|
||||
using namespace boost::intrusive;
|
||||
|
||||
class MyClass : public list_base_hook<tag, auto_unlink>
|
||||
typedef list_base_hook<link_mode<auto_unlink> > auto_unlink_hook;
|
||||
|
||||
class MyClass : public auto_unlink_hook
|
||||
//This hook removes the node in the destructor
|
||||
{
|
||||
int int_;
|
||||
|
||||
public:
|
||||
MyClass(int i = 0) : int_(i) {}
|
||||
void unlink() { list_base_hook<tag, auto_unlink>::unlink(); }
|
||||
bool is_linked() { return list_base_hook<tag, auto_unlink>::is_linked(); }
|
||||
int get() const { return int_; }
|
||||
void unlink() { auto_unlink_hook::unlink(); }
|
||||
bool is_linked() { return auto_unlink_hook::is_linked(); }
|
||||
};
|
||||
|
||||
//Define a list that will store MyClass
|
||||
//using the public base hook
|
||||
//Define a list that will store values using the base hook
|
||||
//The list can't have constant-time size!
|
||||
typedef list< list_base_hook<tag, auto_unlink>::
|
||||
value_traits<MyClass>, false > List;
|
||||
typedef list< MyClass, constant_time_size<false> > List;
|
||||
|
||||
int main()
|
||||
{
|
||||
//Create the list
|
||||
List list;
|
||||
List l;
|
||||
{
|
||||
//Create myclass and check it's linked
|
||||
MyClass myclass;
|
||||
assert(myclass.is_linked() == false);
|
||||
|
||||
//Insert the object
|
||||
list.push_back(myclass);
|
||||
l.push_back(myclass);
|
||||
|
||||
//Check that we have inserted the object
|
||||
assert(list.empty() == false);
|
||||
assert(&list.front() == &myclass);
|
||||
assert(l.empty() == false);
|
||||
assert(&l.front() == &myclass);
|
||||
assert(myclass.is_linked() == true);
|
||||
|
||||
//Now myclass' destructor will unlink it
|
||||
@ -55,7 +54,7 @@ int main()
|
||||
}
|
||||
|
||||
//Check auto-unlink has been executed
|
||||
assert(list.empty() == true);
|
||||
assert(l.empty() == true);
|
||||
|
||||
{
|
||||
//Now test the unlink() function
|
||||
@ -65,18 +64,18 @@ int main()
|
||||
assert(myclass.is_linked() == false);
|
||||
|
||||
//Insert the object
|
||||
list.push_back(myclass);
|
||||
l.push_back(myclass);
|
||||
|
||||
//Check that we have inserted the object
|
||||
assert(list.empty() == false);
|
||||
assert(&list.front() == &myclass);
|
||||
assert(l.empty() == false);
|
||||
assert(&l.front() == &myclass);
|
||||
assert(myclass.is_linked() == true);
|
||||
|
||||
//Now unlink the node
|
||||
myclass.unlink();
|
||||
|
||||
//Check auto-unlink has been executed
|
||||
assert(list.empty() == true);
|
||||
assert(l.empty() == true);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
83
example/doc_bucket_traits.cpp
Normal file
83
example/doc_bucket_traits.cpp
Normal file
@ -0,0 +1,83 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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_bucket_traits
|
||||
#include <boost/intrusive/unordered_set.hpp>
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include <vector>
|
||||
|
||||
using namespace boost::intrusive;
|
||||
|
||||
//A class to be inserted in an unordered_set
|
||||
class MyClass : public unordered_set_base_hook<>
|
||||
{
|
||||
int int_;
|
||||
|
||||
public:
|
||||
MyClass(int i = 0) : int_(i)
|
||||
{}
|
||||
|
||||
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_); }
|
||||
};
|
||||
|
||||
//Define the base hook option
|
||||
typedef base_hook< unordered_set_base_hook<> > BaseHookOption;
|
||||
|
||||
//Obtain the types of the bucket and the bucket pointer
|
||||
typedef unordered_bucket<BaseHookOption>::type BucketType;
|
||||
typedef unordered_bucket_ptr<BaseHookOption>::type BucketPtr;
|
||||
|
||||
//The custom bucket traits.
|
||||
class custom_bucket_traits
|
||||
{
|
||||
public:
|
||||
static const int NumBuckets = 100;
|
||||
|
||||
custom_bucket_traits(BucketPtr buckets)
|
||||
: buckets_(buckets)
|
||||
{}
|
||||
|
||||
//Functions to be implemented by custom bucket traits
|
||||
BucketPtr bucket_begin() const { return buckets_; }
|
||||
std::size_t bucket_count() const { return NumBuckets;}
|
||||
|
||||
private:
|
||||
BucketPtr buckets_;
|
||||
};
|
||||
|
||||
//Define the container using the custom bucket traits
|
||||
typedef unordered_set<MyClass, bucket_traits<custom_bucket_traits> > BucketTraitsUset;
|
||||
|
||||
int main()
|
||||
{
|
||||
typedef std::vector<MyClass>::iterator VectIt;
|
||||
std::vector<MyClass> values;
|
||||
|
||||
//Fill values
|
||||
for(int i = 0; i < 100; ++i) values.push_back(MyClass(i));
|
||||
|
||||
//Now create the bucket array and the custom bucket traits object
|
||||
BucketType buckets[custom_bucket_traits::NumBuckets];
|
||||
custom_bucket_traits btraits(buckets);
|
||||
|
||||
//Now create the unordered set
|
||||
BucketTraitsUset uset(btraits);
|
||||
|
||||
//Insert the values in the unordered set
|
||||
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it)
|
||||
uset.insert(*it);
|
||||
|
||||
return 0;
|
||||
}
|
||||
//]
|
@ -14,9 +14,10 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
using namespace boost::intrusive;
|
||||
|
||||
//A class that can be inserted in an intrusive list
|
||||
class my_class
|
||||
: public boost::intrusive::list_base_hook<>
|
||||
class my_class : public list_base_hook<>
|
||||
{
|
||||
public:
|
||||
friend bool operator==(const my_class &a, const my_class &b)
|
||||
@ -28,20 +29,18 @@ class my_class
|
||||
};
|
||||
|
||||
//Definition of the intrusive list
|
||||
typedef boost::intrusive::list< my_class::value_traits<my_class> > my_class_list;
|
||||
typedef list<my_class> my_class_list;
|
||||
|
||||
//Cloner object function
|
||||
class new_cloner
|
||||
struct new_cloner
|
||||
{
|
||||
public:
|
||||
my_class *operator()(const my_class &clone_this)
|
||||
{ return new my_class(clone_this); }
|
||||
};
|
||||
|
||||
//The disposer object function
|
||||
class delete_disposer
|
||||
struct delete_disposer
|
||||
{
|
||||
public:
|
||||
void operator()(my_class *delete_this)
|
||||
{ delete delete_this; }
|
||||
};
|
||||
@ -54,9 +53,8 @@ int main()
|
||||
//Fill all the nodes and insert them in the list
|
||||
my_class_list list;
|
||||
|
||||
for(int i = 0; i < MaxElem; ++i){
|
||||
nodes[i].int_ = i;
|
||||
}
|
||||
for(int i = 0; i < MaxElem; ++i) nodes[i].int_ = i;
|
||||
|
||||
list.insert(list.end(), nodes.begin(), nodes.end());
|
||||
|
||||
//Now clone "list" using "new" and "delete" object functions
|
||||
@ -64,12 +62,10 @@ int main()
|
||||
cloned_list.clone_from(list, new_cloner(), delete_disposer());
|
||||
|
||||
//Test that both are equal
|
||||
if(cloned_list != list){
|
||||
if(cloned_list != list)
|
||||
std::cout << "Both lists are different" << std::endl;
|
||||
}
|
||||
else{
|
||||
else
|
||||
std::cout << "Both lists are equal" << std::endl;
|
||||
}
|
||||
|
||||
//Don't forget to free the memory from the second list
|
||||
cloned_list.clear_and_dispose(delete_disposer());
|
||||
|
@ -12,9 +12,10 @@
|
||||
//[doc_entity_code
|
||||
#include <boost/intrusive/list.hpp>
|
||||
|
||||
using namespace boost::intrusive;
|
||||
|
||||
//A class that can be inserted in an intrusive list
|
||||
class entity
|
||||
: public boost::intrusive::list_base_hook<>
|
||||
class entity : public list_base_hook<>
|
||||
{
|
||||
public:
|
||||
virtual ~entity();
|
||||
@ -26,25 +27,25 @@ class some_entity : public entity
|
||||
{/**/};
|
||||
|
||||
//Definition of the intrusive list
|
||||
typedef boost::intrusive::list< entity::value_traits<entity> > entity_list;
|
||||
typedef list<entity> entity_list;
|
||||
|
||||
//A global list
|
||||
entity_list list;
|
||||
entity_list global_list;
|
||||
|
||||
//The destructor removes itself from the list
|
||||
//The destructor removes itself from the global list
|
||||
entity::~entity()
|
||||
{ list.erase(entity_list::iterator_to(*this)); }
|
||||
{ global_list.erase(entity_list::s_iterator_to(*this)); }
|
||||
|
||||
//Function to insert a new "some_entity" in the list
|
||||
//Function to insert a new "some_entity" in the global list
|
||||
void insert_some_entity()
|
||||
{ list.push_back (*new some_entity(/*...*/)); }
|
||||
{ global_list.push_back (*new some_entity(/*...*/)); }
|
||||
|
||||
//Function to clear an entity from the intrusive list
|
||||
//Function to clear an entity from the intrusive global list
|
||||
void clear_list ()
|
||||
{
|
||||
// entity's destructor removes itself from the list implicitly
|
||||
while (!list.empty())
|
||||
delete &list.front();
|
||||
// entity's destructor removes itself from the global list implicitly
|
||||
while (!global_list.empty())
|
||||
delete &global_list.front();
|
||||
}
|
||||
|
||||
int main()
|
||||
@ -52,7 +53,7 @@ int main()
|
||||
//Insert some new entities
|
||||
insert_some_entity();
|
||||
insert_some_entity();
|
||||
//list's destructor will free objects
|
||||
//global_list's destructor will free objects
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -12,9 +12,10 @@
|
||||
//[doc_erasing_and_disposing
|
||||
#include <boost/intrusive/list.hpp>
|
||||
|
||||
using namespace boost::intrusive;
|
||||
|
||||
//A class that can be inserted in an intrusive list
|
||||
class my_class
|
||||
: public boost::intrusive::list_base_hook<>
|
||||
class my_class : public list_base_hook<>
|
||||
{
|
||||
public:
|
||||
my_class(int i)
|
||||
@ -26,20 +27,18 @@ class my_class
|
||||
};
|
||||
|
||||
//Definition of the intrusive list
|
||||
typedef boost::intrusive::list< my_class::value_traits<my_class> > my_class_list;
|
||||
typedef list<my_class> my_class_list;
|
||||
|
||||
//The predicate function
|
||||
class is_even
|
||||
struct is_even
|
||||
{
|
||||
public:
|
||||
bool operator()(const my_class &c) const
|
||||
{ return 0 == (c.int_ % 2); }
|
||||
};
|
||||
|
||||
//The disposer object function
|
||||
class delete_disposer
|
||||
struct delete_disposer
|
||||
{
|
||||
public:
|
||||
void operator()(my_class *delete_this)
|
||||
{ delete delete_this; }
|
||||
};
|
||||
@ -53,9 +52,7 @@ int main()
|
||||
|
||||
try{
|
||||
//Insert new objects in the container
|
||||
for(int i = 0; i < MaxElem; ++i){
|
||||
list.push_back(*new my_class(i));
|
||||
}
|
||||
for(int i = 0; i < MaxElem; ++i) list.push_back(*new my_class(i));
|
||||
|
||||
//Now use remove_and_dispose_if to erase and delete the objects
|
||||
list.remove_and_dispose_if(is_even(), delete_disposer());
|
||||
|
129
example/doc_external_value_traits.cpp
Normal file
129
example/doc_external_value_traits.cpp
Normal file
@ -0,0 +1,129 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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_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;
|
||||
}
|
||||
//]
|
@ -15,7 +15,7 @@
|
||||
|
||||
using namespace boost::intrusive;
|
||||
|
||||
class MyClass : public list_base_hook<>
|
||||
class MyClass : public list_base_hook<>
|
||||
{
|
||||
int int_;
|
||||
|
||||
@ -23,62 +23,51 @@ class MyClass : public list_base_hook<>
|
||||
list_member_hook<> member_hook_;
|
||||
|
||||
MyClass(int i) : int_(i) {}
|
||||
int get() const { return int_; }
|
||||
};
|
||||
|
||||
//Define a list that will store MyClass using the base hook
|
||||
typedef list< list_base_hook<>::value_traits<MyClass> >
|
||||
BaseList;
|
||||
typedef list<MyClass> BaseList;
|
||||
|
||||
//Define a list that will store MyClass using the member hook
|
||||
typedef list< list_member_hook<>::
|
||||
value_traits<MyClass, &MyClass::member_hook_>
|
||||
> MemberList;
|
||||
typedef member_hook
|
||||
< MyClass, list_member_hook<>, &MyClass::member_hook_> MemberOption;
|
||||
typedef list<MyClass, MemberOption> MemberList;
|
||||
|
||||
int main()
|
||||
{
|
||||
typedef std::vector<MyClass> Vect;
|
||||
typedef Vect::iterator VectIt;
|
||||
typedef Vect::reverse_iterator VectRit;
|
||||
typedef std::vector<MyClass>::iterator VectIt;
|
||||
typedef std::vector<MyClass>::reverse_iterator VectRit;
|
||||
|
||||
//Create several MyClass objects, each one
|
||||
//with a different internal number
|
||||
Vect myclassvector;
|
||||
for(int i = 0; i < 100; ++i)
|
||||
myclassvector.push_back(MyClass(i));
|
||||
//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));
|
||||
|
||||
BaseList baselist;
|
||||
MemberList memberlist;
|
||||
|
||||
//Now insert them in the reverse order
|
||||
//in the base hook intrusive list
|
||||
for(VectIt it(myclassvector.begin()), itend(myclassvector.end())
|
||||
//Now insert them in the reverse order in the base hook list
|
||||
for(VectIt it(values.begin()), itend(values.end())
|
||||
; it != itend ; ++it){
|
||||
baselist.push_front(*it);
|
||||
}
|
||||
|
||||
//Now insert them in the same order as in vector in the
|
||||
//member hook intrusive list
|
||||
for(VectIt it(myclassvector.begin()), itend(myclassvector.end())
|
||||
; it != itend; ++it){
|
||||
//Now insert them in the same order as in vector in the member hook list
|
||||
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it)
|
||||
memberlist.push_back(*it);
|
||||
}
|
||||
|
||||
//Now test lists
|
||||
{
|
||||
BaseList::reverse_iterator rbit(baselist.rbegin()), rbitend(baselist.rend());
|
||||
MemberList::iterator mit(memberlist.begin()), mitend(memberlist.end());
|
||||
VectIt it(myclassvector.begin()), itend(myclassvector.end());
|
||||
VectIt it(values.begin()), itend(values.end());
|
||||
|
||||
//Test the objects inserted in the base hook list
|
||||
for(; it != itend; ++it, ++rbit){
|
||||
for(; it != itend; ++it, ++rbit)
|
||||
if(&*rbit != &*it) return 1;
|
||||
}
|
||||
|
||||
//Test the objects inserted in the member hook list
|
||||
for(it = myclassvector.begin(); it != itend; ++it, ++mit){
|
||||
for(it = values.begin(); it != itend; ++it, ++mit)
|
||||
if(&*mit != &*it) return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -15,43 +15,44 @@
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include <vector>
|
||||
|
||||
using namespace boost::intrusive;
|
||||
|
||||
class intrusive_data
|
||||
{
|
||||
int data_id_;
|
||||
public:
|
||||
|
||||
int get() const { return data_id_; }
|
||||
void set(int id) { data_id_ = id; }
|
||||
|
||||
//This class can be inserted in an intrusive list
|
||||
typedef boost::intrusive::
|
||||
list_member_hook<> list_member_hook_t;
|
||||
list_member_hook_t list_hook_;
|
||||
list_member_hook<> list_hook_;
|
||||
|
||||
//This class can be inserted in an intrusive unordered_set
|
||||
typedef boost::intrusive::
|
||||
unordered_set_member_hook<> unordered_set_member_hook_t;
|
||||
unordered_set_member_hook_t unordered_set_hook_;
|
||||
unordered_set_member_hook<> unordered_set_hook_;
|
||||
|
||||
//Comparison operators
|
||||
friend bool operator==(const intrusive_data &a, const intrusive_data &b)
|
||||
{ return a.get() == b.get(); }
|
||||
{ return a.data_id_ == b.data_id_; }
|
||||
|
||||
friend bool operator!=(const intrusive_data &a, const intrusive_data &b)
|
||||
{ return a.get() != b.get(); }
|
||||
{ return a.data_id_ != b.data_id_; }
|
||||
|
||||
//The hash function
|
||||
friend std::size_t hash_value(const intrusive_data &i)
|
||||
{ return boost::hash<int>()(i.data_id_); }
|
||||
};
|
||||
|
||||
//The hash function
|
||||
std::size_t hash_value(const intrusive_data &i)
|
||||
{ return boost::hash<int>()(i.get()); }
|
||||
|
||||
//Definition of the intrusive list that will hold intrusive_data
|
||||
typedef boost::intrusive::list< intrusive_data::list_member_hook_t::
|
||||
value_traits<intrusive_data, &intrusive_data::list_hook_> > list_t;
|
||||
typedef member_hook<intrusive_data, list_member_hook<>
|
||||
, &intrusive_data::list_hook_> MemberListOption;
|
||||
typedef list<intrusive_data, MemberListOption> list_t;
|
||||
|
||||
//Definition of the intrusive unordered_set that will hold intrusive_data
|
||||
typedef boost::intrusive::unordered_set< intrusive_data::unordered_set_member_hook_t::
|
||||
value_traits<intrusive_data, &intrusive_data::unordered_set_hook_> > unordered_set_t;
|
||||
typedef member_hook
|
||||
< intrusive_data, unordered_set_member_hook<>
|
||||
, &intrusive_data::unordered_set_hook_> MemberUsetOption;
|
||||
typedef boost::intrusive::unordered_set
|
||||
< intrusive_data, MemberUsetOption> unordered_set_t;
|
||||
|
||||
int main()
|
||||
{
|
||||
@ -62,30 +63,32 @@ int main()
|
||||
//Declare the intrusive containers
|
||||
list_t list;
|
||||
unordered_set_t::bucket_type buckets[MaxElem];
|
||||
unordered_set_t unordered_set(buckets, MaxElem);
|
||||
unordered_set_t unordered_set
|
||||
(unordered_set_t::bucket_traits(buckets, MaxElem));
|
||||
|
||||
//Initialize all the nodes
|
||||
for(int i = 0; i < MaxElem; ++i)
|
||||
nodes[i].set(i);
|
||||
for(int i = 0; i < MaxElem; ++i) nodes[i].set(i);
|
||||
|
||||
//Now insert them in both intrusive containers
|
||||
list.insert(list.end(), nodes.begin(), nodes.end());
|
||||
unordered_set.insert(nodes.begin(), nodes.end());
|
||||
|
||||
//Now check list::iterator_to
|
||||
//which is an static member function
|
||||
//Now check the iterator_to function
|
||||
list_t::iterator list_it(list.begin());
|
||||
for(int i = 0; i < MaxElem; ++i, ++list_it)
|
||||
if(list_t::iterator_to(nodes[i]) != list_it)
|
||||
if(list.iterator_to(nodes[i]) != list_it ||
|
||||
list_t::s_iterator_to(nodes[i]) != list_it)
|
||||
return 1;
|
||||
|
||||
//Now check unordered_set::iterator_to (which is a member function)
|
||||
//and unordered_set::local_current (which is an static member function)
|
||||
//Now check unordered_set::s_iterator_to (which is a member function)
|
||||
//and unordered_set::s_local_iterator_to (which is an static member function)
|
||||
unordered_set_t::iterator unordered_set_it(unordered_set.begin());
|
||||
for(int i = 0; i < MaxElem; ++i, ++unordered_set_it){
|
||||
if(unordered_set.iterator_to(nodes[i]) != unordered_set.find(nodes[i]))
|
||||
for(int i = 0; i < MaxElem; ++i){
|
||||
unordered_set_it = unordered_set.find(nodes[i]);
|
||||
if(unordered_set.iterator_to(nodes[i]) != unordered_set_it)
|
||||
return 1;
|
||||
if(*unordered_set_t::local_iterator_to(nodes[i]) != *unordered_set.find(nodes[i]))
|
||||
if(*unordered_set.local_iterator_to(nodes[i]) != *unordered_set_it ||
|
||||
*unordered_set_t::s_local_iterator_to(nodes[i]) != *unordered_set_it )
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
using namespace boost::intrusive;
|
||||
|
||||
class MyClass : public list_base_hook<> //This is a derivation hook
|
||||
class MyClass : public list_base_hook<> //This is a derivation hook
|
||||
{
|
||||
int int_;
|
||||
|
||||
@ -26,63 +26,49 @@ class MyClass : public list_base_hook<> //This is a derivation hook
|
||||
MyClass(int i)
|
||||
: int_(i)
|
||||
{}
|
||||
|
||||
int get() const
|
||||
{ return int_; }
|
||||
};
|
||||
|
||||
//Define a list that will store MyClass using the public base hook
|
||||
typedef list< list_base_hook<>::value_traits<MyClass> > BaseList;
|
||||
typedef list<MyClass> BaseList;
|
||||
|
||||
//Define a list that will store MyClass using the public member hook
|
||||
typedef list< list_member_hook<>::value_traits<MyClass, &MyClass::member_hook_> > MemberList;
|
||||
typedef list< MyClass
|
||||
, member_hook< MyClass, list_member_hook<>, &MyClass::member_hook_>
|
||||
> MemberList;
|
||||
|
||||
int main()
|
||||
{
|
||||
typedef std::vector<MyClass> Vect;
|
||||
typedef Vect::iterator VectIt;
|
||||
typedef Vect::reverse_iterator VectRit;
|
||||
typedef std::vector<MyClass>::iterator VectIt;
|
||||
typedef std::vector<MyClass>::reverse_iterator VectRit;
|
||||
|
||||
//Create several MyClass objects, each one
|
||||
//with a different internal number
|
||||
Vect myclassvector;
|
||||
for(int i = 0; i < 100; ++i)
|
||||
myclassvector.push_back(MyClass(i));
|
||||
//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));
|
||||
|
||||
BaseList baselist;
|
||||
MemberList memberlist;
|
||||
|
||||
//Now insert them in the reverse order
|
||||
//in the base hook intrusive list
|
||||
for(VectIt it(myclassvector.begin()), itend(myclassvector.end())
|
||||
; it != itend
|
||||
; ++it){
|
||||
//Now insert them in the reverse order in the base hook list
|
||||
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it)
|
||||
baselist.push_front(*it);
|
||||
}
|
||||
|
||||
//Now insert them in the same order as in vector in the
|
||||
//member hook intrusive list
|
||||
for(VectIt it(myclassvector.begin()), itend(myclassvector.end())
|
||||
; it != itend
|
||||
; ++it){
|
||||
//Now insert them in the same order as in vector in the member hook list
|
||||
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it)
|
||||
memberlist.push_back(*it);
|
||||
}
|
||||
|
||||
//Now test lists
|
||||
{
|
||||
BaseList::reverse_iterator rbit(baselist.rbegin()), rbitend(baselist.rend());
|
||||
MemberList::iterator mit(memberlist.begin()), mitend(memberlist.end());
|
||||
VectIt it(myclassvector.begin()), itend(myclassvector.end());
|
||||
VectIt it(values.begin()), itend(values.end());
|
||||
|
||||
//Test the objects inserted in the base hook list
|
||||
for(; it != itend; ++it, ++rbit){
|
||||
for(; it != itend; ++it, ++rbit)
|
||||
if(&*rbit != &*it) return 1;
|
||||
}
|
||||
|
||||
//Test the objects inserted in the member hook list
|
||||
for(it = myclassvector.begin(); it != itend; ++it, ++mit){
|
||||
for(it = values.begin(); it != itend; ++it, ++mit)
|
||||
if(&*mit != &*it) return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -9,35 +9,49 @@
|
||||
// See http://www.boost.org/libs/intrusive for documentation.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//This is needed to allow concurrent test execution in
|
||||
//several platforms. The shared memory must be unique
|
||||
//for each process...
|
||||
#include <boost/interprocess/detail/os_thread_functions.hpp>
|
||||
#include <sstream>
|
||||
|
||||
const char *get_shared_memory_name()
|
||||
{
|
||||
std::stringstream s;
|
||||
s << "process_" << boost::interprocess::detail::get_current_process_id();
|
||||
static std::string str = s.str();
|
||||
return str.c_str();
|
||||
}
|
||||
|
||||
//[doc_offset_ptr_0
|
||||
#include <boost/intrusive/list.hpp>
|
||||
#include <boost/interprocess/offset_ptr.hpp>
|
||||
|
||||
using namespace boost::intrusive;
|
||||
namespace ip = boost::interprocess;
|
||||
|
||||
class shared_memory_data
|
||||
//Declare the hook with an offset_ptr from Boost.Interprocess
|
||||
//to make this class compatible with shared memory
|
||||
: public list_base_hook< void_pointer< ip::offset_ptr<void> > >
|
||||
{
|
||||
int data_id_;
|
||||
public:
|
||||
|
||||
int get() const { return data_id_; }
|
||||
void set(int id) { data_id_ = id; }
|
||||
|
||||
//Declare the hook with an offset_ptr from Boost.Interprocess
|
||||
//to make this class compatible with shared memory
|
||||
typedef boost::intrusive::list_member_hook
|
||||
< boost::intrusive::safe_link
|
||||
, boost::interprocess::offset_ptr<void> > member_hook_t;
|
||||
member_hook_t list_hook_;
|
||||
};
|
||||
//]
|
||||
|
||||
//[doc_offset_ptr_1
|
||||
#include <boost/interprocess/managed_shared_memory.hpp>
|
||||
#include <boost/interprocess/containers/vector.hpp>
|
||||
#include <boost/interprocess/containers/list.hpp>
|
||||
#include <boost/interprocess/allocators/allocator.hpp>
|
||||
|
||||
//Definition of the shared memory friendly intrusive list
|
||||
typedef boost::intrusive::list< shared_memory_data::member_hook_t::
|
||||
value_traits<shared_memory_data, &shared_memory_data::list_hook_> > shm_list_t;
|
||||
typedef ip::list<shared_memory_data> shm_list_t;
|
||||
|
||||
int main()
|
||||
{
|
||||
@ -45,45 +59,42 @@ int main()
|
||||
//nodes and the container itself must be created in shared memory
|
||||
const int MaxElem = 100;
|
||||
const int ShmSize = 50000;
|
||||
const char *ShmName = "SharedMemoryName";
|
||||
const char *ShmName = get_shared_memory_name();
|
||||
{
|
||||
//Erase all old shared memory
|
||||
ip::shared_memory_object::remove(ShmName);
|
||||
ip::managed_shared_memory shm(ip::create_only, ShmName, ShmSize);
|
||||
|
||||
using namespace boost::interprocess;
|
||||
//Create all nodes in shared memory using a shared memory vector
|
||||
//See Boost.Interprocess documentation for more information on this
|
||||
typedef ip::allocator
|
||||
< shared_memory_data, ip::managed_shared_memory::segment_manager>
|
||||
shm_allocator_t;
|
||||
typedef ip::vector<shared_memory_data, shm_allocator_t> shm_vector_t;
|
||||
shm_allocator_t shm_alloc(shm.get_segment_manager());
|
||||
shm_vector_t *pshm_vect =
|
||||
shm.construct<shm_vector_t>(ip::anonymous_instance)(shm_alloc);
|
||||
pshm_vect->resize(MaxElem);
|
||||
|
||||
//Erase all old shared memory
|
||||
shared_memory_object::remove(ShmName);
|
||||
managed_shared_memory shm(create_only, ShmName, ShmSize);
|
||||
//Initialize all the nodes
|
||||
for(int i = 0; i < MaxElem; ++i) (*pshm_vect)[i].set(i);
|
||||
|
||||
//Create all nodes in shared memory using a shared memory vector
|
||||
//See Boost.Interprocess documentation for more information on this
|
||||
typedef allocator< shared_memory_data
|
||||
, managed_shared_memory::segment_manager> shm_allocator_t;
|
||||
typedef vector<shared_memory_data, shm_allocator_t> shm_vector_t;
|
||||
shm_allocator_t shm_alloc(shm.get_segment_manager());
|
||||
shm_vector_t *pshm_vect = shm.construct<shm_vector_t>(anonymous_instance)(shm_alloc);
|
||||
pshm_vect->resize(MaxElem);
|
||||
//Now create the shared memory intrusive list
|
||||
shm_list_t *plist = shm.construct<shm_list_t>(ip::anonymous_instance)();
|
||||
plist->insert(plist->end(), pshm_vect->begin(), pshm_vect->end());
|
||||
|
||||
//Initialize all the nodes
|
||||
for(int i = 0; i < MaxElem; ++i){
|
||||
(*pshm_vect)[i].set(i);
|
||||
}
|
||||
|
||||
//Now create the shared memory intrusive list
|
||||
shm_list_t *plist = shm.construct<shm_list_t>(anonymous_instance)();
|
||||
plist->insert(plist->end(), pshm_vect->begin(), pshm_vect->end());
|
||||
|
||||
//Check all the inserted nodes
|
||||
int checker = 0;
|
||||
for( shm_list_t::const_iterator it = plist->begin(), itend(plist->end())
|
||||
; it != itend
|
||||
; ++it, ++checker){
|
||||
if(it->get() != checker){
|
||||
return false;
|
||||
//Check all the inserted nodes
|
||||
int checker = 0;
|
||||
for( shm_list_t::const_iterator it = plist->begin(), itend(plist->end())
|
||||
; it != itend; ++it, ++checker){
|
||||
if(it->get() != checker) return false;
|
||||
}
|
||||
}
|
||||
|
||||
//Now delete the list and after that, the nodes
|
||||
shm.destroy_ptr(plist);
|
||||
shm.destroy_ptr(pshm_vect);
|
||||
//Now delete the list and after that, the nodes
|
||||
shm.destroy_ptr(plist);
|
||||
shm.destroy_ptr(pshm_vect);
|
||||
}
|
||||
ip::shared_memory_object::remove(ShmName);
|
||||
return 0;
|
||||
}
|
||||
//]
|
||||
|
@ -17,7 +17,7 @@
|
||||
using namespace boost::intrusive;
|
||||
|
||||
//This is a base hook
|
||||
class MyClass : public set_base_hook<>
|
||||
class MyClass : public set_base_hook<>
|
||||
{
|
||||
int int_;
|
||||
|
||||
@ -28,69 +28,54 @@ class MyClass : public set_base_hook<>
|
||||
MyClass(int i)
|
||||
: int_(i)
|
||||
{}
|
||||
int get() const
|
||||
{ return int_; }
|
||||
friend bool operator< (const MyClass &a, const MyClass &b)
|
||||
{ return a.get() < b.get(); }
|
||||
{ return a.int_ < b.int_; }
|
||||
friend bool operator> (const MyClass &a, const MyClass &b)
|
||||
{ return a.get() > b.get(); }
|
||||
{ return a.int_ > b.int_; }
|
||||
friend bool operator== (const MyClass &a, const MyClass &b)
|
||||
{ return a.get() < b.get(); }
|
||||
{ return a.int_ < b.int_; }
|
||||
};
|
||||
|
||||
//Define an set that will store MyClass
|
||||
//in reverse order using the public base hook
|
||||
typedef set< set_base_hook<>::value_traits<MyClass>
|
||||
, std::greater<MyClass> > BaseSet;
|
||||
//Define an set using the base hook that will store values in reverse order
|
||||
typedef set< MyClass, compare<std::greater<MyClass> > > BaseSet;
|
||||
|
||||
//Define an multiset that will store MyClass
|
||||
//using the public member hook
|
||||
typedef multiset< set_member_hook<>::
|
||||
value_traits<MyClass, &MyClass::member_hook_>
|
||||
, std::less<MyClass> > MemberIMultiset;
|
||||
//Define an multiset using the member hook
|
||||
typedef member_hook<MyClass, set_member_hook<>, &MyClass::member_hook_> MemberOption;
|
||||
typedef multiset< MyClass, MemberOption> MemberIMultiset;
|
||||
|
||||
int main()
|
||||
{
|
||||
typedef std::vector<MyClass> Vect;
|
||||
typedef Vect::iterator VectIt;
|
||||
typedef Vect::reverse_iterator VectRit;
|
||||
typedef std::vector<MyClass>::iterator VectIt;
|
||||
typedef std::vector<MyClass>::reverse_iterator VectRit;
|
||||
|
||||
//Create several MyClass objects, each one
|
||||
//with a different internal number
|
||||
Vect myclassvector;
|
||||
for(int i = 0; i < 100; ++i)
|
||||
myclassvector.push_back(MyClass(i));
|
||||
//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;
|
||||
MemberIMultiset membermultiset;
|
||||
|
||||
//Now insert them in the reverse order
|
||||
//in the base hook intrusive set
|
||||
for(VectIt it(myclassvector.begin()), itend(myclassvector.end())
|
||||
; it != itend; ++it)
|
||||
//Now insert them in the reverse order in the base hook 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 intrusive set
|
||||
for(VectIt it(myclassvector.begin()), itend(myclassvector.end())
|
||||
; it != itend; ++it)
|
||||
//Now insert them in the same order as in vector in the member hook set
|
||||
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it)
|
||||
membermultiset.insert(*it);
|
||||
|
||||
//Now test sets
|
||||
{
|
||||
BaseSet::reverse_iterator rbit(baseset.rbegin()), rbitend(baseset.rend());
|
||||
MemberIMultiset::iterator mit(membermultiset.begin()), mitend(membermultiset.end());
|
||||
VectIt it(myclassvector.begin()), itend(myclassvector.end());
|
||||
VectIt it(values.begin()), itend(values.end());
|
||||
|
||||
//Test the objects inserted in the base hook set
|
||||
for(; it != itend; ++it, ++rbit){
|
||||
for(; it != itend; ++it, ++rbit)
|
||||
if(&*rbit != &*it) return 1;
|
||||
}
|
||||
|
||||
//Test the objects inserted in the member hook set
|
||||
for(it = myclassvector.begin(); it != itend; ++it, ++mit){
|
||||
for(it = values.begin(); it != itend; ++it, ++mit)
|
||||
if(&*mit != &*it) return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
using namespace boost::intrusive;
|
||||
|
||||
//This is a base hook
|
||||
class MyClass : public slist_base_hook<>
|
||||
class MyClass : public slist_base_hook<>
|
||||
{
|
||||
int int_;
|
||||
|
||||
@ -27,45 +27,34 @@ class MyClass : public slist_base_hook<>
|
||||
MyClass(int i)
|
||||
: int_(i)
|
||||
{}
|
||||
|
||||
int get() const
|
||||
{ return int_; }
|
||||
};
|
||||
|
||||
//Define an slist that will store MyClass using the public base hook
|
||||
typedef slist< slist_base_hook<>::value_traits<MyClass> > BaseList;
|
||||
typedef slist<MyClass> BaseList;
|
||||
|
||||
//Define an slist that will store MyClass using the public member hook
|
||||
typedef slist< slist_member_hook<>::value_traits<MyClass, &MyClass::member_hook_> > MemberList;
|
||||
typedef member_hook<MyClass, slist_member_hook<>, &MyClass::member_hook_> MemberOption;
|
||||
typedef slist<MyClass, MemberOption> MemberList;
|
||||
|
||||
int main()
|
||||
{
|
||||
typedef std::vector<MyClass> Vect;
|
||||
typedef Vect::iterator VectIt;
|
||||
typedef Vect::reverse_iterator VectRit;
|
||||
typedef std::vector<MyClass>::iterator VectIt;
|
||||
typedef std::vector<MyClass>::reverse_iterator VectRit;
|
||||
|
||||
//Create several MyClass objects, each one
|
||||
//with a different internal number
|
||||
Vect myclassvector;
|
||||
for(int i = 0; i < 100; ++i)
|
||||
myclassvector.push_back(MyClass(i));
|
||||
//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));
|
||||
|
||||
BaseList baselist;
|
||||
MemberList memberlist;
|
||||
|
||||
//Now insert them in the reverse order
|
||||
//in the base hook intrusive list
|
||||
for(VectIt it(myclassvector.begin()), itend(myclassvector.end())
|
||||
; it != itend
|
||||
; ++it){
|
||||
//Now insert them in the reverse order in the base hook list
|
||||
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it)
|
||||
baselist.push_front(*it);
|
||||
}
|
||||
|
||||
//Now insert them in the same order as in vector in the
|
||||
//member hook intrusive list
|
||||
//Now insert them in the same order as in vector in the member hook list
|
||||
for(BaseList::iterator it(baselist.begin()), itend(baselist.end())
|
||||
; it != itend
|
||||
; ++it){
|
||||
; it != itend; ++it){
|
||||
memberlist.push_front(*it);
|
||||
}
|
||||
|
||||
@ -73,18 +62,16 @@ int main()
|
||||
{
|
||||
BaseList::iterator bit(baselist.begin()), bitend(baselist.end());
|
||||
MemberList::iterator mit(memberlist.begin()), mitend(memberlist.end());
|
||||
VectRit rit(myclassvector.rbegin()), ritend(myclassvector.rend());
|
||||
VectIt it(myclassvector.begin()), itend(myclassvector.end());
|
||||
VectRit rit(values.rbegin()), ritend(values.rend());
|
||||
VectIt it(values.begin()), itend(values.end());
|
||||
|
||||
//Test the objects inserted in the base hook list
|
||||
for(; rit != ritend; ++rit, ++bit){
|
||||
for(; rit != ritend; ++rit, ++bit)
|
||||
if(&*bit != &*rit) return 1;
|
||||
}
|
||||
|
||||
//Test the objects inserted in the member hook list
|
||||
for(; it != itend; ++it, ++mit){
|
||||
for(; it != itend; ++it, ++mit)
|
||||
if(&*mit != &*it) return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
87
example/doc_stateful_value_traits.cpp
Normal file
87
example/doc_stateful_value_traits.cpp
Normal file
@ -0,0 +1,87 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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_stateful_value_traits
|
||||
#include <boost/intrusive/list.hpp>
|
||||
|
||||
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:
|
||||
struct stateful_value_traits
|
||||
{
|
||||
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;
|
||||
|
||||
stateful_value_traits(pointer ids, node_ptr node_array)
|
||||
: ids_(ids), nodes_(node_array)
|
||||
{}
|
||||
|
||||
///Note: non static functions!
|
||||
node_ptr to_node_ptr (value_type &value)
|
||||
{ return this->nodes_ + (&value - this->ids_); }
|
||||
const_node_ptr to_node_ptr (const value_type &value) const
|
||||
{ return this->nodes_ + (&value - this->ids_); }
|
||||
pointer to_value_ptr(node_ptr n)
|
||||
{ return this->ids_ + (n - this->nodes_); }
|
||||
const_pointer to_value_ptr(const_node_ptr n) const
|
||||
{ return this->ids_ + (n - this->nodes_); }
|
||||
|
||||
private:
|
||||
pointer ids_;
|
||||
node_ptr nodes_;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
const int NumElements = 100;
|
||||
|
||||
//This is an array of ids that we want to "store"
|
||||
identifier_t ids [NumElements];
|
||||
|
||||
//This is an array of nodes that is necessary to form the linked list
|
||||
list_node_traits<void*>::node nodes [NumElements];
|
||||
|
||||
//Initialize id objects, each one with a different number
|
||||
for(int i = 0; i != NumElements; ++i) ids[i] = i;
|
||||
|
||||
//Define a list that will "link" identifiers using external nodes
|
||||
typedef list<identifier_t, value_traits<stateful_value_traits> > List;
|
||||
|
||||
//This list will store ids without modifying identifier_t instances
|
||||
//Stateful value traits must be explicitly passed in the constructor.
|
||||
List my_list (stateful_value_traits (ids, nodes));
|
||||
|
||||
//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;
|
||||
}
|
||||
//]
|
@ -17,56 +17,43 @@
|
||||
|
||||
using namespace boost::intrusive;
|
||||
|
||||
//This is a derivation hook
|
||||
class MyClass : public unordered_set_base_hook<>
|
||||
{
|
||||
class MyClass : public unordered_set_base_hook<>
|
||||
{ //This is a derivation hook
|
||||
int int_;
|
||||
|
||||
public:
|
||||
//This is a member hook
|
||||
unordered_set_member_hook<> member_hook_;
|
||||
unordered_set_member_hook<> member_hook_; //This is a member hook
|
||||
|
||||
MyClass(int i)
|
||||
: int_(i)
|
||||
{}
|
||||
|
||||
int get() const
|
||||
{ return int_; }
|
||||
|
||||
friend bool operator== (const MyClass &a, const MyClass &b)
|
||||
{ return a.get() == b.get(); }
|
||||
{ return a.int_ == b.int_; }
|
||||
|
||||
friend bool operator> (const MyClass &a, const MyClass &b)
|
||||
{ return a.get() > b.get(); }
|
||||
friend std::size_t hash_value(const MyClass &value)
|
||||
{ return std::size_t(value.int_); }
|
||||
};
|
||||
|
||||
std::size_t hash_value(const MyClass &value)
|
||||
{ return std::size_t(value.get()); }
|
||||
//Define an unordered_set that will store MyClass objects using the base hook
|
||||
typedef unordered_set<MyClass> BaseSet;
|
||||
|
||||
//Define an unordered_set that will store MyClass
|
||||
//in reverse order using the public base hook
|
||||
typedef unordered_set< unordered_set_base_hook<>::
|
||||
value_traits<MyClass> > BaseSet;
|
||||
|
||||
//Define an unordered_multiset that will store MyClass
|
||||
//using the public member hook
|
||||
typedef unordered_multiset< unordered_set_member_hook<>::
|
||||
value_traits<MyClass, &MyClass::member_hook_> > MemberMultiSet;
|
||||
//Define an unordered_multiset that will store MyClass using the member hook
|
||||
typedef member_hook<MyClass, unordered_set_member_hook<>, &MyClass::member_hook_>
|
||||
MemberOption;
|
||||
typedef unordered_multiset< MyClass, MemberOption> MemberMultiSet;
|
||||
|
||||
int main()
|
||||
{
|
||||
typedef std::vector<MyClass> Vect;
|
||||
typedef Vect::iterator VectIt;
|
||||
typedef Vect::reverse_iterator VectRit;
|
||||
typedef std::vector<MyClass>::iterator VectIt;
|
||||
typedef std::vector<MyClass>::reverse_iterator VectRit;
|
||||
|
||||
//Create a vector with 100 different MyClass objects,
|
||||
//each one with a different internal number
|
||||
Vect myclassvector;
|
||||
for(int i = 0; i < 100; ++i)
|
||||
myclassvector.push_back(MyClass(i));
|
||||
//Create a vector with 100 different MyClass objects
|
||||
std::vector<MyClass> values;
|
||||
for(int i = 0; i < 100; ++i) values.push_back(MyClass(i));
|
||||
|
||||
//Create a copy of the vector
|
||||
Vect myclassvector2(myclassvector);
|
||||
std::vector<MyClass> values2(values);
|
||||
|
||||
//Create a bucket array for base_set
|
||||
BaseSet::bucket_type base_buckets[100];
|
||||
@ -74,20 +61,18 @@ int main()
|
||||
//Create a bucket array for member_multi_set
|
||||
MemberMultiSet::bucket_type member_buckets[200];
|
||||
|
||||
//Create a the unordered_set and unordered_multiset,
|
||||
//taking buckets as arguments
|
||||
BaseSet base_set(base_buckets, 100);
|
||||
MemberMultiSet member_multi_set(member_buckets, 200);
|
||||
//Create unordered containers taking buckets as arguments
|
||||
BaseSet base_set(BaseSet::bucket_traits(base_buckets, 100));
|
||||
MemberMultiSet member_multi_set
|
||||
(MemberMultiSet::bucket_traits(member_buckets, 200));
|
||||
|
||||
//Now insert myclassvector's elements in the unordered_set
|
||||
for(VectIt it(myclassvector.begin()), itend(myclassvector.end())
|
||||
; it != itend; ++it){
|
||||
//Now insert values's elements in the unordered_set
|
||||
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it)
|
||||
base_set.insert(*it);
|
||||
}
|
||||
|
||||
//Now insert myclassvector's and myclassvector2's elements in the unordered_multiset
|
||||
for(VectIt it(myclassvector.begin()), itend(myclassvector.end()),
|
||||
it2(myclassvector2.begin()),itend2(myclassvector2.end())
|
||||
//Now insert values's and values2's elements in the unordered_multiset
|
||||
for(VectIt it(values.begin()), itend(values.end()),
|
||||
it2(values2.begin()),itend2(values2.end())
|
||||
; it != itend; ++it, ++it2){
|
||||
member_multi_set.insert(*it);
|
||||
member_multi_set.insert(*it2);
|
||||
@ -95,7 +80,7 @@ int main()
|
||||
|
||||
//Now find every element
|
||||
{
|
||||
VectIt it(myclassvector.begin()), itend(myclassvector.end());
|
||||
VectIt it(values.begin()), itend(values.end());
|
||||
|
||||
for(; it != itend; ++it){
|
||||
//base_set should contain one element for each key
|
||||
|
@ -10,7 +10,7 @@
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//[doc_value_traits_code_legacy
|
||||
#include <boost/intrusive/linking_policy.hpp>
|
||||
#include <boost/intrusive/link_mode.hpp>
|
||||
#include <boost/intrusive/list.hpp>
|
||||
#include <boost/intrusive/slist.hpp>
|
||||
#include <vector>
|
||||
@ -30,6 +30,9 @@ struct legacy_value
|
||||
//Define our own NodeTraits that will configure singly and doubly linked
|
||||
//list algorithms. Note that this node traits is compatible with
|
||||
//circular_slist_algorithms and circular_list_algorithms.
|
||||
|
||||
namespace bi = boost::intrusive;
|
||||
|
||||
struct legacy_node_traits
|
||||
{
|
||||
typedef legacy_value node;
|
||||
@ -54,7 +57,7 @@ struct legacy_value_traits
|
||||
typedef legacy_value value_type;
|
||||
typedef legacy_value * pointer;
|
||||
typedef const legacy_value * const_pointer;
|
||||
enum { linking_policy = boost::intrusive::normal_link };
|
||||
static const bi::link_mode_type link_mode = bi::normal_link;
|
||||
static node_ptr to_node_ptr (value_type &value) { return node_ptr(&value); }
|
||||
static const_node_ptr to_node_ptr (const value_type &value) { return const_node_ptr(&value); }
|
||||
static pointer to_value_ptr(node_ptr n) { return pointer(n); }
|
||||
@ -65,8 +68,9 @@ struct legacy_value_traits
|
||||
|
||||
//[doc_value_traits_test
|
||||
//Now define an intrusive list and slist that will store legacy_value objects
|
||||
typedef boost::intrusive::list <legacy_value_traits> LegacyAbiList;
|
||||
typedef boost::intrusive::slist<legacy_value_traits> LegacyAbiSlist;
|
||||
typedef bi::value_traits<legacy_value_traits> ValueTraitsOption;
|
||||
typedef bi::list<legacy_value, ValueTraitsOption> LegacyAbiList;
|
||||
typedef bi::slist<legacy_value, ValueTraitsOption> LegacyAbiSlist;
|
||||
|
||||
template<class List>
|
||||
bool test_list()
|
||||
@ -87,9 +91,8 @@ bool test_list()
|
||||
typename Vect::const_iterator it(legacy_vector.begin()), itend(legacy_vector.end());
|
||||
|
||||
//Test the objects inserted in our list
|
||||
for(; it != itend; ++it, ++bit){
|
||||
for(; it != itend; ++it, ++bit)
|
||||
if(&*bit != &*it) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -15,11 +15,11 @@
|
||||
using namespace boost::intrusive;
|
||||
|
||||
//An abstract class that can be inserted in an intrusive list
|
||||
class Window : public list_base_hook<>
|
||||
class Window : public list_base_hook<>
|
||||
{
|
||||
public:
|
||||
//This is a container those value is an abstract class: you can't do this with std::list.
|
||||
typedef list< list_base_hook<>::value_traits<Window> > win_list;
|
||||
typedef list<Window> win_list;
|
||||
|
||||
//An static intrusive list declaration
|
||||
static win_list all_windows;
|
||||
@ -27,7 +27,7 @@ class Window : public list_base_hook<>
|
||||
//Constructor. Includes this window in the list
|
||||
Window() { all_windows.push_back(*this); }
|
||||
//Destructor. Removes this node from the list
|
||||
virtual ~Window() { all_windows.erase(win_list::iterator_to(*this)); }
|
||||
virtual ~Window() { all_windows.erase(win_list::s_iterator_to(*this)); }
|
||||
//Pure virtual function to be implemented by derived classes
|
||||
virtual void Paint() = 0;
|
||||
};
|
||||
@ -71,15 +71,13 @@ class MainWindow : public Window
|
||||
//Main function
|
||||
int main()
|
||||
{
|
||||
//When each Window class is created, is
|
||||
//automatically registered in the global list
|
||||
//When a Window class is created, is automatically registered in the global list
|
||||
MainWindow window;
|
||||
|
||||
//Paint all the windows, sub-windows and so on
|
||||
paint_all_windows();
|
||||
|
||||
//All the windows are automatically unregistered
|
||||
//in their destructors.
|
||||
//All the windows are automatically unregistered in their destructors.
|
||||
return 0;
|
||||
}
|
||||
//]
|
||||
|
@ -11,6 +11,7 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//Includes for tests
|
||||
#include <boost/config.hpp>
|
||||
#include <list>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
@ -26,11 +27,8 @@ const int NumElements = 100000;
|
||||
|
||||
using namespace boost::intrusive;
|
||||
|
||||
template<bool BigSize>
|
||||
struct filler { int dummy[10]; };
|
||||
|
||||
template <>
|
||||
struct filler<false> {};
|
||||
template<bool BigSize> struct filler { int dummy[10]; };
|
||||
template <> struct filler<false> {};
|
||||
|
||||
template<bool BigSize> //The object for non-intrusive containers
|
||||
struct test_class : private filler<BigSize>
|
||||
@ -42,8 +40,9 @@ struct test_class : private filler<BigSize>
|
||||
friend bool operator >(const test_class &l, const test_class &r) { return l.i_ > r.i_; }
|
||||
};
|
||||
|
||||
template <bool BigSize, linking_policy Policy> //The object for intrusive containers
|
||||
struct itest_class : public list_base_hook<tag, Policy>, public test_class<BigSize>
|
||||
template <bool BigSize, link_mode_type LinkMode>
|
||||
struct itest_class //The object for intrusive containers
|
||||
: public list_base_hook<link_mode<LinkMode> >, public test_class<BigSize>
|
||||
{
|
||||
itest_class() {}
|
||||
itest_class(int i) : test_class<BigSize>(i) {}
|
||||
@ -60,11 +59,10 @@ struct func_ptr_adaptor : public FuncObj
|
||||
};
|
||||
//]
|
||||
|
||||
template <bool BigSize, linking_policy Policy>
|
||||
template <bool BigSize, link_mode_type LinkMode>
|
||||
struct get_ilist //Helps to define an intrusive list from a policy
|
||||
{
|
||||
typedef list_base_hook<tag, Policy> hook;
|
||||
typedef list<typename hook::template value_traits<itest_class<BigSize, Policy> >, false> type;
|
||||
typedef list<itest_class<BigSize, LinkMode>, constant_time_size<false> > type;
|
||||
};
|
||||
|
||||
template <bool BigSize> //Helps to define an std list
|
||||
@ -73,17 +71,16 @@ struct get_list { typedef std::list<test_class<BigSize> > type; };
|
||||
template <bool BigSize> //Helps to define an std pointer list
|
||||
struct get_ptrlist { typedef std::list<test_class<BigSize>*> type; };
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PUSH_BACK
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <bool BigSize, linking_policy Policy>
|
||||
template <bool BigSize, link_mode_type LinkMode>
|
||||
void test_intrusive_list_push_back()
|
||||
{
|
||||
typedef typename get_ilist<BigSize, Policy>::type ilist;
|
||||
typedef typename get_ilist<BigSize, LinkMode>::type ilist;
|
||||
ptime tini = microsec_clock::universal_time();
|
||||
for(int i = 0; i < NumIter; ++i){
|
||||
//First create the elements and insert them in the intrusive list
|
||||
@ -93,11 +90,12 @@ void test_intrusive_list_push_back()
|
||||
for(int i = 0; i < NumElements; ++i)
|
||||
l.push_back(objects[i]);
|
||||
//Elements are unlinked in ilist's destructor
|
||||
//Elements are disposed in vector's destructor
|
||||
//Elements are destroyed in vector's destructor
|
||||
//]
|
||||
}
|
||||
ptime tend = microsec_clock::universal_time();
|
||||
std::cout << "usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl;
|
||||
std::cout << "link_mode: " << LinkMode << ", usecs/iteration: "
|
||||
<< (tend-tini).total_microseconds()/NumIter << std::endl;
|
||||
}
|
||||
|
||||
template <bool BigSize>
|
||||
@ -111,11 +109,12 @@ void test_std_list_push_back()
|
||||
stdlist l;
|
||||
for(int i = 0; i < NumElements; ++i)
|
||||
l.push_back(typename stdlist::value_type(i));
|
||||
//Elements unlinked and disposed in stdlist's destructor
|
||||
//Elements unlinked and destroyed in stdlist's destructor
|
||||
//]
|
||||
}
|
||||
ptime tend = microsec_clock::universal_time();
|
||||
std::cout << "usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl;
|
||||
std::cout << "std::list usecs/iteration: "
|
||||
<< (tend-tini).total_microseconds()/NumIter << std::endl;
|
||||
}
|
||||
|
||||
template <bool BigSize>
|
||||
@ -132,12 +131,13 @@ void test_compact_std_ptrlist_push_back()
|
||||
stdptrlist l;
|
||||
for(int i = 0; i < NumElements; ++i)
|
||||
l.push_back(&objects[i]);
|
||||
//Pointers to elements unlinked and disposed in stdptrlist's destructor
|
||||
//Elements disposed in vector's destructor
|
||||
//Pointers to elements unlinked and destroyed in stdptrlist's destructor
|
||||
//Elements destroyed in vector's destructor
|
||||
//]
|
||||
}
|
||||
ptime tend = microsec_clock::universal_time();
|
||||
std::cout << "usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl;
|
||||
std::cout << "compact std::list usecs/iteration: "
|
||||
<< (tend-tini).total_microseconds()/NumIter << std::endl;
|
||||
}
|
||||
|
||||
template <bool BigSize>
|
||||
@ -155,12 +155,13 @@ void test_disperse_std_ptrlist_push_back()
|
||||
objects.push_back(typename stdlist::value_type(i));
|
||||
l.push_back(&objects.back());
|
||||
}
|
||||
//Pointers to elements unlinked and disposed in stdptrlist's destructor
|
||||
//Elements unlinked and disposed in stdlist's destructor
|
||||
//Pointers to elements unlinked and destroyed in stdptrlist's destructor
|
||||
//Elements unlinked and destroyed in stdlist's destructor
|
||||
//]
|
||||
}
|
||||
ptime tend = microsec_clock::universal_time();
|
||||
std::cout << "usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl;
|
||||
std::cout << "disperse std::list usecs/iteration: "
|
||||
<< (tend-tini).total_microseconds()/NumIter << std::endl;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
@ -170,10 +171,10 @@ void test_disperse_std_ptrlist_push_back()
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//[perf_list_reverse
|
||||
template <bool BigSize, linking_policy Policy>
|
||||
template <bool BigSize, link_mode_type LinkMode>
|
||||
void test_intrusive_list_reverse()
|
||||
{
|
||||
typedef typename get_ilist<BigSize, Policy>::type ilist;
|
||||
typedef typename get_ilist<BigSize, LinkMode>::type ilist;
|
||||
//First create the elements
|
||||
std::vector<typename ilist::value_type> objects(NumElements);
|
||||
|
||||
@ -186,7 +187,8 @@ void test_intrusive_list_reverse()
|
||||
l.reverse();
|
||||
}
|
||||
ptime tend = microsec_clock::universal_time();
|
||||
std::cout << "usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl;
|
||||
std::cout << "link_mode: " << LinkMode << ", usecs/iteration: "
|
||||
<< (tend-tini).total_microseconds()/NumIter << std::endl;
|
||||
}
|
||||
|
||||
template <bool BigSize>
|
||||
@ -205,7 +207,8 @@ void test_std_list_reverse()
|
||||
l.reverse();
|
||||
}
|
||||
ptime tend = microsec_clock::universal_time();
|
||||
std::cout << "usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl;
|
||||
std::cout << "std::list usecs/iteration: "
|
||||
<< (tend-tini).total_microseconds()/NumIter << std::endl;
|
||||
}
|
||||
|
||||
template <bool BigSize>
|
||||
@ -228,7 +231,8 @@ void test_compact_std_ptrlist_reverse()
|
||||
l.reverse();
|
||||
}
|
||||
ptime tend = microsec_clock::universal_time();
|
||||
std::cout << "usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl;
|
||||
std::cout << "compact std::list usecs/iteration: "
|
||||
<< (tend-tini).total_microseconds()/NumIter << std::endl;
|
||||
}
|
||||
|
||||
template <bool BigSize>
|
||||
@ -252,7 +256,8 @@ void test_disperse_std_ptrlist_reverse()
|
||||
l.reverse();
|
||||
}
|
||||
ptime tend = microsec_clock::universal_time();
|
||||
std::cout << "usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl;
|
||||
std::cout << "disperse std::list usecs/iteration: "
|
||||
<< (tend-tini).total_microseconds()/NumIter << std::endl;
|
||||
}
|
||||
//]
|
||||
|
||||
@ -263,10 +268,10 @@ void test_disperse_std_ptrlist_reverse()
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//[perf_list_sort
|
||||
template <bool BigSize, linking_policy Policy>
|
||||
template <bool BigSize, link_mode_type LinkMode>
|
||||
void test_intrusive_list_sort()
|
||||
{
|
||||
typedef typename get_ilist<BigSize, Policy>::type ilist;
|
||||
typedef typename get_ilist<BigSize, LinkMode>::type ilist;
|
||||
|
||||
//First create the elements
|
||||
std::vector<typename ilist::value_type> objects(NumElements);
|
||||
@ -287,7 +292,8 @@ void test_intrusive_list_sort()
|
||||
}
|
||||
}
|
||||
ptime tend = microsec_clock::universal_time();
|
||||
std::cout << "usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl;
|
||||
std::cout << "link_mode: " << LinkMode << ", usecs/iteration: "
|
||||
<< (tend-tini).total_microseconds()/NumIter << std::endl;
|
||||
}
|
||||
|
||||
template <bool BigSize>
|
||||
@ -311,7 +317,8 @@ void test_std_list_sort()
|
||||
}
|
||||
}
|
||||
ptime tend = microsec_clock::universal_time();
|
||||
std::cout << "usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl;
|
||||
std::cout << "std::list usecs/iteration: "
|
||||
<< (tend-tini).total_microseconds()/NumIter << std::endl;
|
||||
}
|
||||
|
||||
template <bool BigSize>
|
||||
@ -340,7 +347,8 @@ void test_compact_std_ptrlist_sort()
|
||||
}
|
||||
}
|
||||
ptime tend = microsec_clock::universal_time();
|
||||
std::cout << "usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl;
|
||||
std::cout << "compact std::list usecs/iteration: "
|
||||
<< (tend-tini).total_microseconds()/NumIter << std::endl;
|
||||
}
|
||||
|
||||
template <bool BigSize>
|
||||
@ -368,7 +376,8 @@ void test_disperse_std_ptrlist_sort()
|
||||
}
|
||||
}
|
||||
ptime tend = microsec_clock::universal_time();
|
||||
std::cout << "usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl;
|
||||
std::cout << "disperse std::list usecs/iteration: "
|
||||
<< (tend-tini).total_microseconds()/NumIter << std::endl;
|
||||
}
|
||||
//]
|
||||
|
||||
@ -378,10 +387,10 @@ void test_disperse_std_ptrlist_sort()
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//[perf_list_write_access
|
||||
template <bool BigSize, linking_policy Policy>
|
||||
template <bool BigSize, link_mode_type LinkMode>
|
||||
void test_intrusive_list_write_access()
|
||||
{
|
||||
typedef typename get_ilist<BigSize, Policy>::type ilist;
|
||||
typedef typename get_ilist<BigSize, LinkMode>::type ilist;
|
||||
|
||||
//First create the elements
|
||||
std::vector<typename ilist::value_type> objects(NumElements);
|
||||
@ -401,7 +410,8 @@ void test_intrusive_list_write_access()
|
||||
}
|
||||
}
|
||||
ptime tend = microsec_clock::universal_time();
|
||||
std::cout << "usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl;
|
||||
std::cout << "link_mode: " << LinkMode << ", usecs/iteration: "
|
||||
<< (tend-tini).total_microseconds()/NumIter << std::endl;
|
||||
}
|
||||
|
||||
template <bool BigSize>
|
||||
@ -423,7 +433,8 @@ void test_std_list_write_access()
|
||||
}
|
||||
}
|
||||
ptime tend = microsec_clock::universal_time();
|
||||
std::cout << "usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl;
|
||||
std::cout << "std::list usecs/iteration: "
|
||||
<< (tend-tini).total_microseconds()/NumIter << std::endl;
|
||||
}
|
||||
|
||||
template <bool BigSize>
|
||||
@ -452,7 +463,8 @@ void test_compact_std_ptrlist_write_access()
|
||||
}
|
||||
}
|
||||
ptime tend = microsec_clock::universal_time();
|
||||
std::cout << "usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl;
|
||||
std::cout << "compact std::list usecs/iteration: "
|
||||
<< (tend-tini).total_microseconds()/NumIter << std::endl;
|
||||
}
|
||||
|
||||
template <bool BigSize>
|
||||
@ -479,7 +491,8 @@ void test_disperse_std_ptrlist_write_access()
|
||||
}
|
||||
}
|
||||
ptime tend = microsec_clock::universal_time();
|
||||
std::cout << "usecs/iteration: " << (tend-tini).total_microseconds()/NumIter << std::endl;
|
||||
std::cout << "disperse std::list usecs/iteration: "
|
||||
<< (tend-tini).total_microseconds()/NumIter << std::endl;
|
||||
}
|
||||
//]
|
||||
|
||||
@ -491,7 +504,7 @@ void test_disperse_std_ptrlist_write_access()
|
||||
template<bool BigSize>
|
||||
void do_all_tests()
|
||||
{
|
||||
std::cout << "Testing push back() with BigSize:" << BigSize << std::endl;
|
||||
std::cout << "\n\nTesting push back() with BigSize:" << BigSize << std::endl;
|
||||
test_intrusive_list_push_back<BigSize, normal_link>();
|
||||
test_intrusive_list_push_back<BigSize, safe_link>();
|
||||
test_intrusive_list_push_back<BigSize, auto_unlink>();
|
||||
@ -499,7 +512,7 @@ void do_all_tests()
|
||||
test_compact_std_ptrlist_push_back<BigSize>();
|
||||
test_disperse_std_ptrlist_push_back<BigSize>();
|
||||
//reverse
|
||||
std::cout << "Testing reverse() with BigSize:" << BigSize << std::endl;
|
||||
std::cout << "\n\nTesting reverse() with BigSize:" << BigSize << std::endl;
|
||||
test_intrusive_list_reverse<BigSize, normal_link>();
|
||||
test_intrusive_list_reverse<BigSize, safe_link>();
|
||||
test_intrusive_list_reverse<BigSize, auto_unlink>();
|
||||
@ -507,7 +520,7 @@ void do_all_tests()
|
||||
test_compact_std_ptrlist_reverse<BigSize>();
|
||||
test_disperse_std_ptrlist_reverse<BigSize>();
|
||||
//sort
|
||||
std::cout << "Testing sort() with BigSize:" << BigSize << std::endl;
|
||||
std::cout << "\n\nTesting sort() with BigSize:" << BigSize << std::endl;
|
||||
test_intrusive_list_sort<BigSize, normal_link>();
|
||||
test_intrusive_list_sort<BigSize, safe_link>();
|
||||
test_intrusive_list_sort<BigSize, auto_unlink>();
|
||||
@ -515,7 +528,7 @@ void do_all_tests()
|
||||
test_compact_std_ptrlist_sort<BigSize>();
|
||||
test_disperse_std_ptrlist_sort<BigSize>();
|
||||
//write_access
|
||||
std::cout << "Testing write_access() with BigSize:" << BigSize << std::endl;
|
||||
std::cout << "\n\nTesting write_access() with BigSize:" << BigSize << std::endl;
|
||||
test_intrusive_list_write_access<BigSize, normal_link>();
|
||||
test_intrusive_list_write_access<BigSize, safe_link>();
|
||||
test_intrusive_list_write_access<BigSize, auto_unlink>();
|
||||
|
127
test/custom_bucket_traits_test.cpp
Normal file
127
test/custom_bucket_traits_test.cpp
Normal file
@ -0,0 +1,127 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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/unordered_set.hpp>
|
||||
#include <boost/intrusive/detail/mpl.hpp>
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include <vector>
|
||||
|
||||
using namespace boost::intrusive;
|
||||
|
||||
class MyClass : public unordered_set_base_hook<>
|
||||
{
|
||||
int int_;
|
||||
|
||||
public:
|
||||
MyClass(int i = 0) : int_(i)
|
||||
{}
|
||||
unordered_set_member_hook<> member_hook_;
|
||||
|
||||
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_); }
|
||||
};
|
||||
|
||||
struct uset_value_traits
|
||||
{
|
||||
typedef slist_node_traits<void*> node_traits;
|
||||
typedef node_traits::node_ptr node_ptr;
|
||||
typedef node_traits::const_node_ptr const_node_ptr;
|
||||
typedef MyClass value_type;
|
||||
typedef MyClass * pointer;
|
||||
typedef const MyClass * const_pointer;
|
||||
static const link_mode_type link_mode = normal_link;
|
||||
|
||||
static node_ptr to_node_ptr (value_type &value)
|
||||
{ return node_ptr(&value); }
|
||||
static const_node_ptr to_node_ptr (const value_type &value)
|
||||
{ return const_node_ptr(&value); }
|
||||
static pointer to_value_ptr(node_ptr n)
|
||||
{ return static_cast<value_type*>(n); }
|
||||
static const_pointer to_value_ptr(const_node_ptr n)
|
||||
{ return static_cast<const value_type*>(n); }
|
||||
};
|
||||
|
||||
//Base
|
||||
typedef base_hook< unordered_set_base_hook<> > BaseHook;
|
||||
typedef unordered_bucket<BaseHook>::type BaseBucketType;
|
||||
typedef unordered_set<MyClass, BaseHook> BaseUset;
|
||||
//Member
|
||||
typedef member_hook
|
||||
< MyClass, unordered_set_member_hook<>
|
||||
, &MyClass::member_hook_ > MemberHook;
|
||||
typedef unordered_bucket<MemberHook>::type MemberBucketType;
|
||||
typedef unordered_set<MyClass, MemberHook> MemberUset;
|
||||
//Explicit
|
||||
typedef value_traits< uset_value_traits > Traits;
|
||||
typedef unordered_bucket<Traits>::type TraitsBucketType;
|
||||
typedef unordered_set<MyClass, Traits> TraitsUset;
|
||||
|
||||
struct uset_bucket_traits
|
||||
{
|
||||
//Power of two bucket length
|
||||
static const std::size_t NumBuckets = 128;
|
||||
|
||||
uset_bucket_traits(BaseBucketType *buckets)
|
||||
: buckets_(buckets)
|
||||
{}
|
||||
|
||||
uset_bucket_traits(const uset_bucket_traits &other)
|
||||
: buckets_(other.buckets_)
|
||||
{}
|
||||
|
||||
BaseBucketType * bucket_begin() const
|
||||
{ return buckets_; }
|
||||
|
||||
std::size_t bucket_count() const
|
||||
{ return NumBuckets; }
|
||||
|
||||
BaseBucketType *buckets_;
|
||||
};
|
||||
|
||||
typedef unordered_set
|
||||
<MyClass, bucket_traits<uset_bucket_traits>, power_2_buckets<true> >
|
||||
BucketTraitsUset;
|
||||
|
||||
int main()
|
||||
{
|
||||
if(!detail::is_same<BaseUset::bucket_type, BaseBucketType>::value)
|
||||
return 1;
|
||||
if(!detail::is_same<MemberUset::bucket_type, MemberBucketType>::value)
|
||||
return 1;
|
||||
if(!detail::is_same<TraitsUset::bucket_type, TraitsBucketType>::value)
|
||||
return 1;
|
||||
if(!detail::is_same<BaseBucketType, MemberBucketType>::value)
|
||||
return 1;
|
||||
if(!detail::is_same<BaseBucketType, TraitsBucketType>::value)
|
||||
return 1;
|
||||
|
||||
typedef std::vector<MyClass>::iterator VectIt;
|
||||
typedef std::vector<MyClass>::reverse_iterator VectRit;
|
||||
std::vector<MyClass> values;
|
||||
|
||||
for(int i = 0; i < 100; ++i) values.push_back(MyClass(i));
|
||||
|
||||
BaseBucketType buckets[uset_bucket_traits::NumBuckets];
|
||||
uset_bucket_traits btraits(buckets);
|
||||
BucketTraitsUset uset(btraits);
|
||||
|
||||
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it)
|
||||
uset.insert(*it);
|
||||
|
||||
for( VectRit it(values.rbegin()), itend(values.rend()); it != itend; ++it){
|
||||
if(uset.find(*it) == uset.cend()) return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
97
test/default_hook_test.cpp
Normal file
97
test/default_hook_test.cpp
Normal file
@ -0,0 +1,97 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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/list.hpp>
|
||||
#include <boost/intrusive/slist.hpp>
|
||||
#include <boost/intrusive/set.hpp>
|
||||
#include <boost/intrusive/unordered_set.hpp>
|
||||
#include "smart_ptr.hpp"
|
||||
#include <vector>
|
||||
|
||||
using namespace boost::intrusive;
|
||||
|
||||
class MyClass
|
||||
|
||||
: public list_base_hook
|
||||
< void_pointer<smart_ptr<void> >, link_mode<normal_link> >
|
||||
, public slist_base_hook
|
||||
< void_pointer<smart_ptr<void> >, link_mode<normal_link> >
|
||||
, public set_base_hook
|
||||
< void_pointer<smart_ptr<void> >, link_mode<normal_link> >
|
||||
, public unordered_set_base_hook
|
||||
< void_pointer<smart_ptr<void> >, link_mode<normal_link> >
|
||||
{
|
||||
int int_;
|
||||
|
||||
public:
|
||||
MyClass(int i)
|
||||
: int_(i)
|
||||
{}
|
||||
|
||||
friend bool operator<(const MyClass &l, const MyClass &r)
|
||||
{ return l.int_ < r.int_; }
|
||||
|
||||
friend bool operator==(const MyClass &l, const MyClass &r)
|
||||
{ return l.int_ == r.int_; }
|
||||
|
||||
friend std::size_t hash_value(const MyClass &v)
|
||||
{ return boost::hash_value(v.int_); }
|
||||
};
|
||||
|
||||
//Define a list that will store MyClass using the public base hook
|
||||
typedef list<MyClass> List;
|
||||
typedef slist<MyClass> Slist;
|
||||
typedef set<MyClass> Set;
|
||||
typedef unordered_set<MyClass> USet;
|
||||
|
||||
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));
|
||||
|
||||
USet::bucket_type buckets[100];
|
||||
|
||||
List my_list;
|
||||
Slist my_slist;
|
||||
Set my_set;
|
||||
USet my_uset(USet::bucket_traits(buckets, 100));
|
||||
|
||||
//Now insert them in the reverse order
|
||||
//in the base hook intrusive list
|
||||
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it){
|
||||
my_list.push_front(*it);
|
||||
my_slist.push_front(*it);
|
||||
my_set.insert(*it);
|
||||
my_uset.insert(*it);
|
||||
}
|
||||
|
||||
//Now test lists
|
||||
{
|
||||
List::const_iterator list_it(my_list.cbegin());
|
||||
Slist::const_iterator slist_it(my_slist.cbegin());
|
||||
Set::const_reverse_iterator set_rit(my_set.crbegin());
|
||||
VectRit vect_it(values.rbegin()), vect_itend(values.rend());
|
||||
|
||||
//Test the objects inserted in the base hook list
|
||||
for(; vect_it != vect_itend; ++vect_it, ++list_it, ++slist_it, ++set_rit){
|
||||
if(&*list_it != &*vect_it) return 1;
|
||||
if(&*slist_it != &*vect_it) return 1;
|
||||
if(&*set_rit != &*vect_it) return 1;
|
||||
if(my_uset.find(*set_rit) == my_uset.cend()) return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
240
test/external_value_traits_test.cpp
Normal file
240
test/external_value_traits_test.cpp
Normal file
@ -0,0 +1,240 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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/list.hpp>
|
||||
#include <boost/intrusive/slist.hpp>
|
||||
#include <boost/intrusive/rbtree.hpp>
|
||||
#include <boost/intrusive/hashtable.hpp>
|
||||
#include <boost/pointer_to_other.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 boost::pointer_to_other
|
||||
<node_ptr, MyClass>::type pointer;
|
||||
typedef typename boost::pointer_to_other
|
||||
<node_ptr, 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 the reverse order
|
||||
//in the base hook intrusive list
|
||||
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 lists
|
||||
{
|
||||
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 the objects inserted in the base hook list
|
||||
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;
|
||||
}
|
@ -35,17 +35,19 @@ struct test_list
|
||||
static void test_shift(std::vector<value_type>& values);
|
||||
static void test_swap(std::vector<value_type>& values);
|
||||
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_list<ValueTraits>::test_all(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef boost::intrusive::list
|
||||
< ValueTraits
|
||||
, ValueTraits::value_type::constant_time_size
|
||||
, std::size_t
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef list
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, size_type<std::size_t>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> list_type;
|
||||
|
||||
{
|
||||
list_type list(values.begin(), values.end());
|
||||
test::test_container(list);
|
||||
@ -60,9 +62,15 @@ void test_list<ValueTraits>::test_all(std::vector<typename ValueTraits::value_ty
|
||||
test_shift(values);
|
||||
test_swap(values);
|
||||
test_clone(values);
|
||||
|
||||
list_type testlist(values.begin(), values.end());
|
||||
list_type testlist2;
|
||||
test_container_from_end(values);
|
||||
/*
|
||||
const char *list_name = typeid(list_type).name();
|
||||
std::cout << list_name << std::endl << strlen(list_name) << std::endl;
|
||||
const char *value_t = typeid(typename list_type::value_traits).name();
|
||||
std::cout << value_t << std::endl << strlen(value_t) << std::endl;
|
||||
const char *list_it_name = typeid(typename list_type::iterator).name();
|
||||
std::cout << list_it_name << std::endl << strlen(list_it_name ) << std::endl;
|
||||
*/
|
||||
}
|
||||
|
||||
//test: push_front, pop_front, push_back, pop_back, front, back, size, empty:
|
||||
@ -70,10 +78,12 @@ template<class ValueTraits>
|
||||
void test_list<ValueTraits>
|
||||
::test_front_back(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef boost::intrusive::list
|
||||
< ValueTraits
|
||||
, ValueTraits::value_type::constant_time_size
|
||||
, std::size_t
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef list
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, size_type<std::size_t>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> list_type;
|
||||
list_type testlist;
|
||||
BOOST_TEST (testlist.empty());
|
||||
@ -104,12 +114,12 @@ template<class ValueTraits>
|
||||
void test_list<ValueTraits>
|
||||
::test_sort(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type testvalue_t;
|
||||
std::vector<int> expected;
|
||||
typedef boost::intrusive::list
|
||||
< ValueTraits
|
||||
, ValueTraits::value_type::constant_time_size
|
||||
, std::size_t
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef list
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, size_type<std::size_t>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> list_type;
|
||||
list_type testlist(values.begin(), values.end());
|
||||
|
||||
@ -125,17 +135,17 @@ void test_list<ValueTraits>
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist.begin() ); }
|
||||
}
|
||||
|
||||
//test: assign, insert, const_iterator, const_reverse_iterator, erase, iterator_to:
|
||||
//test: assign, insert, const_iterator, const_reverse_iterator, erase, s_iterator_to:
|
||||
template<class ValueTraits>
|
||||
void test_list<ValueTraits>
|
||||
::test_insert(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type testvalue_t;
|
||||
std::vector<int> expected;
|
||||
typedef boost::intrusive::list
|
||||
< ValueTraits
|
||||
, ValueTraits::value_type::constant_time_size
|
||||
, std::size_t
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef list
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, size_type<std::size_t>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> list_type;
|
||||
list_type testlist;
|
||||
testlist.assign (&values[0] + 2, &values[0] + 5);
|
||||
@ -159,6 +169,9 @@ void test_list<ValueTraits>
|
||||
i = testlist.iterator_to (values[4]);
|
||||
BOOST_TEST (&*i == &values[4]);
|
||||
|
||||
i = list_type::s_iterator_to (values[4]);
|
||||
BOOST_TEST (&*i == &values[4]);
|
||||
|
||||
i = testlist.erase (i);
|
||||
BOOST_TEST (i == testlist.end());
|
||||
|
||||
@ -170,15 +183,14 @@ template<class ValueTraits>
|
||||
void test_list<ValueTraits>
|
||||
::test_shift(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type testvalue_t;
|
||||
typedef boost::intrusive::list
|
||||
< ValueTraits
|
||||
, ValueTraits::value_type::constant_time_size
|
||||
, std::size_t
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef list
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, size_type<std::size_t>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> list_type;
|
||||
list_type testlist;
|
||||
std::vector<int> expected;
|
||||
|
||||
const int num_values = (int)values.size();
|
||||
std::vector<int> expected_values(num_values);
|
||||
|
||||
@ -210,12 +222,13 @@ template<class ValueTraits>
|
||||
void test_list<ValueTraits>
|
||||
::test_swap(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type testvalue_t;
|
||||
typedef boost::intrusive::list
|
||||
<ValueTraits
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef list
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, size_type<std::size_t>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> list_type;
|
||||
std::vector<int> expected;
|
||||
{
|
||||
list_type testlist1 (&values[0], &values[0] + 2);
|
||||
list_type testlist2;
|
||||
@ -267,23 +280,40 @@ void test_list<ValueTraits>
|
||||
}
|
||||
}
|
||||
|
||||
template<class ValueTraits>
|
||||
void test_list<ValueTraits>
|
||||
::test_container_from_end(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef list
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, size_type<std::size_t>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> list_type;
|
||||
list_type testlist1 (&values[0], &values[0] + values.size());
|
||||
BOOST_TEST (testlist1 == list_type::container_from_end_iterator(testlist1.end()));
|
||||
BOOST_TEST (testlist1 == list_type::container_from_end_iterator(testlist1.cend()));
|
||||
}
|
||||
|
||||
|
||||
template<class ValueTraits>
|
||||
void test_list<ValueTraits>
|
||||
::test_clone(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type testvalue_t;
|
||||
std::vector<int> expected;
|
||||
typedef boost::intrusive::list
|
||||
<ValueTraits
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef list
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, size_type<std::size_t>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> list_type;
|
||||
|
||||
list_type testlist1 (&values[0], &values[0] + values.size());
|
||||
list_type testlist2;
|
||||
|
||||
testlist2.clone_from(testlist1, test::new_cloner(), test::delete_disposer());
|
||||
testlist2.clone_from(testlist1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
|
||||
BOOST_TEST (testlist2 == testlist1);
|
||||
testlist2.clear_and_dispose(test::delete_disposer());
|
||||
testlist2.clear_and_dispose(test::delete_disposer<value_type>());
|
||||
BOOST_TEST (testlist2.empty());
|
||||
}
|
||||
|
||||
@ -293,17 +323,24 @@ class test_main_template
|
||||
public:
|
||||
int operator()()
|
||||
{
|
||||
typedef testvalue<VoidPointer, constant_time_size> testvalue_t;
|
||||
std::vector<testvalue_t> data (5);
|
||||
typedef testvalue<VoidPointer, constant_time_size> value_type;
|
||||
std::vector<value_type> data (5);
|
||||
for (int i = 0; i < 5; ++i)
|
||||
data[i].value_ = i + 1;
|
||||
|
||||
test_list <typename testvalue_t::list_base_hook_t::template
|
||||
value_traits<testvalue_t> >::test_all(data);
|
||||
|
||||
test_list <typename testvalue_t::list_member_hook_t::template
|
||||
value_traits<testvalue_t, &testvalue_t::list_node_> >::test_all(data);
|
||||
|
||||
test_list < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::list_base_hook_t
|
||||
>::type
|
||||
>::test_all(data);
|
||||
test_list < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::list_member_hook_t
|
||||
, &value_type::list_node_
|
||||
>
|
||||
>::type
|
||||
>::test_all(data);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
@ -314,48 +351,64 @@ class test_main_template<VoidPointer, false>
|
||||
public:
|
||||
int operator()()
|
||||
{
|
||||
typedef testvalue<VoidPointer, false> testvalue_t;
|
||||
std::vector<testvalue_t> data (5);
|
||||
typedef testvalue<VoidPointer, false> value_type;
|
||||
std::vector<value_type> data (5);
|
||||
for (int i = 0; i < 5; ++i)
|
||||
data[i].value_ = i + 1;
|
||||
|
||||
test_list <typename testvalue_t::list_base_hook_t::template
|
||||
value_traits<testvalue_t> >::test_all(data);
|
||||
test_list < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::list_base_hook_t
|
||||
>::type
|
||||
>::test_all(data);
|
||||
|
||||
test_list <typename testvalue_t::list_member_hook_t::template
|
||||
value_traits<testvalue_t, &testvalue_t::list_node_> >::test_all(data);
|
||||
test_list < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::list_member_hook_t
|
||||
, &value_type::list_node_
|
||||
>
|
||||
>::type
|
||||
>::test_all(data);
|
||||
/*
|
||||
test_list<stateful_value_traits
|
||||
< value_type
|
||||
, list_node_traits<VoidPointer>
|
||||
, safe_link>
|
||||
>::test_all(data);
|
||||
*/
|
||||
test_list < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::list_auto_base_hook_t
|
||||
>::type
|
||||
>::test_all(data);
|
||||
|
||||
test_list <typename testvalue_t::list_auto_base_hook_t::template
|
||||
value_traits<testvalue_t> >::test_all(data);
|
||||
|
||||
test_list <typename testvalue_t::list_auto_member_hook_t::template
|
||||
value_traits<testvalue_t, &testvalue_t::list_auto_node_> >::test_all(data);
|
||||
test_list < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::list_auto_member_hook_t
|
||||
, &value_type::list_auto_node_
|
||||
>
|
||||
>::type
|
||||
>::test_all(data);
|
||||
/*
|
||||
test_list<stateful_value_traits
|
||||
< value_type
|
||||
, list_node_traits<VoidPointer>
|
||||
, auto_unlink>
|
||||
>::test_all(data);
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
//Explicit instantiations of non-counted classes
|
||||
//template class boost::intrusive::list<list_base_raw, false>;
|
||||
//template class boost::intrusive::list<list_member_raw, false>;
|
||||
//template class boost::intrusive::list<list_auto_base_raw, false>;
|
||||
//template class boost::intrusive::list<list_auto_member_raw, false>;
|
||||
//template class boost::intrusive::list<list_base_smart, false>;
|
||||
//template class boost::intrusive::list<list_member_smart, false>;
|
||||
//template class boost::intrusive::list<list_auto_base_smart, false>;
|
||||
//template class boost::intrusive::list<list_auto_member_smart, false>;
|
||||
|
||||
//Explicit instantiation of counted classes
|
||||
//template class boost::intrusive::list<list_base_raw_t, true>;
|
||||
//template class boost::intrusive::list<list_member_raw_t, true>;
|
||||
//template class boost::intrusive::list<list_base_smart_t, true>;
|
||||
//template class boost::intrusive::list<list_member_smart_t, true>;
|
||||
|
||||
int main( int, char* [] )
|
||||
{
|
||||
test_main_template<void*, false>()();
|
||||
test_main_template<boost::intrusive::smart_ptr<void>, false>()();
|
||||
test_main_template<smart_ptr<void>, false>()();
|
||||
test_main_template<void*, true>()();
|
||||
test_main_template<boost::intrusive::smart_ptr<void>, true>()();
|
||||
test_main_template<smart_ptr<void>, true>()();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
|
148
test/make_functions_test.cpp
Normal file
148
test/make_functions_test.cpp
Normal file
@ -0,0 +1,148 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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/list.hpp>
|
||||
#include <boost/intrusive/slist.hpp>
|
||||
#include <boost/intrusive/set.hpp>
|
||||
#include <boost/intrusive/unordered_set.hpp>
|
||||
#include <boost/intrusive/detail/mpl.hpp>
|
||||
#include "smart_ptr.hpp"
|
||||
#include <vector>
|
||||
|
||||
using namespace boost::intrusive;
|
||||
|
||||
class MyClass
|
||||
: public make_list_base_hook
|
||||
< void_pointer<smart_ptr<void> >, link_mode<normal_link> >::type
|
||||
, public make_slist_base_hook
|
||||
< void_pointer<smart_ptr<void> >, link_mode<normal_link> >::type
|
||||
, public make_set_base_hook
|
||||
< void_pointer<smart_ptr<void> >, link_mode<normal_link> >::type
|
||||
, public make_unordered_set_base_hook
|
||||
< void_pointer<smart_ptr<void> >, link_mode<normal_link> >::type
|
||||
{
|
||||
int int_;
|
||||
|
||||
public:
|
||||
MyClass(int i)
|
||||
: int_(i)
|
||||
{}
|
||||
|
||||
friend bool operator<(const MyClass &l, const MyClass &r)
|
||||
{ return l.int_ < r.int_; }
|
||||
|
||||
friend bool operator==(const MyClass &l, const MyClass &r)
|
||||
{ return l.int_ == r.int_; }
|
||||
|
||||
friend std::size_t hash_value(const MyClass &v)
|
||||
{ return boost::hash_value(v.int_); }
|
||||
};
|
||||
|
||||
//Define a list that will store MyClass using the public base hook
|
||||
typedef make_list<MyClass>::type List;
|
||||
typedef make_slist<MyClass>::type Slist;
|
||||
typedef make_set<MyClass>::type Set;
|
||||
typedef make_unordered_set<MyClass>::type USet;
|
||||
|
||||
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));
|
||||
|
||||
USet::bucket_type buckets[100];
|
||||
|
||||
List my_list;
|
||||
Slist my_slist;
|
||||
Set my_set;
|
||||
USet my_uset(USet::bucket_traits(buckets, 100));
|
||||
|
||||
//Now insert them in the reverse order
|
||||
//in the base hook intrusive list
|
||||
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it){
|
||||
my_list.push_front(*it);
|
||||
my_slist.push_front(*it);
|
||||
my_set.insert(*it);
|
||||
my_uset.insert(*it);
|
||||
}
|
||||
|
||||
//Now test lists
|
||||
{
|
||||
List::const_iterator list_it(my_list.cbegin());
|
||||
Slist::const_iterator slist_it(my_slist.cbegin());
|
||||
Set::const_reverse_iterator set_rit(my_set.crbegin());
|
||||
VectRit vect_it(values.rbegin()), vect_itend(values.rend());
|
||||
|
||||
//Test the objects inserted in the base hook list
|
||||
for(; vect_it != vect_itend; ++vect_it, ++list_it, ++slist_it, ++set_rit){
|
||||
if(&*list_it != &*vect_it) return 1;
|
||||
if(&*slist_it != &*vect_it) return 1;
|
||||
if(&*set_rit != &*vect_it) return 1;
|
||||
if(my_uset.find(*set_rit) == my_uset.cend()) return 1;
|
||||
}
|
||||
}
|
||||
|
||||
//Check defined types and implicitly defined types are equal
|
||||
if(detail::is_same<make_list_base_hook<void_pointer<void*>, link_mode<safe_link> >::type
|
||||
,make_list_base_hook<>::type
|
||||
>::value == false){
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(detail::is_same<make_slist_base_hook<void_pointer<void*>, link_mode<safe_link> >::type
|
||||
,make_slist_base_hook<>::type
|
||||
>::value == false){
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(detail::is_same<make_set_base_hook<void_pointer<void*>, link_mode<safe_link> >::type
|
||||
,make_set_base_hook<>::type
|
||||
>::value == false){
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(detail::is_same<make_unordered_set_base_hook<void_pointer<void*>, link_mode<safe_link> >::type
|
||||
,make_unordered_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
|
||||
>::value == true){
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(detail::is_same<make_slist_base_hook<void_pointer<void*>, link_mode<normal_link> >::type
|
||||
,make_slist_base_hook<>::type
|
||||
>::value == true){
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(detail::is_same<make_set_base_hook<void_pointer<void*>, link_mode<normal_link> >::type
|
||||
,make_set_base_hook<>::type
|
||||
>::value == true){
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(detail::is_same<make_unordered_set_base_hook<void_pointer<void*>, link_mode<normal_link> >::type
|
||||
,make_unordered_set_base_hook<>::type
|
||||
>::value == true){
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
@ -10,6 +10,7 @@
|
||||
// See http://www.boost.org/libs/intrusive for documentation.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/set.hpp>
|
||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||
@ -22,7 +23,6 @@
|
||||
#include "test_container.hpp"
|
||||
|
||||
using namespace boost::intrusive;
|
||||
|
||||
template<class ValueTraits>
|
||||
struct test_multiset
|
||||
{
|
||||
@ -34,15 +34,17 @@ struct test_multiset
|
||||
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_multiset<ValueTraits>::test_all (std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef multiset
|
||||
<ValueTraits
|
||||
,std::less<typename ValueTraits::value_type>
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> multiset_type;
|
||||
{
|
||||
multiset_type testset(values.begin(), values.end());
|
||||
@ -63,21 +65,24 @@ void test_multiset<ValueTraits>::test_all (std::vector<typename ValueTraits::val
|
||||
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_multiset<ValueTraits>::test_impl()
|
||||
{
|
||||
typedef typename ValueTraits::value_type testvalue_t;
|
||||
std::vector<testvalue_t> values (5);
|
||||
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 multiset
|
||||
<ValueTraits
|
||||
,std::less<typename ValueTraits::value_type>
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
< 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]);
|
||||
@ -94,12 +99,13 @@ void test_multiset<ValueTraits>::test_impl()
|
||||
template<class ValueTraits>
|
||||
void test_multiset<ValueTraits>::test_sort(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type testvalue_t;
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef multiset
|
||||
<ValueTraits
|
||||
,std::less<typename ValueTraits::value_type>
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
< 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() ); }
|
||||
@ -108,9 +114,10 @@ void test_multiset<ValueTraits>::test_sort(std::vector<typename ValueTraits::val
|
||||
BOOST_TEST (testset1.empty());
|
||||
|
||||
typedef multiset
|
||||
<ValueTraits
|
||||
,even_odd
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
<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 };
|
||||
@ -124,11 +131,12 @@ void test_multiset<ValueTraits>::test_sort(std::vector<typename ValueTraits::val
|
||||
template<class ValueTraits>
|
||||
void test_multiset<ValueTraits>::test_insert(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type testvalue_t;
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef multiset
|
||||
<ValueTraits
|
||||
,std::less<typename ValueTraits::value_type>
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, size_type<std::size_t>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> multiset_type;
|
||||
|
||||
multiset_type testset;
|
||||
@ -147,6 +155,10 @@ void test_multiset<ValueTraits>::test_insert(std::vector<typename ValueTraits::v
|
||||
|
||||
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 };
|
||||
@ -157,11 +169,12 @@ void test_multiset<ValueTraits>::test_insert(std::vector<typename ValueTraits::v
|
||||
template<class ValueTraits>
|
||||
void test_multiset<ValueTraits>::test_swap(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type testvalue_t;
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef multiset
|
||||
<ValueTraits
|
||||
,std::less<typename ValueTraits::value_type>
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
< 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;
|
||||
@ -182,16 +195,17 @@ void test_multiset<ValueTraits>::test_swap(std::vector<typename ValueTraits::val
|
||||
template<class ValueTraits>
|
||||
void test_multiset<ValueTraits>::test_find(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type testvalue_t;
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef multiset
|
||||
<ValueTraits
|
||||
,std::less<typename ValueTraits::value_type>
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
< 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;
|
||||
|
||||
testvalue_t cmp_val;
|
||||
value_type cmp_val;
|
||||
cmp_val.value_ = 2;
|
||||
iterator i = testset.find (cmp_val);
|
||||
BOOST_TEST (i->value_ == 2);
|
||||
@ -210,20 +224,37 @@ template<class ValueTraits>
|
||||
void test_multiset<ValueTraits>
|
||||
::test_clone(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type testvalue_t;
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef multiset
|
||||
<ValueTraits
|
||||
,std::less<typename ValueTraits::value_type>
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
< 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_multiset<ValueTraits>
|
||||
::test_container_from_end(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef 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(), test::delete_disposer());
|
||||
BOOST_TEST (testmultiset2 == testmultiset1);
|
||||
testmultiset2.clear_and_dispose(test::delete_disposer());
|
||||
BOOST_TEST (testmultiset2.empty());
|
||||
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>
|
||||
@ -232,18 +263,25 @@ class test_main_template
|
||||
public:
|
||||
int operator()()
|
||||
{
|
||||
typedef testvalue<VoidPointer, constant_time_size> testvalue_t;
|
||||
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_multiset <typename testvalue_t::set_base_hook_t::template
|
||||
value_traits<testvalue_t> >::test_all(data);
|
||||
|
||||
test_multiset <typename testvalue_t::set_member_hook_t::template
|
||||
value_traits<testvalue_t, &testvalue_t::set_node_> >::test_all(data);
|
||||
|
||||
test_multiset < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::set_base_hook_t
|
||||
>::type
|
||||
>::test_all(data);
|
||||
test_multiset < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::set_member_hook_t
|
||||
, &value_type::set_node_
|
||||
>
|
||||
>::type
|
||||
>::test_all(data);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
@ -254,55 +292,73 @@ class test_main_template<VoidPointer, false>
|
||||
public:
|
||||
int operator()()
|
||||
{
|
||||
typedef testvalue<VoidPointer, false> testvalue_t;
|
||||
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_multiset <typename testvalue_t::set_base_hook_t::template
|
||||
value_traits<testvalue_t> >::test_all(data);
|
||||
test_multiset < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::set_base_hook_t
|
||||
>::type
|
||||
>::test_all(data);
|
||||
|
||||
test_multiset <typename testvalue_t::set_member_hook_t::template
|
||||
value_traits<testvalue_t, &testvalue_t::set_node_> >::test_all(data);
|
||||
test_multiset < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::set_member_hook_t
|
||||
, &value_type::set_node_
|
||||
>
|
||||
>::type
|
||||
>::test_all(data);
|
||||
|
||||
test_multiset <typename testvalue_t::set_auto_base_hook_t::template
|
||||
value_traits<testvalue_t> >::test_all(data);
|
||||
test_multiset < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::set_auto_base_hook_t
|
||||
>::type
|
||||
>::test_all(data);
|
||||
|
||||
test_multiset <typename testvalue_t::set_auto_member_hook_t::template
|
||||
value_traits<testvalue_t, &testvalue_t::set_auto_node_> >::test_all(data);
|
||||
test_multiset < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::set_auto_member_hook_t
|
||||
, &value_type::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>;
|
||||
//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>;
|
||||
*/
|
||||
//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>()();
|
||||
@ -311,5 +367,3 @@ int main( int, char* [] )
|
||||
test_main_template<smart_ptr<void>, true>()();
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
|
@ -34,15 +34,17 @@ struct test_set
|
||||
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_set<ValueTraits>::test_all(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef boost::intrusive::set
|
||||
<ValueTraits
|
||||
,std::less<typename ValueTraits::value_type>
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef set
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> set_type;
|
||||
{
|
||||
set_type testset(values.begin(), values.end());
|
||||
@ -63,21 +65,23 @@ void test_set<ValueTraits>::test_all(std::vector<typename ValueTraits::value_typ
|
||||
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_set<ValueTraits>::test_impl()
|
||||
{
|
||||
typedef typename ValueTraits::value_type testvalue_t;
|
||||
std::vector<testvalue_t> values (5);
|
||||
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 boost::intrusive::set
|
||||
<ValueTraits
|
||||
,std::less<typename ValueTraits::value_type>
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef set
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> set_type;
|
||||
set_type testset;
|
||||
for (int i = 0; i < 5; ++i)
|
||||
@ -95,11 +99,11 @@ void test_set<ValueTraits>::test_impl()
|
||||
template<class ValueTraits>
|
||||
void test_set<ValueTraits>::test_sort(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type testvalue_t;
|
||||
typedef boost::intrusive::set
|
||||
<ValueTraits
|
||||
,std::less<typename ValueTraits::value_type>
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef set
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> set_type;
|
||||
set_type testset1 (values.begin(), values.end());
|
||||
{ int init_values [] = { 1, 2, 3, 4, 5 };
|
||||
@ -108,10 +112,12 @@ void test_set<ValueTraits>::test_sort(std::vector<typename ValueTraits::value_ty
|
||||
testset1.clear();
|
||||
BOOST_TEST (testset1.empty());
|
||||
|
||||
typedef boost::intrusive::set
|
||||
<ValueTraits
|
||||
,even_odd
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef 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 };
|
||||
@ -120,15 +126,15 @@ void test_set<ValueTraits>::test_sort(std::vector<typename ValueTraits::value_ty
|
||||
BOOST_TEST (testset2.rbegin()->value_ == 5);
|
||||
}
|
||||
|
||||
//test: insert, const_iterator, const_reverse_iterator, erase, iterator_to:
|
||||
//test: insert, const_iterator, const_reverse_iterator, erase, s_iterator_to:
|
||||
template<class ValueTraits>
|
||||
void test_set<ValueTraits>::test_insert(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type testvalue_t;
|
||||
typedef boost::intrusive::set
|
||||
<ValueTraits
|
||||
,std::less<typename ValueTraits::value_type>
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef set
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> set_type;
|
||||
set_type testset;
|
||||
testset.insert(&values[0] + 2, &values[0] + 5);
|
||||
@ -149,6 +155,9 @@ void test_set<ValueTraits>::test_insert(std::vector<typename ValueTraits::value_
|
||||
i = testset.iterator_to (values[2]);
|
||||
BOOST_TEST (&*i == &values[2]);
|
||||
|
||||
i = 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() ); }
|
||||
@ -158,11 +167,11 @@ void test_set<ValueTraits>::test_insert(std::vector<typename ValueTraits::value_
|
||||
template<class ValueTraits>
|
||||
void test_set<ValueTraits>::test_swap(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type testvalue_t;
|
||||
typedef boost::intrusive::set
|
||||
<ValueTraits
|
||||
,std::less<typename ValueTraits::value_type>
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef set
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> set_type;
|
||||
set_type testset1 (&values[0], &values[0] + 2);
|
||||
set_type testset2;
|
||||
@ -185,16 +194,16 @@ void test_set<ValueTraits>::test_swap(std::vector<typename ValueTraits::value_ty
|
||||
template<class ValueTraits>
|
||||
void test_set<ValueTraits>::test_find(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type testvalue_t;
|
||||
typedef boost::intrusive::set
|
||||
<ValueTraits
|
||||
,std::less<typename ValueTraits::value_type>
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef set
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> set_type;
|
||||
set_type testset (values.begin(), values.end());
|
||||
typedef typename set_type::iterator iterator;
|
||||
|
||||
testvalue_t cmp_val;
|
||||
value_type cmp_val;
|
||||
cmp_val.value_ = 2;
|
||||
iterator i = testset.find (cmp_val);
|
||||
BOOST_TEST (i->value_ == 2);
|
||||
@ -213,20 +222,35 @@ template<class ValueTraits>
|
||||
void test_set<ValueTraits>
|
||||
::test_clone(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type testvalue_t;
|
||||
typedef boost::intrusive::set
|
||||
<ValueTraits
|
||||
,std::less<typename ValueTraits::value_type>
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef set
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> set_type;
|
||||
|
||||
set_type testset1 (&values[0], &values[0] + values.size());
|
||||
set_type testset2;
|
||||
set_type testset1 (&values[0], &values[0] + values.size());
|
||||
set_type testset2;
|
||||
|
||||
testset2.clone_from(testset1, test::new_cloner(), test::delete_disposer());
|
||||
BOOST_TEST (testset2 == testset1);
|
||||
testset2.clear_and_dispose(test::delete_disposer());
|
||||
BOOST_TEST (testset2.empty());
|
||||
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_set<ValueTraits>
|
||||
::test_container_from_end(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef set
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> set_type;
|
||||
set_type testset (&values[0], &values[0] + values.size());
|
||||
BOOST_TEST (testset == set_type::container_from_end_iterator(testset.end()));
|
||||
BOOST_TEST (testset == set_type::container_from_end_iterator(testset.cend()));
|
||||
}
|
||||
|
||||
template<class VoidPointer, bool constant_time_size>
|
||||
@ -235,18 +259,25 @@ class test_main_template
|
||||
public:
|
||||
int operator()()
|
||||
{
|
||||
typedef testvalue<VoidPointer, constant_time_size> testvalue_t;
|
||||
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_set <typename testvalue_t::set_base_hook_t::template
|
||||
value_traits<testvalue_t> >::test_all(data);
|
||||
|
||||
test_set <typename testvalue_t::set_member_hook_t::template
|
||||
value_traits<testvalue_t, &testvalue_t::set_node_> >::test_all(data);
|
||||
|
||||
test_set < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::set_base_hook_t
|
||||
>::type
|
||||
>::test_all(data);
|
||||
test_set < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::set_member_hook_t
|
||||
, &value_type::set_node_
|
||||
>
|
||||
>::type
|
||||
>::test_all(data);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
@ -257,61 +288,53 @@ class test_main_template<VoidPointer, false>
|
||||
public:
|
||||
int operator()()
|
||||
{
|
||||
typedef testvalue<VoidPointer, false> testvalue_t;
|
||||
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_set <typename testvalue_t::set_base_hook_t::template
|
||||
value_traits<testvalue_t> >::test_all(data);
|
||||
test_set < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::set_base_hook_t
|
||||
>::type
|
||||
>::test_all(data);
|
||||
|
||||
test_set <typename testvalue_t::set_member_hook_t::template
|
||||
value_traits<testvalue_t, &testvalue_t::set_node_> >::test_all(data);
|
||||
test_set < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::set_member_hook_t
|
||||
, &value_type::set_node_
|
||||
>
|
||||
>::type
|
||||
>::test_all(data);
|
||||
|
||||
test_set <typename testvalue_t::set_auto_base_hook_t::template
|
||||
value_traits<testvalue_t> >::test_all(data);
|
||||
test_set < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::set_auto_base_hook_t
|
||||
>::type
|
||||
>::test_all(data);
|
||||
|
||||
test_set < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::set_auto_member_hook_t
|
||||
, &value_type::set_auto_node_
|
||||
>
|
||||
>::type
|
||||
>::test_all(data);
|
||||
|
||||
test_set <typename testvalue_t::set_auto_member_hook_t::template
|
||||
value_traits<testvalue_t, &testvalue_t::set_auto_node_> >::test_all(data);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
/*
|
||||
//Explicit instantiations of non-counted classes
|
||||
template class boost::intrusive::set
|
||||
<set_base_raw, std::less<set_base_raw::value_type>, false>;
|
||||
template class boost::intrusive::set
|
||||
<set_member_raw, std::less<set_member_raw::value_type>, false>;
|
||||
template class boost::intrusive::set
|
||||
<set_auto_base_raw, std::less<set_auto_base_raw::value_type>, false>;
|
||||
template class boost::intrusive::set
|
||||
<set_auto_member_raw, std::less<set_auto_member_raw::value_type>, false>;
|
||||
template class boost::intrusive::set
|
||||
<set_base_smart, std::less<set_base_smart::value_type>, false>;
|
||||
template class boost::intrusive::set
|
||||
<set_member_smart, std::less<set_member_smart::value_type>, false>;
|
||||
template class boost::intrusive::set
|
||||
<set_auto_base_smart, std::less<set_auto_base_smart::value_type>, false>;
|
||||
template class boost::intrusive::set
|
||||
<set_auto_member_smart, std::less<set_auto_member_smart::value_type>, false>;
|
||||
|
||||
//Explicit instantiation of counted classes
|
||||
template class boost::intrusive::set
|
||||
<set_base_raw_t, std::less<set_base_raw_t::value_type>, true>;
|
||||
template class boost::intrusive::set
|
||||
<set_member_raw_t, std::less<set_member_raw_t::value_type>, true>;
|
||||
template class boost::intrusive::set
|
||||
<set_base_smart_t, std::less<set_base_smart_t::value_type>, true>;
|
||||
template class boost::intrusive::set
|
||||
<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<boost::intrusive::smart_ptr<void>, false>()();
|
||||
test_main_template<smart_ptr<void>, false>()();
|
||||
test_main_template<void*, true>()();
|
||||
test_main_template<boost::intrusive::smart_ptr<void>, true>()();
|
||||
test_main_template<smart_ptr<void>, true>()();
|
||||
return boost::report_errors();
|
||||
}
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
|
@ -10,6 +10,7 @@
|
||||
// See http://www.boost.org/libs/intrusive for documentation.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/slist.hpp>
|
||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||
@ -36,15 +37,19 @@ struct test_slist
|
||||
static void test_swap(std::vector<value_type>& values);
|
||||
static void test_slow_insert (std::vector<value_type>& values);
|
||||
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_slist<ValueTraits>
|
||||
::test_all (std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef boost::intrusive::slist
|
||||
<ValueTraits
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef slist
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, size_type<std::size_t>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> list_type;
|
||||
{
|
||||
list_type list(values.begin(), values.end());
|
||||
@ -61,6 +66,7 @@ void test_slist<ValueTraits>
|
||||
test_slow_insert (values);
|
||||
test_swap(values);
|
||||
test_clone(values);
|
||||
test_container_from_end(values);
|
||||
}
|
||||
|
||||
//test: push_front, pop_front, front, size, empty:
|
||||
@ -68,9 +74,12 @@ template<class ValueTraits>
|
||||
void test_slist<ValueTraits>
|
||||
::test_front_back (std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef boost::intrusive::slist
|
||||
<ValueTraits
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef slist
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, size_type<std::size_t>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> list_type;
|
||||
list_type testlist;
|
||||
BOOST_TEST (testlist.empty());
|
||||
@ -96,10 +105,12 @@ template<class ValueTraits>
|
||||
void test_slist<ValueTraits>
|
||||
::test_merge (std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type testvalue_t;
|
||||
typedef boost::intrusive::slist
|
||||
<ValueTraits
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef slist
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, size_type<std::size_t>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> list_type;
|
||||
list_type testlist1, testlist2;
|
||||
testlist1.push_front (values[0]);
|
||||
@ -117,10 +128,12 @@ template<class ValueTraits>
|
||||
void test_slist<ValueTraits>
|
||||
::test_sort(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type testvalue_t;
|
||||
typedef boost::intrusive::slist
|
||||
<ValueTraits
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef slist
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, size_type<std::size_t>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> list_type;
|
||||
list_type testlist (values.begin(), values.end());
|
||||
|
||||
@ -136,15 +149,17 @@ void test_slist<ValueTraits>
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist.begin() ); }
|
||||
}
|
||||
|
||||
//test: assign, insert_after, const_iterator, erase_after, iterator_to, previous:
|
||||
//test: assign, insert_after, const_iterator, erase_after, s_iterator_to, previous:
|
||||
template<class ValueTraits>
|
||||
void test_slist<ValueTraits>
|
||||
::test_insert(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type testvalue_t;
|
||||
typedef boost::intrusive::slist
|
||||
<ValueTraits
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef slist
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, size_type<std::size_t>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> list_type;
|
||||
list_type testlist;
|
||||
testlist.assign (&values[0] + 2, &values[0] + 5);
|
||||
@ -162,6 +177,8 @@ void test_slist<ValueTraits>
|
||||
|
||||
i = testlist.iterator_to (values[4]);
|
||||
BOOST_TEST (&*i == &values[4]);
|
||||
i = list_type::s_iterator_to (values[4]);
|
||||
BOOST_TEST (&*i == &values[4]);
|
||||
i = testlist.previous (i);
|
||||
BOOST_TEST (&*i == &values[0]);
|
||||
|
||||
@ -171,15 +188,17 @@ void test_slist<ValueTraits>
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, const_testlist.begin() ); }
|
||||
}
|
||||
|
||||
//test: insert, const_iterator, erase, iterator_to:
|
||||
//test: insert, const_iterator, erase, siterator_to:
|
||||
template<class ValueTraits>
|
||||
void test_slist<ValueTraits>
|
||||
::test_slow_insert (std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type testvalue_t;
|
||||
typedef boost::intrusive::slist
|
||||
<ValueTraits
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef slist
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, size_type<std::size_t>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> list_type;
|
||||
list_type testlist;
|
||||
testlist.push_front (values[4]);
|
||||
@ -199,6 +218,9 @@ void test_slist<ValueTraits>
|
||||
i = testlist.iterator_to (values[4]);
|
||||
BOOST_TEST (&*i == &values[4]);
|
||||
|
||||
i = list_type::s_iterator_to (values[4]);
|
||||
BOOST_TEST (&*i == &values[4]);
|
||||
|
||||
i = testlist.erase (i);
|
||||
BOOST_TEST (i == testlist.end());
|
||||
|
||||
@ -214,10 +236,12 @@ template<class ValueTraits>
|
||||
void test_slist<ValueTraits>
|
||||
::test_shift(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type testvalue_t;
|
||||
typedef boost::intrusive::slist
|
||||
<ValueTraits
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef slist
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, size_type<std::size_t>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> list_type;
|
||||
list_type testlist;
|
||||
|
||||
@ -254,10 +278,12 @@ template<class ValueTraits>
|
||||
void test_slist<ValueTraits>
|
||||
::test_swap(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type testvalue_t;
|
||||
typedef boost::intrusive::slist
|
||||
<ValueTraits
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef slist
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, size_type<std::size_t>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> list_type;
|
||||
{
|
||||
list_type testlist1 (&values[0], &values[0] + 2);
|
||||
@ -306,37 +332,63 @@ template<class ValueTraits>
|
||||
void test_slist<ValueTraits>
|
||||
::test_clone(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type testvalue_t;
|
||||
typedef boost::intrusive::slist
|
||||
<ValueTraits
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef slist
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, size_type<std::size_t>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> list_type;
|
||||
|
||||
list_type testlist1 (&values[0], &values[0] + values.size());
|
||||
list_type testlist2;
|
||||
|
||||
testlist2.clone_from(testlist1, test::new_cloner(), test::delete_disposer());
|
||||
testlist2.clone_from(testlist1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
|
||||
BOOST_TEST (testlist2 == testlist1);
|
||||
testlist2.clear_and_dispose(test::delete_disposer());
|
||||
testlist2.clear_and_dispose(test::delete_disposer<value_type>());
|
||||
BOOST_TEST (testlist2.empty());
|
||||
}
|
||||
|
||||
template<class ValueTraits>
|
||||
void test_slist<ValueTraits>
|
||||
::test_container_from_end(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef slist
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, size_type<std::size_t>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> list_type;
|
||||
list_type testlist1 (&values[0], &values[0] + values.size());
|
||||
BOOST_TEST (testlist1 == list_type::container_from_end_iterator(testlist1.end()));
|
||||
BOOST_TEST (testlist1 == list_type::container_from_end_iterator(testlist1.cend()));
|
||||
}
|
||||
|
||||
template<class VoidPointer, bool constant_time_size>
|
||||
class test_main_template
|
||||
{
|
||||
public:
|
||||
int operator()()
|
||||
{
|
||||
typedef testvalue<VoidPointer, constant_time_size> testvalue_t;
|
||||
std::vector<testvalue_t> data (5);
|
||||
typedef testvalue<VoidPointer, constant_time_size> value_type;
|
||||
std::vector<value_type> data (5);
|
||||
for (int i = 0; i < 5; ++i)
|
||||
data[i].value_ = i + 1;
|
||||
|
||||
test_slist <typename testvalue_t::slist_base_hook_t::template
|
||||
value_traits<testvalue_t> >::test_all(data);
|
||||
|
||||
test_slist <typename testvalue_t::slist_member_hook_t::template
|
||||
value_traits<testvalue_t, &testvalue_t::slist_node_> >::test_all(data);
|
||||
test_slist < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::slist_base_hook_t
|
||||
>::type
|
||||
>::test_all(data);
|
||||
test_slist < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::slist_member_hook_t
|
||||
, &value_type::slist_node_
|
||||
>
|
||||
>::type
|
||||
>::test_all(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -348,48 +400,50 @@ class test_main_template<VoidPointer, false>
|
||||
public:
|
||||
int operator()()
|
||||
{
|
||||
typedef testvalue<VoidPointer, false> testvalue_t;
|
||||
std::vector<testvalue_t> data (5);
|
||||
typedef testvalue<VoidPointer, false> value_type;
|
||||
std::vector<value_type> data (5);
|
||||
for (int i = 0; i < 5; ++i)
|
||||
data[i].value_ = i + 1;
|
||||
|
||||
test_slist <typename testvalue_t::slist_base_hook_t::template
|
||||
value_traits<testvalue_t> >::test_all(data);
|
||||
test_slist < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::slist_base_hook_t
|
||||
>::type
|
||||
>::test_all(data);
|
||||
|
||||
test_slist <typename testvalue_t::slist_member_hook_t::template
|
||||
value_traits<testvalue_t, &testvalue_t::slist_node_> >::test_all(data);
|
||||
test_slist < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::slist_member_hook_t
|
||||
, &value_type::slist_node_
|
||||
>
|
||||
>::type
|
||||
>::test_all(data);
|
||||
|
||||
test_slist <typename testvalue_t::slist_auto_base_hook_t::template
|
||||
value_traits<testvalue_t> >::test_all(data);
|
||||
test_slist < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::slist_auto_base_hook_t
|
||||
>::type
|
||||
>::test_all(data);
|
||||
|
||||
test_slist <typename testvalue_t::slist_auto_member_hook_t::template
|
||||
value_traits<testvalue_t, &testvalue_t::slist_auto_node_> >::test_all(data);
|
||||
test_slist < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::slist_auto_member_hook_t
|
||||
, &value_type::slist_auto_node_
|
||||
>
|
||||
>::type
|
||||
>::test_all(data);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
/*
|
||||
//Explicit instantiations of non-counted classes
|
||||
template class boost::intrusive::slist<slist_base_raw, false>;
|
||||
template class boost::intrusive::slist<slist_member_raw, false>;
|
||||
template class boost::intrusive::slist<slist_auto_base_raw, false>;
|
||||
template class boost::intrusive::slist<slist_auto_member_raw, false>;
|
||||
template class boost::intrusive::slist<slist_base_smart, false>;
|
||||
template class boost::intrusive::slist<slist_member_smart, false>;
|
||||
template class boost::intrusive::slist<slist_auto_base_smart, false>;
|
||||
template class boost::intrusive::slist<slist_auto_member_smart, false>;
|
||||
|
||||
//Explicit instantiation of counted classes
|
||||
template class boost::intrusive::slist<slist_base_raw_t, true>;
|
||||
template class boost::intrusive::slist<slist_member_raw_t, true>;
|
||||
template class boost::intrusive::slist<slist_base_smart_t, true>;
|
||||
template class boost::intrusive::slist<slist_member_smart_t, true>;
|
||||
*/
|
||||
int main(int, char* [])
|
||||
{
|
||||
test_main_template<void*, false>()();
|
||||
test_main_template<boost::intrusive::smart_ptr<void>, false>()();
|
||||
test_main_template<smart_ptr<void>, false>()();
|
||||
test_main_template<void*, true>()();
|
||||
test_main_template<boost::intrusive::smart_ptr<void>, true>()();
|
||||
test_main_template<smart_ptr<void>, true>()();
|
||||
return boost::report_errors();
|
||||
}
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
|
148
test/stateful_value_traits_test.cpp
Normal file
148
test/stateful_value_traits_test.cpp
Normal file
@ -0,0 +1,148 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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/list.hpp>
|
||||
#include <boost/intrusive/slist.hpp>
|
||||
#include <boost/intrusive/set.hpp>
|
||||
#include <boost/intrusive/unordered_set.hpp>
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include <boost/pointer_to_other.hpp>
|
||||
#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_); }
|
||||
};
|
||||
|
||||
template<class T, class NodeTraits>
|
||||
struct stateful_value_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 T value_type;
|
||||
typedef typename boost::pointer_to_other
|
||||
<node_ptr, T>::type pointer;
|
||||
typedef typename boost::pointer_to_other
|
||||
<node_ptr, const T>::type const_pointer;
|
||||
static const link_mode_type link_mode = normal_link;
|
||||
|
||||
stateful_value_traits(pointer values, node_ptr node_array)
|
||||
: values_(values), node_array_(node_array)
|
||||
{}
|
||||
|
||||
node_ptr to_node_ptr (value_type &value)
|
||||
{ return node_array_ + (&value - values_); }
|
||||
|
||||
const_node_ptr to_node_ptr (const value_type &value) const
|
||||
{ return node_array_ + (&value - values_); }
|
||||
|
||||
pointer to_value_ptr(node_ptr n)
|
||||
{ return values_ + (n - node_array_); }
|
||||
|
||||
const_pointer to_value_ptr(const_node_ptr n) const
|
||||
{ return values_ + (n - node_array_); }
|
||||
|
||||
pointer values_;
|
||||
node_ptr node_array_;
|
||||
};
|
||||
|
||||
//Define a list that will store MyClass using the external hook
|
||||
typedef stateful_value_traits< MyClass, list_node_traits<void*> > list_traits;
|
||||
typedef list<MyClass, value_traits<list_traits> > List;
|
||||
|
||||
//Define a slist that will store MyClass using the external hook
|
||||
typedef stateful_value_traits< MyClass, slist_node_traits<void*> > slist_traits;
|
||||
typedef slist<MyClass, value_traits<slist_traits> > Slist;
|
||||
|
||||
//Define a set that will store MyClass using the external hook
|
||||
typedef stateful_value_traits< MyClass, rbtree_node_traits<void*> > rbtree_traits;
|
||||
typedef set<MyClass, value_traits<rbtree_traits> > Set;
|
||||
|
||||
//uset uses the same traits as slist
|
||||
typedef unordered_set<MyClass, value_traits<slist_traits> > Uset;
|
||||
|
||||
|
||||
typedef list_traits::node list_node_t;
|
||||
typedef slist_traits::node slist_node_t;
|
||||
typedef rbtree_traits::node rbtree_node_t;
|
||||
|
||||
const int NumElements = 100;
|
||||
|
||||
MyClass values [NumElements];
|
||||
list_node_t list_hook_array [NumElements];
|
||||
slist_node_t slist_hook_array [NumElements];
|
||||
rbtree_node_t rbtree_hook_array [NumElements];
|
||||
slist_node_t uset_hook_array [NumElements];
|
||||
|
||||
int main()
|
||||
{
|
||||
//Create several MyClass objects, each one with a different value
|
||||
for(int i = 0; i < NumElements; ++i)
|
||||
values[i].int_ = i;
|
||||
|
||||
Uset::bucket_type buckets[NumElements];
|
||||
|
||||
List my_list (list_traits (values, list_hook_array));
|
||||
Slist my_slist(slist_traits(values, slist_hook_array));
|
||||
Set my_set (std::less<MyClass>(), rbtree_traits(values, rbtree_hook_array));
|
||||
Uset my_uset ( Uset::bucket_traits(buckets, NumElements)
|
||||
, boost::hash<MyClass>()
|
||||
, std::equal_to<MyClass>()
|
||||
, slist_traits(values, uset_hook_array)
|
||||
);
|
||||
|
||||
//Now insert them in the reverse order
|
||||
//in the base hook intrusive list
|
||||
for(MyClass * it(&values[0]), *itend(&values[NumElements])
|
||||
; it != itend
|
||||
; ++it){
|
||||
my_list.push_front(*it);
|
||||
my_slist.push_front(*it);
|
||||
my_set.insert(*it);
|
||||
my_uset.insert(*it);
|
||||
}
|
||||
|
||||
//Now test lists
|
||||
{
|
||||
List::const_iterator list_it (my_list.cbegin());
|
||||
Slist::const_iterator slist_it(my_slist.cbegin());
|
||||
Set::const_reverse_iterator set_rit(my_set.crbegin());
|
||||
MyClass *it_val(&values[NumElements-1]), *it_rbeg_val(&values[0]-1);
|
||||
|
||||
//Test the objects inserted in the base hook list
|
||||
for(; it_val != it_rbeg_val; --it_val, ++list_it, ++slist_it, ++set_rit){
|
||||
if(&*list_it != &*it_val) return 1;
|
||||
if(&*slist_it != &*it_val) return 1;
|
||||
if(&*set_rit != &*it_val) return 1;
|
||||
if(my_uset.find(*it_val) == my_uset.cend()) return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -44,15 +44,16 @@ struct test_unordered_multiset
|
||||
template<class ValueTraits>
|
||||
void test_unordered_multiset<ValueTraits>::test_all (std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef boost::intrusive::unordered_multiset
|
||||
<ValueTraits
|
||||
,boost::hash<typename ValueTraits::value_type>
|
||||
,std::equal_to<typename ValueTraits::value_type>
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef unordered_multiset
|
||||
<value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> unordered_multiset_type;
|
||||
{
|
||||
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
||||
typename unordered_multiset_type::bucket_type buckets [BucketSize];
|
||||
unordered_multiset_type testset(buckets, BucketSize);
|
||||
unordered_multiset_type testset(bucket_traits(buckets, BucketSize));
|
||||
testset.insert(values.begin(), values.end());
|
||||
test::test_container(testset);
|
||||
testset.clear();
|
||||
@ -78,18 +79,20 @@ void test_unordered_multiset<ValueTraits>::test_all (std::vector<typename ValueT
|
||||
template<class ValueTraits>
|
||||
void test_unordered_multiset<ValueTraits>::test_impl()
|
||||
{
|
||||
typedef typename ValueTraits::value_type testvalue_t;
|
||||
std::vector<testvalue_t> values (5);
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef unordered_multiset
|
||||
<value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> unordered_multiset_type;
|
||||
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
||||
|
||||
std::vector<value_type> values (5);
|
||||
for (int i = 0; i < 5; ++i)
|
||||
values[i].value_ = i;
|
||||
typedef boost::intrusive::unordered_multiset
|
||||
<ValueTraits
|
||||
,boost::hash<typename ValueTraits::value_type>
|
||||
,std::equal_to<typename ValueTraits::value_type>
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
> unordered_multiset_type;
|
||||
|
||||
typename unordered_multiset_type::bucket_type buckets [BucketSize];
|
||||
unordered_multiset_type testset(buckets, BucketSize);
|
||||
unordered_multiset_type testset(bucket_traits(buckets, BucketSize));
|
||||
|
||||
for (int i = 0; i < 5; ++i)
|
||||
testset.insert (values[i]);
|
||||
@ -106,15 +109,16 @@ void test_unordered_multiset<ValueTraits>::test_impl()
|
||||
template<class ValueTraits>
|
||||
void test_unordered_multiset<ValueTraits>::test_sort(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type testvalue_t;
|
||||
typedef boost::intrusive::unordered_multiset
|
||||
<ValueTraits
|
||||
,boost::hash<typename ValueTraits::value_type>
|
||||
,std::equal_to<typename ValueTraits::value_type>
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef unordered_multiset
|
||||
<value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> unordered_multiset_type;
|
||||
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
||||
|
||||
typename unordered_multiset_type::bucket_type buckets [BucketSize];
|
||||
unordered_multiset_type testset1(buckets, BucketSize, values.begin(), values.end());
|
||||
unordered_multiset_type testset1(values.begin(), values.end(), bucket_traits(buckets, BucketSize));
|
||||
|
||||
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
@ -126,16 +130,16 @@ void test_unordered_multiset<ValueTraits>::test_sort(std::vector<typename ValueT
|
||||
template<class ValueTraits>
|
||||
void test_unordered_multiset<ValueTraits>::test_insert(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type testvalue_t;
|
||||
typedef boost::intrusive::unordered_multiset
|
||||
<ValueTraits
|
||||
,boost::hash<typename ValueTraits::value_type>
|
||||
,std::equal_to<typename ValueTraits::value_type>
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef unordered_multiset
|
||||
<value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> unordered_multiset_type;
|
||||
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
||||
|
||||
typename unordered_multiset_type::bucket_type buckets [BucketSize];
|
||||
unordered_multiset_type testset(buckets, BucketSize);
|
||||
typedef typename unordered_multiset_type::value_type value_type;
|
||||
unordered_multiset_type testset(bucket_traits(buckets, BucketSize));
|
||||
|
||||
testset.insert(&values[0] + 2, &values[0] + 5);
|
||||
|
||||
@ -170,7 +174,7 @@ void test_unordered_multiset<ValueTraits>::test_insert(std::vector<typename Valu
|
||||
|
||||
//Now with a single bucket
|
||||
typename unordered_multiset_type::bucket_type single_bucket[1];
|
||||
unordered_multiset_type testset2(single_bucket, 1);
|
||||
unordered_multiset_type testset2(bucket_traits(single_bucket, 1));
|
||||
testset2.insert(&values[0], &values[0] + values.size());
|
||||
BOOST_TEST (testset2.erase(5) == 1);
|
||||
BOOST_TEST (testset2.erase(2) == 2);
|
||||
@ -184,18 +188,18 @@ void test_unordered_multiset<ValueTraits>::test_insert(std::vector<typename Valu
|
||||
template<class ValueTraits>
|
||||
void test_unordered_multiset<ValueTraits>::test_swap(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type testvalue_t;
|
||||
typedef boost::intrusive::unordered_multiset
|
||||
<ValueTraits
|
||||
,boost::hash<typename ValueTraits::value_type>
|
||||
,std::equal_to<typename ValueTraits::value_type>
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef unordered_multiset
|
||||
<value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> unordered_multiset_type;
|
||||
typename unordered_multiset_type::bucket_type buckets [BucketSize];
|
||||
unordered_multiset_type testset1(buckets, BucketSize, &values[0], &values[0] + 2);
|
||||
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
||||
|
||||
typename unordered_multiset_type::bucket_type buckets [BucketSize];
|
||||
typename unordered_multiset_type::bucket_type buckets2 [BucketSize];
|
||||
unordered_multiset_type testset2(buckets2, BucketSize);
|
||||
unordered_multiset_type testset1(&values[0], &values[0] + 2, bucket_traits(buckets, BucketSize));
|
||||
unordered_multiset_type testset2(bucket_traits(buckets2, BucketSize));
|
||||
|
||||
testset2.insert (&values[0] + 2, &values[0] + 6);
|
||||
testset1.swap (testset2);
|
||||
@ -216,40 +220,41 @@ void test_unordered_multiset<ValueTraits>::test_swap(std::vector<typename ValueT
|
||||
template<class ValueTraits>
|
||||
void test_unordered_multiset<ValueTraits>::test_rehash(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type testvalue_t;
|
||||
typedef boost::intrusive::unordered_multiset
|
||||
<ValueTraits
|
||||
,boost::hash<typename ValueTraits::value_type>
|
||||
,std::equal_to<typename ValueTraits::value_type>
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef unordered_multiset
|
||||
<value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> unordered_multiset_type;
|
||||
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
||||
|
||||
typename unordered_multiset_type::bucket_type buckets1 [BucketSize];
|
||||
unordered_multiset_type testset1(buckets1, BucketSize, &values[0], &values[0] + 6);
|
||||
typename unordered_multiset_type::bucket_type buckets2 [2];
|
||||
typename unordered_multiset_type::bucket_type buckets3 [BucketSize*2];
|
||||
|
||||
unordered_multiset_type testset1(&values[0], &values[0] + 6, bucket_traits(buckets1, BucketSize));
|
||||
BOOST_TEST (testset1.size() == 6);
|
||||
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
|
||||
typename unordered_multiset_type::bucket_type buckets2 [2];
|
||||
testset1.rehash(buckets2, 2);
|
||||
testset1.rehash(bucket_traits(buckets2, 2));
|
||||
BOOST_TEST (testset1.size() == 6);
|
||||
{ int init_values [] = { 4, 2, 2, 5, 3, 1 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
|
||||
typename unordered_multiset_type::bucket_type buckets3 [BucketSize*2];
|
||||
testset1.rehash(buckets3, BucketSize*2);
|
||||
testset1.rehash(bucket_traits(buckets3, BucketSize*2));
|
||||
BOOST_TEST (testset1.size() == 6);
|
||||
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
|
||||
//Now rehash reducing the buckets
|
||||
testset1.rehash(buckets3, 2);
|
||||
testset1.rehash(bucket_traits(buckets3, 2));
|
||||
BOOST_TEST (testset1.size() == 6);
|
||||
{ int init_values [] = { 4, 2, 2, 5, 3, 1 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
|
||||
//Now rehash increasing the buckets
|
||||
testset1.rehash(buckets3, BucketSize*2);
|
||||
testset1.rehash(bucket_traits(buckets3, BucketSize*2));
|
||||
BOOST_TEST (testset1.size() == 6);
|
||||
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
@ -259,19 +264,20 @@ void test_unordered_multiset<ValueTraits>::test_rehash(std::vector<typename Valu
|
||||
template<class ValueTraits>
|
||||
void test_unordered_multiset<ValueTraits>::test_find(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type testvalue_t;
|
||||
typedef boost::intrusive::unordered_multiset
|
||||
<ValueTraits
|
||||
,boost::hash<typename ValueTraits::value_type>
|
||||
,std::equal_to<typename ValueTraits::value_type>
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef unordered_multiset
|
||||
<value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> unordered_multiset_type;
|
||||
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
||||
|
||||
typename unordered_multiset_type::bucket_type buckets[BucketSize];
|
||||
unordered_multiset_type testset(buckets, BucketSize, values.begin(), values.end());
|
||||
unordered_multiset_type testset(values.begin(), values.end(), bucket_traits(buckets, BucketSize));
|
||||
|
||||
typedef typename unordered_multiset_type::iterator iterator;
|
||||
|
||||
testvalue_t cmp_val;
|
||||
value_type cmp_val;
|
||||
cmp_val.value_ = 2;
|
||||
iterator i = testset.find (cmp_val);
|
||||
BOOST_TEST (i->value_ == 2);
|
||||
@ -291,61 +297,62 @@ template<class ValueTraits>
|
||||
void test_unordered_multiset<ValueTraits>
|
||||
::test_clone(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef boost::intrusive::unordered_multiset
|
||||
<ValueTraits
|
||||
,boost::hash<typename ValueTraits::value_type>
|
||||
,std::equal_to<typename ValueTraits::value_type>
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef unordered_multiset
|
||||
<value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> unordered_multiset_type;
|
||||
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
||||
{
|
||||
//Test with equal bucket arrays
|
||||
typename unordered_multiset_type::bucket_type buckets1 [BucketSize];
|
||||
typename unordered_multiset_type::bucket_type buckets2 [BucketSize];
|
||||
unordered_multiset_type testset1 (buckets1, BucketSize, values.begin(), values.end());
|
||||
unordered_multiset_type testset2 (buckets2, BucketSize);
|
||||
unordered_multiset_type testset1 (values.begin(), values.end(), bucket_traits(buckets1, BucketSize));
|
||||
unordered_multiset_type testset2 (bucket_traits(buckets2, BucketSize));
|
||||
|
||||
testset2.clone_from(testset1, test::new_cloner(), test::delete_disposer());
|
||||
testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
|
||||
//Ordering is not guarantee in the cloning so insert data in a set and test
|
||||
std::multiset<typename ValueTraits::value_type>
|
||||
src(testset1.begin(), testset1.end());
|
||||
std::multiset<typename ValueTraits::value_type>
|
||||
dst(testset2.begin(), testset2.end());
|
||||
BOOST_TEST (src == dst);
|
||||
testset2.clear_and_dispose(test::delete_disposer());
|
||||
testset2.clear_and_dispose(test::delete_disposer<value_type>());
|
||||
BOOST_TEST (testset2.empty());
|
||||
}
|
||||
{
|
||||
//Test with bigger source bucket arrays
|
||||
typename unordered_multiset_type::bucket_type buckets1 [BucketSize*2];
|
||||
typename unordered_multiset_type::bucket_type buckets2 [BucketSize];
|
||||
unordered_multiset_type testset1 (buckets1, BucketSize*2, values.begin(), values.end());
|
||||
unordered_multiset_type testset2 (buckets2, BucketSize);
|
||||
unordered_multiset_type testset1 (values.begin(), values.end(), bucket_traits(buckets1, BucketSize*2));
|
||||
unordered_multiset_type testset2 (bucket_traits(buckets2, BucketSize));
|
||||
|
||||
testset2.clone_from(testset1, test::new_cloner(), test::delete_disposer());
|
||||
testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
|
||||
//Ordering is not guarantee in the cloning so insert data in a set and test
|
||||
std::multiset<typename ValueTraits::value_type>
|
||||
src(testset1.begin(), testset1.end());
|
||||
std::multiset<typename ValueTraits::value_type>
|
||||
dst(testset2.begin(), testset2.end());
|
||||
BOOST_TEST (src == dst);
|
||||
testset2.clear_and_dispose(test::delete_disposer());
|
||||
testset2.clear_and_dispose(test::delete_disposer<value_type>());
|
||||
BOOST_TEST (testset2.empty());
|
||||
}
|
||||
{
|
||||
//Test with smaller source bucket arrays
|
||||
typename unordered_multiset_type::bucket_type buckets1 [BucketSize];
|
||||
typename unordered_multiset_type::bucket_type buckets2 [BucketSize*2];
|
||||
unordered_multiset_type testset1 (buckets1, BucketSize, values.begin(), values.end());
|
||||
unordered_multiset_type testset2 (buckets2, BucketSize*2);
|
||||
unordered_multiset_type testset1 (values.begin(), values.end(), bucket_traits(buckets1, BucketSize));
|
||||
unordered_multiset_type testset2 (bucket_traits(buckets2, BucketSize*2));
|
||||
|
||||
testset2.clone_from(testset1, test::new_cloner(), test::delete_disposer());
|
||||
testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
|
||||
//Ordering is not guarantee in the cloning so insert data in a set and test
|
||||
std::multiset<typename ValueTraits::value_type>
|
||||
src(testset1.begin(), testset1.end());
|
||||
std::multiset<typename ValueTraits::value_type>
|
||||
dst(testset2.begin(), testset2.end());
|
||||
BOOST_TEST (src == dst);
|
||||
testset2.clear_and_dispose(test::delete_disposer());
|
||||
testset2.clear_and_dispose(test::delete_disposer<value_type>());
|
||||
BOOST_TEST (testset2.empty());
|
||||
}
|
||||
}
|
||||
@ -356,17 +363,26 @@ class test_main_template
|
||||
public:
|
||||
int operator()()
|
||||
{
|
||||
typedef testvalue<VoidPointer, constant_time_size> testvalue_t;
|
||||
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_unordered_multiset <typename testvalue_t::unordered_set_base_hook_t::template
|
||||
value_traits<testvalue_t> >::test_all(data);
|
||||
test_unordered_multiset < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::unordered_set_base_hook_t
|
||||
>::type
|
||||
>::test_all(data);
|
||||
|
||||
test_unordered_multiset <typename testvalue_t::unordered_set_member_hook_t::template
|
||||
value_traits<testvalue_t, &testvalue_t::unordered_set_node_> >::test_all(data);
|
||||
test_unordered_multiset < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::unordered_set_member_hook_t
|
||||
, &value_type::unordered_set_node_
|
||||
>
|
||||
>::type
|
||||
>::test_all(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -378,87 +394,51 @@ class test_main_template<VoidPointer, false>
|
||||
public:
|
||||
int operator()()
|
||||
{
|
||||
typedef testvalue<VoidPointer, false> testvalue_t;
|
||||
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_unordered_multiset <typename testvalue_t::unordered_set_base_hook_t::template
|
||||
value_traits<testvalue_t> >::test_all(data);
|
||||
test_unordered_multiset < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::unordered_set_base_hook_t
|
||||
>::type
|
||||
>::test_all(data);
|
||||
|
||||
test_unordered_multiset <typename testvalue_t::unordered_set_member_hook_t::template
|
||||
value_traits<testvalue_t, &testvalue_t::unordered_set_node_> >::test_all(data);
|
||||
test_unordered_multiset < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::unordered_set_member_hook_t
|
||||
, &value_type::unordered_set_node_
|
||||
>
|
||||
>::type
|
||||
>::test_all(data);
|
||||
|
||||
test_unordered_multiset <typename testvalue_t::unordered_set_auto_base_hook_t::template
|
||||
value_traits<testvalue_t> >::test_all(data);
|
||||
test_unordered_multiset < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::unordered_set_auto_base_hook_t
|
||||
>::type
|
||||
>::test_all(data);
|
||||
|
||||
test_unordered_multiset <typename testvalue_t::unordered_set_auto_member_hook_t::template
|
||||
value_traits<testvalue_t, &testvalue_t::unordered_set_auto_node_> >::test_all(data);
|
||||
test_unordered_multiset < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::unordered_set_auto_member_hook_t
|
||||
, &value_type::unordered_set_auto_node_
|
||||
>
|
||||
>::type
|
||||
>::test_all(data);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
//Explicit instantiations of non-counted classes
|
||||
template class boost::intrusive::unordered_multiset
|
||||
< unordered_set_base_raw_t
|
||||
, boost::hash<unordered_set_base_raw_t::value_type>
|
||||
, std::equal_to<unordered_set_base_raw_t::value_type>, false>;
|
||||
template class boost::intrusive::unordered_multiset
|
||||
< unordered_set_member_raw_t
|
||||
, boost::hash<unordered_set_member_raw_t::value_type>
|
||||
, std::equal_to<unordered_set_member_raw_t::value_type>, false>;
|
||||
template class boost::intrusive::unordered_multiset
|
||||
< unordered_set_auto_base_raw
|
||||
, boost::hash<unordered_set_auto_base_raw::value_type>
|
||||
, std::equal_to<unordered_set_auto_base_raw::value_type>, false>;
|
||||
template class boost::intrusive::unordered_multiset
|
||||
< unordered_set_auto_member_raw
|
||||
, boost::hash<unordered_set_auto_member_raw::value_type>
|
||||
, std::equal_to<unordered_set_auto_member_raw::value_type>, false>;
|
||||
template class boost::intrusive::unordered_multiset
|
||||
< unordered_set_base_smart
|
||||
, boost::hash<unordered_set_base_smart::value_type>
|
||||
, std::equal_to<unordered_set_base_smart::value_type>, false>;
|
||||
template class boost::intrusive::unordered_multiset
|
||||
< unordered_set_member_smart
|
||||
, boost::hash<unordered_set_member_smart::value_type>
|
||||
, std::equal_to<unordered_set_member_smart::value_type>, false>;
|
||||
template class boost::intrusive::unordered_multiset
|
||||
< unordered_set_auto_base_smart
|
||||
, boost::hash<unordered_set_auto_base_smart::value_type>
|
||||
, std::equal_to<unordered_set_auto_base_smart::value_type>, false>;
|
||||
template class boost::intrusive::unordered_multiset
|
||||
< unordered_set_auto_member_smart
|
||||
, boost::hash<unordered_set_auto_member_smart::value_type>
|
||||
, std::equal_to<unordered_set_auto_member_smart::value_type>, false>;
|
||||
|
||||
//Explicit instantiation of counted classes
|
||||
template class boost::intrusive::unordered_multiset
|
||||
< unordered_set_base_raw_t
|
||||
, boost::hash<unordered_set_base_raw_t::value_type>
|
||||
, std::equal_to<unordered_set_base_raw_t::value_type>, true>;
|
||||
template class boost::intrusive::unordered_multiset
|
||||
< unordered_set_member_raw_t
|
||||
, boost::hash<unordered_set_base_raw_t::value_type>
|
||||
, std::equal_to<unordered_set_member_raw_t::value_type>, true>;
|
||||
template class boost::intrusive::unordered_multiset
|
||||
< unordered_set_base_smart_t
|
||||
, boost::hash<unordered_set_base_smart_t::value_type>
|
||||
, std::equal_to<unordered_set_base_smart_t::value_type>, true>;
|
||||
template class boost::intrusive::unordered_multiset
|
||||
< unordered_set_member_smart_t
|
||||
, boost::hash<unordered_set_member_smart_t::value_type>
|
||||
, std::equal_to<unordered_set_member_smart_t::value_type>, true>;
|
||||
*/
|
||||
|
||||
int main( int, char* [] )
|
||||
{
|
||||
test_main_template<void*, false>()();
|
||||
test_main_template<boost::intrusive::smart_ptr<void>, false>()();
|
||||
test_main_template<smart_ptr<void>, false>()();
|
||||
test_main_template<void*, true>()();
|
||||
test_main_template<boost::intrusive::smart_ptr<void>, true>()();
|
||||
test_main_template<smart_ptr<void>, true>()();
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
|
@ -43,15 +43,16 @@ struct test_unordered_set
|
||||
template<class ValueTraits>
|
||||
void test_unordered_set<ValueTraits>::test_all(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef boost::intrusive::unordered_set
|
||||
<ValueTraits
|
||||
,boost::hash<typename ValueTraits::value_type>
|
||||
,std::equal_to<typename ValueTraits::value_type>
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef unordered_set
|
||||
<value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> unordered_set_type;
|
||||
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
||||
{
|
||||
typename unordered_set_type::bucket_type buckets [BucketSize];
|
||||
unordered_set_type testset(buckets, BucketSize);
|
||||
unordered_set_type testset(bucket_traits(buckets, BucketSize));
|
||||
testset.insert(values.begin(), values.end());
|
||||
test::test_container(testset);
|
||||
testset.clear();
|
||||
@ -77,19 +78,20 @@ void test_unordered_set<ValueTraits>::test_all(std::vector<typename ValueTraits:
|
||||
template<class ValueTraits>
|
||||
void test_unordered_set<ValueTraits>::test_impl()
|
||||
{
|
||||
typedef typename ValueTraits::value_type testvalue_t;
|
||||
std::vector<testvalue_t> values (5);
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef unordered_set
|
||||
<value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> unordered_set_type;
|
||||
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
||||
|
||||
std::vector<value_type> values (5);
|
||||
for (int i = 0; i < 5; ++i)
|
||||
values[i].value_ = i;
|
||||
|
||||
typedef boost::intrusive::unordered_set
|
||||
<ValueTraits
|
||||
,boost::hash<typename ValueTraits::value_type>
|
||||
,std::equal_to<typename ValueTraits::value_type>
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
> unordered_set_type;
|
||||
typename unordered_set_type::bucket_type buckets [BucketSize];
|
||||
unordered_set_type testset(buckets, BucketSize);
|
||||
unordered_set_type testset(bucket_traits(buckets, BucketSize));
|
||||
for (int i = 0; i < 5; ++i)
|
||||
testset.insert (values[i]);
|
||||
|
||||
@ -104,15 +106,16 @@ void test_unordered_set<ValueTraits>::test_impl()
|
||||
template<class ValueTraits>
|
||||
void test_unordered_set<ValueTraits>::test_sort(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type testvalue_t;
|
||||
typedef boost::intrusive::unordered_set
|
||||
<ValueTraits
|
||||
,boost::hash<typename ValueTraits::value_type>
|
||||
,std::equal_to<typename ValueTraits::value_type>
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef unordered_set
|
||||
<value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> unordered_set_type;
|
||||
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
||||
|
||||
typename unordered_set_type::bucket_type buckets [BucketSize];
|
||||
unordered_set_type testset1(buckets, BucketSize, values.begin(), values.end());
|
||||
unordered_set_type testset1(values.begin(), values.end(), bucket_traits(buckets, BucketSize));
|
||||
|
||||
BOOST_TEST (5 == std::distance(testset1.begin(), testset1.end()));
|
||||
{ int init_values [] = { 1, 2, 3, 4, 5 };
|
||||
@ -126,15 +129,16 @@ void test_unordered_set<ValueTraits>::test_sort(std::vector<typename ValueTraits
|
||||
template<class ValueTraits>
|
||||
void test_unordered_set<ValueTraits>::test_insert(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type testvalue_t;
|
||||
typedef boost::intrusive::unordered_set
|
||||
<ValueTraits
|
||||
,boost::hash<typename ValueTraits::value_type>
|
||||
,std::equal_to<typename ValueTraits::value_type>
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef unordered_set
|
||||
<value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> unordered_set_type;
|
||||
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
||||
|
||||
typename unordered_set_type::bucket_type buckets [BucketSize];
|
||||
unordered_set_type testset(buckets, BucketSize);
|
||||
unordered_set_type testset(bucket_traits(buckets, BucketSize));
|
||||
testset.insert(&values[0] + 2, &values[0] + 5);
|
||||
|
||||
const unordered_set_type& const_testset = testset;
|
||||
@ -160,19 +164,18 @@ void test_unordered_set<ValueTraits>::test_insert(std::vector<typename ValueTrai
|
||||
template<class ValueTraits>
|
||||
void test_unordered_set<ValueTraits>::test_swap(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type testvalue_t;
|
||||
typedef boost::intrusive::unordered_set
|
||||
<ValueTraits
|
||||
,boost::hash<typename ValueTraits::value_type>
|
||||
,std::equal_to<typename ValueTraits::value_type>
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef unordered_set
|
||||
<value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> unordered_set_type;
|
||||
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
||||
|
||||
typename unordered_set_type::bucket_type buckets1 [BucketSize];
|
||||
unordered_set_type testset1(buckets1, BucketSize, &values[0], &values[0] + 2);
|
||||
|
||||
typename unordered_set_type::bucket_type buckets2 [BucketSize];
|
||||
unordered_set_type testset2(buckets2, BucketSize);
|
||||
unordered_set_type testset1(&values[0], &values[0] + 2, bucket_traits(buckets1, BucketSize));
|
||||
unordered_set_type testset2(bucket_traits(buckets2, BucketSize));
|
||||
|
||||
testset2.insert (&values[0] + 2, &values[0] + 6);
|
||||
testset1.swap (testset2);
|
||||
@ -192,40 +195,41 @@ void test_unordered_set<ValueTraits>::test_swap(std::vector<typename ValueTraits
|
||||
template<class ValueTraits>
|
||||
void test_unordered_set<ValueTraits>::test_rehash(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type testvalue_t;
|
||||
typedef boost::intrusive::unordered_set
|
||||
<ValueTraits
|
||||
,boost::hash<typename ValueTraits::value_type>
|
||||
,std::equal_to<typename ValueTraits::value_type>
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef unordered_set
|
||||
<value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> unordered_set_type;
|
||||
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
||||
|
||||
typename unordered_set_type::bucket_type buckets1 [BucketSize];
|
||||
unordered_set_type testset1(buckets1, BucketSize, &values[0], &values[0] + 6);
|
||||
typename unordered_set_type::bucket_type buckets2 [2];
|
||||
typename unordered_set_type::bucket_type buckets3 [BucketSize*2];
|
||||
|
||||
unordered_set_type testset1(&values[0], &values[0] + 6, bucket_traits(buckets1, BucketSize));
|
||||
BOOST_TEST (testset1.size() == 5);
|
||||
{ int init_values [] = { 1, 2, 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
|
||||
typename unordered_set_type::bucket_type buckets2 [2];
|
||||
testset1.rehash(buckets2, 2);
|
||||
testset1.rehash(bucket_traits(buckets2, 2));
|
||||
BOOST_TEST (testset1.size() == 5);
|
||||
{ int init_values [] = { 4, 2, 5, 3, 1 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
|
||||
typename unordered_set_type::bucket_type buckets3 [BucketSize*2];
|
||||
testset1.rehash(buckets3, BucketSize*2);
|
||||
testset1.rehash(bucket_traits(buckets3, BucketSize*2));
|
||||
BOOST_TEST (testset1.size() == 5);
|
||||
{ int init_values [] = { 1, 2, 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
|
||||
//Now rehash reducing the buckets
|
||||
testset1.rehash(buckets3, 2);
|
||||
testset1.rehash(bucket_traits(buckets3, 2));
|
||||
BOOST_TEST (testset1.size() == 5);
|
||||
{ int init_values [] = { 4, 2, 5, 3, 1 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
|
||||
//Now rehash increasing the buckets
|
||||
testset1.rehash(buckets3, BucketSize*2);
|
||||
testset1.rehash(bucket_traits(buckets3, BucketSize*2));
|
||||
BOOST_TEST (testset1.size() == 5);
|
||||
{ int init_values [] = { 1, 2, 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
@ -236,18 +240,19 @@ void test_unordered_set<ValueTraits>::test_rehash(std::vector<typename ValueTrai
|
||||
template<class ValueTraits>
|
||||
void test_unordered_set<ValueTraits>::test_find(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type testvalue_t;
|
||||
typedef boost::intrusive::unordered_set
|
||||
<ValueTraits
|
||||
,boost::hash<typename ValueTraits::value_type>
|
||||
,std::equal_to<typename ValueTraits::value_type>
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef unordered_set
|
||||
<value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> unordered_set_type;
|
||||
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
||||
|
||||
typename unordered_set_type::bucket_type buckets [BucketSize];
|
||||
unordered_set_type testset (buckets, BucketSize, values.begin(), values.end());
|
||||
unordered_set_type testset (values.begin(), values.end(), bucket_traits(buckets, BucketSize));
|
||||
typedef typename unordered_set_type::iterator iterator;
|
||||
|
||||
testvalue_t cmp_val;
|
||||
value_type cmp_val;
|
||||
cmp_val.value_ = 2;
|
||||
iterator i = testset.find (cmp_val);
|
||||
BOOST_TEST (i->value_ == 2);
|
||||
@ -266,61 +271,62 @@ template<class ValueTraits>
|
||||
void test_unordered_set<ValueTraits>
|
||||
::test_clone(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef boost::intrusive::unordered_set
|
||||
<ValueTraits
|
||||
,boost::hash<typename ValueTraits::value_type>
|
||||
,std::equal_to<typename ValueTraits::value_type>
|
||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef unordered_set
|
||||
<value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> unordered_set_type;
|
||||
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
||||
{
|
||||
//Test with equal bucket arrays
|
||||
typename unordered_set_type::bucket_type buckets1 [BucketSize];
|
||||
typename unordered_set_type::bucket_type buckets2 [BucketSize];
|
||||
unordered_set_type testset1 (buckets1, BucketSize, values.begin(), values.end());
|
||||
unordered_set_type testset2 (buckets2, BucketSize);
|
||||
unordered_set_type testset1 (values.begin(), values.end(), bucket_traits(buckets1, BucketSize));
|
||||
unordered_set_type testset2 (bucket_traits(buckets2, BucketSize));
|
||||
|
||||
testset2.clone_from(testset1, test::new_cloner(), test::delete_disposer());
|
||||
testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
|
||||
//Ordering is not guarantee in the cloning so insert data in a set and test
|
||||
std::set<typename ValueTraits::value_type>
|
||||
src(testset1.begin(), testset1.end());
|
||||
std::set<typename ValueTraits::value_type>
|
||||
dst(testset2.begin(), testset2.end());
|
||||
BOOST_TEST (src == dst );
|
||||
testset2.clear_and_dispose(test::delete_disposer());
|
||||
testset2.clear_and_dispose(test::delete_disposer<value_type>());
|
||||
BOOST_TEST (testset2.empty());
|
||||
}
|
||||
{
|
||||
//Test with bigger source bucket arrays
|
||||
typename unordered_set_type::bucket_type buckets1 [BucketSize*2];
|
||||
typename unordered_set_type::bucket_type buckets2 [BucketSize];
|
||||
unordered_set_type testset1 (buckets1, BucketSize*2, values.begin(), values.end());
|
||||
unordered_set_type testset2 (buckets2, BucketSize);
|
||||
unordered_set_type testset1 (values.begin(), values.end(), bucket_traits(buckets1, BucketSize*2));
|
||||
unordered_set_type testset2 (bucket_traits(buckets2, BucketSize));
|
||||
|
||||
testset2.clone_from(testset1, test::new_cloner(), test::delete_disposer());
|
||||
testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
|
||||
//Ordering is not guarantee in the cloning so insert data in a set and test
|
||||
std::set<typename ValueTraits::value_type>
|
||||
src(testset1.begin(), testset1.end());
|
||||
std::set<typename ValueTraits::value_type>
|
||||
dst(testset2.begin(), testset2.end());
|
||||
BOOST_TEST (src == dst );
|
||||
testset2.clear_and_dispose(test::delete_disposer());
|
||||
testset2.clear_and_dispose(test::delete_disposer<value_type>());
|
||||
BOOST_TEST (testset2.empty());
|
||||
}
|
||||
{
|
||||
//Test with smaller source bucket arrays
|
||||
typename unordered_set_type::bucket_type buckets1 [BucketSize];
|
||||
typename unordered_set_type::bucket_type buckets2 [BucketSize*2];
|
||||
unordered_set_type testset1 (buckets1, BucketSize, values.begin(), values.end());
|
||||
unordered_set_type testset2 (buckets2, BucketSize*2);
|
||||
unordered_set_type testset1 (values.begin(), values.end(), bucket_traits(buckets1, BucketSize));
|
||||
unordered_set_type testset2 (bucket_traits(buckets2, BucketSize*2));
|
||||
|
||||
testset2.clone_from(testset1, test::new_cloner(), test::delete_disposer());
|
||||
testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
|
||||
//Ordering is not guarantee in the cloning so insert data in a set and test
|
||||
std::set<typename ValueTraits::value_type>
|
||||
src(testset1.begin(), testset1.end());
|
||||
std::set<typename ValueTraits::value_type>
|
||||
dst(testset2.begin(), testset2.end());
|
||||
BOOST_TEST (src == dst );
|
||||
testset2.clear_and_dispose(test::delete_disposer());
|
||||
testset2.clear_and_dispose(test::delete_disposer<value_type>());
|
||||
BOOST_TEST (testset2.empty());
|
||||
}
|
||||
}
|
||||
@ -331,17 +337,25 @@ class test_main_template
|
||||
public:
|
||||
int operator()()
|
||||
{
|
||||
typedef testvalue<VoidPointer, constant_time_size> testvalue_t;
|
||||
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_unordered_set <typename testvalue_t::unordered_set_base_hook_t::template
|
||||
value_traits<testvalue_t> >::test_all(data);
|
||||
|
||||
test_unordered_set <typename testvalue_t::unordered_set_member_hook_t::template
|
||||
value_traits<testvalue_t, &testvalue_t::unordered_set_node_> >::test_all(data);
|
||||
test_unordered_set < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::unordered_set_base_hook_t
|
||||
>::type
|
||||
>::test_all(data);
|
||||
test_unordered_set < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::unordered_set_member_hook_t
|
||||
, &value_type::unordered_set_node_
|
||||
>
|
||||
>::type
|
||||
>::test_all(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -353,84 +367,51 @@ class test_main_template<VoidPointer, false>
|
||||
public:
|
||||
int operator()()
|
||||
{
|
||||
typedef testvalue<VoidPointer, false> testvalue_t;
|
||||
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_unordered_set <typename testvalue_t::unordered_set_base_hook_t::template
|
||||
value_traits<testvalue_t> >::test_all(data);
|
||||
test_unordered_set < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::unordered_set_base_hook_t
|
||||
>::type
|
||||
>::test_all(data);
|
||||
|
||||
test_unordered_set <typename testvalue_t::unordered_set_member_hook_t::template
|
||||
value_traits<testvalue_t, &testvalue_t::unordered_set_node_> >::test_all(data);
|
||||
test_unordered_set < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::unordered_set_member_hook_t
|
||||
, &value_type::unordered_set_node_
|
||||
>
|
||||
>::type
|
||||
>::test_all(data);
|
||||
|
||||
test_unordered_set <typename testvalue_t::unordered_set_auto_base_hook_t::template
|
||||
value_traits<testvalue_t> >::test_all(data);
|
||||
test_unordered_set < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::unordered_set_auto_base_hook_t
|
||||
>::type
|
||||
>::test_all(data);
|
||||
|
||||
test_unordered_set <typename testvalue_t::unordered_set_auto_member_hook_t::template
|
||||
value_traits<testvalue_t, &testvalue_t::unordered_set_auto_node_> >::test_all(data);
|
||||
test_unordered_set < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::unordered_set_auto_member_hook_t
|
||||
, &value_type::unordered_set_auto_node_
|
||||
>
|
||||
>::type
|
||||
>::test_all(data);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
/*
|
||||
template class boost::intrusive::unordered_set
|
||||
< unordered_set_base_raw_t
|
||||
, boost::hash<unordered_set_base_raw_t::value_type>
|
||||
, std::equal_to<unordered_set_base_raw_t::value_type>, false>;
|
||||
template class boost::intrusive::unordered_set
|
||||
< unordered_set_member_raw_t
|
||||
, boost::hash<unordered_set_member_raw_t::value_type>
|
||||
, std::equal_to<unordered_set_member_raw_t::value_type>, false>;
|
||||
template class boost::intrusive::unordered_set
|
||||
< unordered_set_auto_base_raw
|
||||
, boost::hash<unordered_set_auto_base_raw::value_type>
|
||||
, std::equal_to<unordered_set_auto_base_raw::value_type>, false>;
|
||||
template class boost::intrusive::unordered_set
|
||||
< unordered_set_auto_member_raw
|
||||
, boost::hash<unordered_set_auto_member_raw::value_type>
|
||||
, std::equal_to<unordered_set_auto_member_raw::value_type>, false>;
|
||||
template class boost::intrusive::unordered_set
|
||||
< unordered_set_base_smart
|
||||
, boost::hash<unordered_set_base_smart::value_type>
|
||||
, std::equal_to<unordered_set_base_smart::value_type>, false>;
|
||||
template class boost::intrusive::unordered_set
|
||||
< unordered_set_member_smart
|
||||
, boost::hash<unordered_set_member_smart::value_type>
|
||||
, std::equal_to<unordered_set_member_smart::value_type>, false>;
|
||||
template class boost::intrusive::unordered_set
|
||||
< unordered_set_auto_base_smart
|
||||
, boost::hash<unordered_set_auto_base_smart::value_type>
|
||||
, std::equal_to<unordered_set_auto_base_smart::value_type>, false>;
|
||||
template class boost::intrusive::unordered_set
|
||||
< unordered_set_auto_member_smart
|
||||
, boost::hash<unordered_set_auto_member_smart::value_type>
|
||||
, std::equal_to<unordered_set_auto_member_smart::value_type>, false>;
|
||||
|
||||
//Explicit instantiation of counted classes
|
||||
template class boost::intrusive::unordered_set
|
||||
< unordered_set_base_raw_t
|
||||
, boost::hash<unordered_set_base_raw_t::value_type>
|
||||
, std::equal_to<unordered_set_base_raw_t::value_type>, true>;
|
||||
template class boost::intrusive::unordered_set
|
||||
< unordered_set_member_raw_t
|
||||
, boost::hash<unordered_set_base_raw_t::value_type>
|
||||
, std::equal_to<unordered_set_member_raw_t::value_type>, true>;
|
||||
template class boost::intrusive::unordered_set
|
||||
< unordered_set_base_smart_t
|
||||
, boost::hash<unordered_set_base_smart_t::value_type>
|
||||
, std::equal_to<unordered_set_base_smart_t::value_type>, true>;
|
||||
template class boost::intrusive::unordered_set
|
||||
< unordered_set_member_smart_t
|
||||
, boost::hash<unordered_set_member_smart_t::value_type>
|
||||
, std::equal_to<unordered_set_member_smart_t::value_type>, true>;
|
||||
*/
|
||||
int main( int, char* [] )
|
||||
{
|
||||
test_main_template<void*, false>()();
|
||||
test_main_template<boost::intrusive::smart_ptr<void>, false>()();
|
||||
test_main_template<smart_ptr<void>, false>()();
|
||||
test_main_template<void*, true>()();
|
||||
test_main_template<boost::intrusive::smart_ptr<void>, true>()();
|
||||
test_main_template<smart_ptr<void>, true>()();
|
||||
return boost::report_errors();
|
||||
}
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
|
85
test/virtual_base_test.cpp
Normal file
85
test/virtual_base_test.cpp
Normal 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.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#include <boost/intrusive/list.hpp>
|
||||
#include <boost/intrusive/slist.hpp>
|
||||
#include <boost/intrusive/set.hpp>
|
||||
#include <boost/intrusive/unordered_set.hpp>
|
||||
#include <vector>
|
||||
|
||||
using namespace boost::intrusive;
|
||||
|
||||
struct VirtualBase
|
||||
{
|
||||
virtual ~VirtualBase(){}
|
||||
};
|
||||
|
||||
struct VirtualBase2
|
||||
{
|
||||
virtual ~VirtualBase2(){}
|
||||
};
|
||||
|
||||
struct VirtualBase3
|
||||
{
|
||||
};
|
||||
|
||||
class NonVirtualBase
|
||||
: public virtual VirtualBase
|
||||
, public virtual VirtualBase2
|
||||
{
|
||||
public:
|
||||
int dummy[10];
|
||||
};
|
||||
|
||||
class MyClass
|
||||
: public NonVirtualBase
|
||||
, public virtual VirtualBase3
|
||||
{
|
||||
int int_;
|
||||
public:
|
||||
list_member_hook<> list_hook_;
|
||||
MyClass(int i = 0)
|
||||
: int_(i)
|
||||
{}
|
||||
};
|
||||
|
||||
//Define a list that will store MyClass using the public base hook
|
||||
typedef member_hook< MyClass, list_member_hook<>, &MyClass::list_hook_ > MemberHook;
|
||||
typedef list<MyClass, MemberHook> List;
|
||||
|
||||
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));
|
||||
|
||||
List my_list;
|
||||
|
||||
//Now insert them in the reverse order
|
||||
//in the base hook intrusive list
|
||||
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it)
|
||||
my_list.push_front(*it);
|
||||
|
||||
//Now test lists
|
||||
{
|
||||
List::const_iterator list_it(my_list.cbegin());
|
||||
VectRit vect_it(values.rbegin()), vect_itend(values.rend());
|
||||
|
||||
//Test the objects inserted in the base hook list
|
||||
for(; vect_it != vect_itend; ++vect_it, ++list_it)
|
||||
if(&*list_it != &*vect_it) return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user