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
|
//[doc_advanced_value_traits_code
|
||||||
#include <boost/intrusive/linking_policy.hpp>
|
#include <boost/intrusive/link_mode.hpp>
|
||||||
#include <boost/intrusive/list.hpp>
|
#include <boost/intrusive/list.hpp>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ struct simple_node_traits
|
|||||||
|
|
||||||
//A templatized value traits for value_1 and value_2
|
//A templatized value traits for value_1 and value_2
|
||||||
template<class ValueType>
|
template<class ValueType>
|
||||||
struct value_traits
|
struct simple_value_traits
|
||||||
{
|
{
|
||||||
typedef simple_node_traits node_traits;
|
typedef simple_node_traits node_traits;
|
||||||
typedef node_traits::node_ptr node_ptr;
|
typedef node_traits::node_ptr node_ptr;
|
||||||
@ -54,7 +54,7 @@ struct value_traits
|
|||||||
typedef ValueType value_type;
|
typedef ValueType value_type;
|
||||||
typedef ValueType * pointer;
|
typedef ValueType * pointer;
|
||||||
typedef const ValueType * const_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 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 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 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
|
//[doc_advanced_value_traits_containers
|
||||||
//Now define two intrusive lists. Both lists will use the same algorithms:
|
//Now define two intrusive lists. Both lists will use the same algorithms:
|
||||||
// circular_list_algorithms<simple_node_traits>
|
// 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
|
//[doc_advanced_value_traits_test
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
// See http://www.boost.org/libs/intrusive for documentation.
|
// 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/list.hpp>
|
||||||
#include <boost/intrusive/member_value_traits.hpp>
|
#include <boost/intrusive/member_value_traits.hpp>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -57,8 +57,8 @@ typedef member_value_traits
|
|||||||
|
|
||||||
//Now define two intrusive lists. Both lists will use the same algorithms:
|
//Now define two intrusive lists. Both lists will use the same algorithms:
|
||||||
// circular_list_algorithms<simple_node_traits>
|
// circular_list_algorithms<simple_node_traits>
|
||||||
typedef boost::intrusive::list <ValueTraits1> Value1List;
|
typedef list <value_1, value_traits<ValueTraits1> > Value1List;
|
||||||
typedef boost::intrusive::list <ValueTraits2> Value2List;
|
typedef list <value_2, value_traits<ValueTraits2> > Value2List;
|
||||||
//]
|
//]
|
||||||
|
|
||||||
//[doc_advanced_value_traits2_test
|
//[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
|
// A set and unordered_set that store Expensive objects
|
||||||
typedef set<set_base_hook<>::value_traits<Expensive> > Set;
|
typedef set<Expensive> Set;
|
||||||
typedef unordered_set<unordered_set_base_hook<>::
|
typedef unordered_set<Expensive> UnorderedSet;
|
||||||
value_traits<Expensive> > UnorderedSet;
|
|
||||||
|
|
||||||
// Search functions
|
// 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));
|
Set::iterator it = set_object.find(Expensive(key));
|
||||||
if( it == set.end() ) return 0;
|
if( it == set_object.end() ) return 0;
|
||||||
return &*it;
|
return &*it;
|
||||||
}
|
}
|
||||||
|
|
||||||
Expensive *get_from_unordered_set
|
Expensive *get_from_uset(const char* key, UnorderedSet &uset_object)
|
||||||
(const char* key, UnorderedSet &unordered_set)
|
|
||||||
{
|
{
|
||||||
UnorderedSet::iterator it =
|
UnorderedSet::iterator it = uset_object.find(Expensive (key));
|
||||||
unordered_set.find(Expensive (key));
|
if( it == uset_object.end() ) return 0;
|
||||||
if( it == unordered_set.end() ) return 0;
|
|
||||||
return &*it;
|
return &*it;
|
||||||
}
|
}
|
||||||
//]
|
//]
|
||||||
@ -94,38 +91,35 @@ struct StrExpEqual
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Optimized search functions
|
// 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());
|
Set::iterator it = set_object.find(key, StrExpComp());
|
||||||
if( it == set.end() ) return 0;
|
if( it == set_object.end() ) return 0;
|
||||||
return &*it;
|
return &*it;
|
||||||
}
|
}
|
||||||
|
|
||||||
Expensive *get_from_unordered_set_optimized
|
Expensive *get_from_uset_optimized(const char* key, UnorderedSet &uset_object)
|
||||||
(const char* key, UnorderedSet &unordered_set)
|
|
||||||
{
|
{
|
||||||
UnorderedSet::iterator it =
|
UnorderedSet::iterator it = uset_object.find(key, StrHasher(), StrExpEqual());
|
||||||
unordered_set.find(key, StrHasher(), StrExpEqual());
|
if( it == uset_object.end() ) return 0;
|
||||||
if( it == unordered_set.end() ) return 0;
|
|
||||||
return &*it;
|
return &*it;
|
||||||
}
|
}
|
||||||
//]
|
//]
|
||||||
|
|
||||||
//[doc_assoc_optimized_code_normal_insert
|
//[doc_assoc_optimized_code_normal_insert
|
||||||
// Insertion functions
|
// 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);
|
Expensive *pobject = new Expensive(key);
|
||||||
bool success = set.insert(*pobject).second;
|
bool success = set_object.insert(*pobject).second;
|
||||||
if(!success) delete pobject;
|
if(!success) delete pobject;
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool insert_to_unordered_set
|
bool insert_to_uset(const char* key, UnorderedSet &uset_object)
|
||||||
(const char* key, UnorderedSet &unordered_set)
|
|
||||||
{
|
{
|
||||||
Expensive *pobject = new Expensive(key);
|
Expensive *pobject = new Expensive(key);
|
||||||
bool success = unordered_set.insert(*pobject).second;
|
bool success = uset_object.insert(*pobject).second;
|
||||||
if(!success) delete pobject;
|
if(!success) delete pobject;
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
@ -133,24 +127,20 @@ bool insert_to_unordered_set
|
|||||||
|
|
||||||
//[doc_assoc_optimized_code_optimized_insert
|
//[doc_assoc_optimized_code_optimized_insert
|
||||||
// Optimized insertion functions
|
// 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;
|
Set::insert_commit_data insert_data;
|
||||||
bool success = set.insert_check
|
bool success = set_object.insert_check(key, StrExpComp(), insert_data).second;
|
||||||
(key, StrExpComp(), insert_data).second;
|
if(success) set_object.insert_commit(*new Expensive(key), insert_data);
|
||||||
if(success)
|
|
||||||
set.insert_commit(*new Expensive(key), insert_data);
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool insert_to_unordered_set_optimized
|
bool insert_to_uset_optimized(const char* key, UnorderedSet &uset_object)
|
||||||
(const char* key, UnorderedSet &unordered_set)
|
|
||||||
{
|
{
|
||||||
UnorderedSet::insert_commit_data insert_data;
|
UnorderedSet::insert_commit_data insert_data;
|
||||||
bool success = unordered_set.insert_check
|
bool success = uset_object.insert_check
|
||||||
(key, StrHasher(), StrExpEqual(), insert_data).second;
|
(key, StrHasher(), StrExpEqual(), insert_data).second;
|
||||||
if(success)
|
if(success) uset_object.insert_commit(*new Expensive(key), insert_data);
|
||||||
unordered_set.insert_commit(*new Expensive(key), insert_data);
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
//]
|
//]
|
||||||
@ -159,7 +149,7 @@ int main()
|
|||||||
{
|
{
|
||||||
Set set;
|
Set set;
|
||||||
UnorderedSet::bucket_type buckets[10];
|
UnorderedSet::bucket_type buckets[10];
|
||||||
UnorderedSet unordered_set(buckets, 10);
|
UnorderedSet unordered_set(UnorderedSet::bucket_traits(buckets, 10));
|
||||||
|
|
||||||
const char * const expensive_key
|
const char * const expensive_key
|
||||||
= "A long string that avoids small string optimization";
|
= "A long string that avoids small string optimization";
|
||||||
@ -170,7 +160,7 @@ int main()
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(get_from_unordered_set(expensive_key, unordered_set)){
|
if(get_from_uset(expensive_key, unordered_set)){
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,7 +168,7 @@ int main()
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(get_from_unordered_set_optimized(expensive_key, unordered_set)){
|
if(get_from_uset_optimized(expensive_key, unordered_set)){
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,7 +179,7 @@ int main()
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!get_from_unordered_set(expensive_key, unordered_set)){
|
if(!get_from_uset(expensive_key, unordered_set)){
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,7 +187,7 @@ int main()
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!get_from_unordered_set_optimized(expensive_key, unordered_set)){
|
if(!get_from_uset_optimized(expensive_key, unordered_set)){
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,7 +198,7 @@ int main()
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!insert_to_unordered_set(expensive_key, unordered_set)){
|
if(!insert_to_uset(expensive_key, unordered_set)){
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,7 +218,7 @@ int main()
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!insert_to_unordered_set_optimized(expensive_key, unordered_set)){
|
if(!insert_to_uset_optimized(expensive_key, unordered_set)){
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,7 +241,7 @@ int main()
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(insert_to_unordered_set(expensive_key, unordered_set)){
|
if(insert_to_uset(expensive_key, unordered_set)){
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,7 +249,7 @@ int main()
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(insert_to_unordered_set_optimized(expensive_key, unordered_set)){
|
if(insert_to_uset_optimized(expensive_key, unordered_set)){
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,39 +15,38 @@
|
|||||||
|
|
||||||
using namespace boost::intrusive;
|
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
|
//This hook removes the node in the destructor
|
||||||
{
|
{
|
||||||
int int_;
|
int int_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MyClass(int i = 0) : int_(i) {}
|
MyClass(int i = 0) : int_(i) {}
|
||||||
void unlink() { list_base_hook<tag, auto_unlink>::unlink(); }
|
void unlink() { auto_unlink_hook::unlink(); }
|
||||||
bool is_linked() { return list_base_hook<tag, auto_unlink>::is_linked(); }
|
bool is_linked() { return auto_unlink_hook::is_linked(); }
|
||||||
int get() const { return int_; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//Define a list that will store MyClass
|
//Define a list that will store values using the base hook
|
||||||
//using the public base hook
|
|
||||||
//The list can't have constant-time size!
|
//The list can't have constant-time size!
|
||||||
typedef list< list_base_hook<tag, auto_unlink>::
|
typedef list< MyClass, constant_time_size<false> > List;
|
||||||
value_traits<MyClass>, false > List;
|
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
//Create the list
|
//Create the list
|
||||||
List list;
|
List l;
|
||||||
{
|
{
|
||||||
//Create myclass and check it's linked
|
//Create myclass and check it's linked
|
||||||
MyClass myclass;
|
MyClass myclass;
|
||||||
assert(myclass.is_linked() == false);
|
assert(myclass.is_linked() == false);
|
||||||
|
|
||||||
//Insert the object
|
//Insert the object
|
||||||
list.push_back(myclass);
|
l.push_back(myclass);
|
||||||
|
|
||||||
//Check that we have inserted the object
|
//Check that we have inserted the object
|
||||||
assert(list.empty() == false);
|
assert(l.empty() == false);
|
||||||
assert(&list.front() == &myclass);
|
assert(&l.front() == &myclass);
|
||||||
assert(myclass.is_linked() == true);
|
assert(myclass.is_linked() == true);
|
||||||
|
|
||||||
//Now myclass' destructor will unlink it
|
//Now myclass' destructor will unlink it
|
||||||
@ -55,7 +54,7 @@ int main()
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Check auto-unlink has been executed
|
//Check auto-unlink has been executed
|
||||||
assert(list.empty() == true);
|
assert(l.empty() == true);
|
||||||
|
|
||||||
{
|
{
|
||||||
//Now test the unlink() function
|
//Now test the unlink() function
|
||||||
@ -65,18 +64,18 @@ int main()
|
|||||||
assert(myclass.is_linked() == false);
|
assert(myclass.is_linked() == false);
|
||||||
|
|
||||||
//Insert the object
|
//Insert the object
|
||||||
list.push_back(myclass);
|
l.push_back(myclass);
|
||||||
|
|
||||||
//Check that we have inserted the object
|
//Check that we have inserted the object
|
||||||
assert(list.empty() == false);
|
assert(l.empty() == false);
|
||||||
assert(&list.front() == &myclass);
|
assert(&l.front() == &myclass);
|
||||||
assert(myclass.is_linked() == true);
|
assert(myclass.is_linked() == true);
|
||||||
|
|
||||||
//Now unlink the node
|
//Now unlink the node
|
||||||
myclass.unlink();
|
myclass.unlink();
|
||||||
|
|
||||||
//Check auto-unlink has been executed
|
//Check auto-unlink has been executed
|
||||||
assert(list.empty() == true);
|
assert(l.empty() == true);
|
||||||
}
|
}
|
||||||
return 0;
|
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 <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
using namespace boost::intrusive;
|
||||||
|
|
||||||
//A class that can be inserted in an intrusive list
|
//A class that can be inserted in an intrusive list
|
||||||
class my_class
|
class my_class : public list_base_hook<>
|
||||||
: public boost::intrusive::list_base_hook<>
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
friend bool operator==(const my_class &a, const my_class &b)
|
friend bool operator==(const my_class &a, const my_class &b)
|
||||||
@ -28,20 +29,18 @@ class my_class
|
|||||||
};
|
};
|
||||||
|
|
||||||
//Definition of the intrusive list
|
//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
|
//Cloner object function
|
||||||
class new_cloner
|
struct new_cloner
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
my_class *operator()(const my_class &clone_this)
|
my_class *operator()(const my_class &clone_this)
|
||||||
{ return new my_class(clone_this); }
|
{ return new my_class(clone_this); }
|
||||||
};
|
};
|
||||||
|
|
||||||
//The disposer object function
|
//The disposer object function
|
||||||
class delete_disposer
|
struct delete_disposer
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
void operator()(my_class *delete_this)
|
void operator()(my_class *delete_this)
|
||||||
{ delete delete_this; }
|
{ delete delete_this; }
|
||||||
};
|
};
|
||||||
@ -54,9 +53,8 @@ int main()
|
|||||||
//Fill all the nodes and insert them in the list
|
//Fill all the nodes and insert them in the list
|
||||||
my_class_list list;
|
my_class_list list;
|
||||||
|
|
||||||
for(int i = 0; i < MaxElem; ++i){
|
for(int i = 0; i < MaxElem; ++i) nodes[i].int_ = i;
|
||||||
nodes[i].int_ = i;
|
|
||||||
}
|
|
||||||
list.insert(list.end(), nodes.begin(), nodes.end());
|
list.insert(list.end(), nodes.begin(), nodes.end());
|
||||||
|
|
||||||
//Now clone "list" using "new" and "delete" object functions
|
//Now clone "list" using "new" and "delete" object functions
|
||||||
@ -64,12 +62,10 @@ int main()
|
|||||||
cloned_list.clone_from(list, new_cloner(), delete_disposer());
|
cloned_list.clone_from(list, new_cloner(), delete_disposer());
|
||||||
|
|
||||||
//Test that both are equal
|
//Test that both are equal
|
||||||
if(cloned_list != list){
|
if(cloned_list != list)
|
||||||
std::cout << "Both lists are different" << std::endl;
|
std::cout << "Both lists are different" << std::endl;
|
||||||
}
|
else
|
||||||
else{
|
|
||||||
std::cout << "Both lists are equal" << std::endl;
|
std::cout << "Both lists are equal" << std::endl;
|
||||||
}
|
|
||||||
|
|
||||||
//Don't forget to free the memory from the second list
|
//Don't forget to free the memory from the second list
|
||||||
cloned_list.clear_and_dispose(delete_disposer());
|
cloned_list.clear_and_dispose(delete_disposer());
|
||||||
|
@ -12,9 +12,10 @@
|
|||||||
//[doc_entity_code
|
//[doc_entity_code
|
||||||
#include <boost/intrusive/list.hpp>
|
#include <boost/intrusive/list.hpp>
|
||||||
|
|
||||||
|
using namespace boost::intrusive;
|
||||||
|
|
||||||
//A class that can be inserted in an intrusive list
|
//A class that can be inserted in an intrusive list
|
||||||
class entity
|
class entity : public list_base_hook<>
|
||||||
: public boost::intrusive::list_base_hook<>
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~entity();
|
virtual ~entity();
|
||||||
@ -26,25 +27,25 @@ class some_entity : public entity
|
|||||||
{/**/};
|
{/**/};
|
||||||
|
|
||||||
//Definition of the intrusive list
|
//Definition of the intrusive list
|
||||||
typedef boost::intrusive::list< entity::value_traits<entity> > entity_list;
|
typedef list<entity> entity_list;
|
||||||
|
|
||||||
//A global 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()
|
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()
|
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 ()
|
void clear_list ()
|
||||||
{
|
{
|
||||||
// entity's destructor removes itself from the list implicitly
|
// entity's destructor removes itself from the global list implicitly
|
||||||
while (!list.empty())
|
while (!global_list.empty())
|
||||||
delete &list.front();
|
delete &global_list.front();
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
@ -52,7 +53,7 @@ int main()
|
|||||||
//Insert some new entities
|
//Insert some new entities
|
||||||
insert_some_entity();
|
insert_some_entity();
|
||||||
insert_some_entity();
|
insert_some_entity();
|
||||||
//list's destructor will free objects
|
//global_list's destructor will free objects
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,9 +12,10 @@
|
|||||||
//[doc_erasing_and_disposing
|
//[doc_erasing_and_disposing
|
||||||
#include <boost/intrusive/list.hpp>
|
#include <boost/intrusive/list.hpp>
|
||||||
|
|
||||||
|
using namespace boost::intrusive;
|
||||||
|
|
||||||
//A class that can be inserted in an intrusive list
|
//A class that can be inserted in an intrusive list
|
||||||
class my_class
|
class my_class : public list_base_hook<>
|
||||||
: public boost::intrusive::list_base_hook<>
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
my_class(int i)
|
my_class(int i)
|
||||||
@ -26,20 +27,18 @@ class my_class
|
|||||||
};
|
};
|
||||||
|
|
||||||
//Definition of the intrusive list
|
//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
|
//The predicate function
|
||||||
class is_even
|
struct is_even
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
bool operator()(const my_class &c) const
|
bool operator()(const my_class &c) const
|
||||||
{ return 0 == (c.int_ % 2); }
|
{ return 0 == (c.int_ % 2); }
|
||||||
};
|
};
|
||||||
|
|
||||||
//The disposer object function
|
//The disposer object function
|
||||||
class delete_disposer
|
struct delete_disposer
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
void operator()(my_class *delete_this)
|
void operator()(my_class *delete_this)
|
||||||
{ delete delete_this; }
|
{ delete delete_this; }
|
||||||
};
|
};
|
||||||
@ -53,9 +52,7 @@ int main()
|
|||||||
|
|
||||||
try{
|
try{
|
||||||
//Insert new objects in the container
|
//Insert new objects in the container
|
||||||
for(int i = 0; i < MaxElem; ++i){
|
for(int i = 0; i < MaxElem; ++i) list.push_back(*new my_class(i));
|
||||||
list.push_back(*new my_class(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
//Now use remove_and_dispose_if to erase and delete the objects
|
//Now use remove_and_dispose_if to erase and delete the objects
|
||||||
list.remove_and_dispose_if(is_even(), delete_disposer());
|
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;
|
using namespace boost::intrusive;
|
||||||
|
|
||||||
class MyClass : public list_base_hook<>
|
class MyClass : public list_base_hook<>
|
||||||
{
|
{
|
||||||
int int_;
|
int int_;
|
||||||
|
|
||||||
@ -23,62 +23,51 @@ class MyClass : public list_base_hook<>
|
|||||||
list_member_hook<> member_hook_;
|
list_member_hook<> member_hook_;
|
||||||
|
|
||||||
MyClass(int i) : int_(i) {}
|
MyClass(int i) : int_(i) {}
|
||||||
int get() const { return int_; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//Define a list that will store MyClass using the base hook
|
//Define a list that will store MyClass using the base hook
|
||||||
typedef list< list_base_hook<>::value_traits<MyClass> >
|
typedef list<MyClass> BaseList;
|
||||||
BaseList;
|
|
||||||
|
|
||||||
//Define a list that will store MyClass using the member hook
|
//Define a list that will store MyClass using the member hook
|
||||||
typedef list< list_member_hook<>::
|
typedef member_hook
|
||||||
value_traits<MyClass, &MyClass::member_hook_>
|
< MyClass, list_member_hook<>, &MyClass::member_hook_> MemberOption;
|
||||||
> MemberList;
|
typedef list<MyClass, MemberOption> MemberList;
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
typedef std::vector<MyClass> Vect;
|
typedef std::vector<MyClass>::iterator VectIt;
|
||||||
typedef Vect::iterator VectIt;
|
typedef std::vector<MyClass>::reverse_iterator VectRit;
|
||||||
typedef Vect::reverse_iterator VectRit;
|
|
||||||
|
|
||||||
//Create several MyClass objects, each one
|
//Create several MyClass objects, each one with a different value
|
||||||
//with a different internal number
|
std::vector<MyClass> values;
|
||||||
Vect myclassvector;
|
for(int i = 0; i < 100; ++i) values.push_back(MyClass(i));
|
||||||
for(int i = 0; i < 100; ++i)
|
|
||||||
myclassvector.push_back(MyClass(i));
|
|
||||||
|
|
||||||
BaseList baselist;
|
BaseList baselist;
|
||||||
MemberList memberlist;
|
MemberList memberlist;
|
||||||
|
|
||||||
//Now insert them in the reverse order
|
//Now insert them in the reverse order in the base hook list
|
||||||
//in the base hook intrusive list
|
for(VectIt it(values.begin()), itend(values.end())
|
||||||
for(VectIt it(myclassvector.begin()), itend(myclassvector.end())
|
|
||||||
; it != itend ; ++it){
|
; it != itend ; ++it){
|
||||||
baselist.push_front(*it);
|
baselist.push_front(*it);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Now insert them in the same order as in vector in the
|
//Now insert them in the same order as in vector in the member hook list
|
||||||
//member hook intrusive list
|
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it)
|
||||||
for(VectIt it(myclassvector.begin()), itend(myclassvector.end())
|
|
||||||
; it != itend; ++it){
|
|
||||||
memberlist.push_back(*it);
|
memberlist.push_back(*it);
|
||||||
}
|
|
||||||
|
|
||||||
//Now test lists
|
//Now test lists
|
||||||
{
|
{
|
||||||
BaseList::reverse_iterator rbit(baselist.rbegin()), rbitend(baselist.rend());
|
BaseList::reverse_iterator rbit(baselist.rbegin()), rbitend(baselist.rend());
|
||||||
MemberList::iterator mit(memberlist.begin()), mitend(memberlist.end());
|
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
|
//Test the objects inserted in the base hook list
|
||||||
for(; it != itend; ++it, ++rbit){
|
for(; it != itend; ++it, ++rbit)
|
||||||
if(&*rbit != &*it) return 1;
|
if(&*rbit != &*it) return 1;
|
||||||
}
|
|
||||||
|
|
||||||
//Test the objects inserted in the member hook list
|
//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;
|
if(&*mit != &*it) return 1;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -15,43 +15,44 @@
|
|||||||
#include <boost/functional/hash.hpp>
|
#include <boost/functional/hash.hpp>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
using namespace boost::intrusive;
|
||||||
|
|
||||||
class intrusive_data
|
class intrusive_data
|
||||||
{
|
{
|
||||||
int data_id_;
|
int data_id_;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
int get() const { return data_id_; }
|
|
||||||
void set(int id) { data_id_ = id; }
|
void set(int id) { data_id_ = id; }
|
||||||
|
|
||||||
//This class can be inserted in an intrusive list
|
//This class can be inserted in an intrusive list
|
||||||
typedef boost::intrusive::
|
list_member_hook<> list_hook_;
|
||||||
list_member_hook<> list_member_hook_t;
|
|
||||||
list_member_hook_t list_hook_;
|
|
||||||
|
|
||||||
//This class can be inserted in an intrusive unordered_set
|
//This class can be inserted in an intrusive unordered_set
|
||||||
typedef boost::intrusive::
|
unordered_set_member_hook<> unordered_set_hook_;
|
||||||
unordered_set_member_hook<> unordered_set_member_hook_t;
|
|
||||||
unordered_set_member_hook_t unordered_set_hook_;
|
|
||||||
|
|
||||||
//Comparison operators
|
//Comparison operators
|
||||||
friend bool operator==(const intrusive_data &a, const intrusive_data &b)
|
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)
|
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
|
//Definition of the intrusive list that will hold intrusive_data
|
||||||
typedef boost::intrusive::list< intrusive_data::list_member_hook_t::
|
typedef member_hook<intrusive_data, list_member_hook<>
|
||||||
value_traits<intrusive_data, &intrusive_data::list_hook_> > list_t;
|
, &intrusive_data::list_hook_> MemberListOption;
|
||||||
|
typedef list<intrusive_data, MemberListOption> list_t;
|
||||||
|
|
||||||
//Definition of the intrusive unordered_set that will hold intrusive_data
|
//Definition of the intrusive unordered_set that will hold intrusive_data
|
||||||
typedef boost::intrusive::unordered_set< intrusive_data::unordered_set_member_hook_t::
|
typedef member_hook
|
||||||
value_traits<intrusive_data, &intrusive_data::unordered_set_hook_> > unordered_set_t;
|
< 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()
|
int main()
|
||||||
{
|
{
|
||||||
@ -62,30 +63,32 @@ int main()
|
|||||||
//Declare the intrusive containers
|
//Declare the intrusive containers
|
||||||
list_t list;
|
list_t list;
|
||||||
unordered_set_t::bucket_type buckets[MaxElem];
|
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
|
//Initialize all the nodes
|
||||||
for(int i = 0; i < MaxElem; ++i)
|
for(int i = 0; i < MaxElem; ++i) nodes[i].set(i);
|
||||||
nodes[i].set(i);
|
|
||||||
|
|
||||||
//Now insert them in both intrusive containers
|
//Now insert them in both intrusive containers
|
||||||
list.insert(list.end(), nodes.begin(), nodes.end());
|
list.insert(list.end(), nodes.begin(), nodes.end());
|
||||||
unordered_set.insert(nodes.begin(), nodes.end());
|
unordered_set.insert(nodes.begin(), nodes.end());
|
||||||
|
|
||||||
//Now check list::iterator_to
|
//Now check the iterator_to function
|
||||||
//which is an static member function
|
|
||||||
list_t::iterator list_it(list.begin());
|
list_t::iterator list_it(list.begin());
|
||||||
for(int i = 0; i < MaxElem; ++i, ++list_it)
|
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;
|
return 1;
|
||||||
|
|
||||||
//Now check unordered_set::iterator_to (which is a member function)
|
//Now check unordered_set::s_iterator_to (which is a member function)
|
||||||
//and unordered_set::local_current (which is an static 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());
|
unordered_set_t::iterator unordered_set_it(unordered_set.begin());
|
||||||
for(int i = 0; i < MaxElem; ++i, ++unordered_set_it){
|
for(int i = 0; i < MaxElem; ++i){
|
||||||
if(unordered_set.iterator_to(nodes[i]) != unordered_set.find(nodes[i]))
|
unordered_set_it = unordered_set.find(nodes[i]);
|
||||||
|
if(unordered_set.iterator_to(nodes[i]) != unordered_set_it)
|
||||||
return 1;
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
using namespace boost::intrusive;
|
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_;
|
int int_;
|
||||||
|
|
||||||
@ -26,63 +26,49 @@ class MyClass : public list_base_hook<> //This is a derivation hook
|
|||||||
MyClass(int i)
|
MyClass(int i)
|
||||||
: int_(i)
|
: int_(i)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
int get() const
|
|
||||||
{ return int_; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//Define a list that will store MyClass using the public base hook
|
//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
|
//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()
|
int main()
|
||||||
{
|
{
|
||||||
typedef std::vector<MyClass> Vect;
|
typedef std::vector<MyClass>::iterator VectIt;
|
||||||
typedef Vect::iterator VectIt;
|
typedef std::vector<MyClass>::reverse_iterator VectRit;
|
||||||
typedef Vect::reverse_iterator VectRit;
|
|
||||||
|
|
||||||
//Create several MyClass objects, each one
|
//Create several MyClass objects, each one with a different value
|
||||||
//with a different internal number
|
std::vector<MyClass> values;
|
||||||
Vect myclassvector;
|
for(int i = 0; i < 100; ++i) values.push_back(MyClass(i));
|
||||||
for(int i = 0; i < 100; ++i)
|
|
||||||
myclassvector.push_back(MyClass(i));
|
|
||||||
|
|
||||||
BaseList baselist;
|
BaseList baselist;
|
||||||
MemberList memberlist;
|
MemberList memberlist;
|
||||||
|
|
||||||
//Now insert them in the reverse order
|
//Now insert them in the reverse order in the base hook list
|
||||||
//in the base hook intrusive list
|
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it)
|
||||||
for(VectIt it(myclassvector.begin()), itend(myclassvector.end())
|
|
||||||
; it != itend
|
|
||||||
; ++it){
|
|
||||||
baselist.push_front(*it);
|
baselist.push_front(*it);
|
||||||
}
|
|
||||||
|
|
||||||
//Now insert them in the same order as in vector in the
|
//Now insert them in the same order as in vector in the member hook list
|
||||||
//member hook intrusive list
|
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it)
|
||||||
for(VectIt it(myclassvector.begin()), itend(myclassvector.end())
|
|
||||||
; it != itend
|
|
||||||
; ++it){
|
|
||||||
memberlist.push_back(*it);
|
memberlist.push_back(*it);
|
||||||
}
|
|
||||||
|
|
||||||
//Now test lists
|
//Now test lists
|
||||||
{
|
{
|
||||||
BaseList::reverse_iterator rbit(baselist.rbegin()), rbitend(baselist.rend());
|
BaseList::reverse_iterator rbit(baselist.rbegin()), rbitend(baselist.rend());
|
||||||
MemberList::iterator mit(memberlist.begin()), mitend(memberlist.end());
|
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
|
//Test the objects inserted in the base hook list
|
||||||
for(; it != itend; ++it, ++rbit){
|
for(; it != itend; ++it, ++rbit)
|
||||||
if(&*rbit != &*it) return 1;
|
if(&*rbit != &*it) return 1;
|
||||||
}
|
|
||||||
|
|
||||||
//Test the objects inserted in the member hook list
|
//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;
|
if(&*mit != &*it) return 1;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -9,35 +9,49 @@
|
|||||||
// See http://www.boost.org/libs/intrusive for documentation.
|
// 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
|
//[doc_offset_ptr_0
|
||||||
#include <boost/intrusive/list.hpp>
|
#include <boost/intrusive/list.hpp>
|
||||||
#include <boost/interprocess/offset_ptr.hpp>
|
#include <boost/interprocess/offset_ptr.hpp>
|
||||||
|
|
||||||
|
using namespace boost::intrusive;
|
||||||
|
namespace ip = boost::interprocess;
|
||||||
|
|
||||||
class shared_memory_data
|
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_;
|
int data_id_;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
int get() const { return data_id_; }
|
int get() const { return data_id_; }
|
||||||
void set(int id) { data_id_ = 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
|
//[doc_offset_ptr_1
|
||||||
#include <boost/interprocess/managed_shared_memory.hpp>
|
#include <boost/interprocess/managed_shared_memory.hpp>
|
||||||
#include <boost/interprocess/containers/vector.hpp>
|
#include <boost/interprocess/containers/vector.hpp>
|
||||||
|
#include <boost/interprocess/containers/list.hpp>
|
||||||
#include <boost/interprocess/allocators/allocator.hpp>
|
#include <boost/interprocess/allocators/allocator.hpp>
|
||||||
|
|
||||||
//Definition of the shared memory friendly intrusive list
|
//Definition of the shared memory friendly intrusive list
|
||||||
typedef boost::intrusive::list< shared_memory_data::member_hook_t::
|
typedef ip::list<shared_memory_data> shm_list_t;
|
||||||
value_traits<shared_memory_data, &shared_memory_data::list_hook_> > shm_list_t;
|
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
@ -45,45 +59,42 @@ int main()
|
|||||||
//nodes and the container itself must be created in shared memory
|
//nodes and the container itself must be created in shared memory
|
||||||
const int MaxElem = 100;
|
const int MaxElem = 100;
|
||||||
const int ShmSize = 50000;
|
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
|
//Initialize all the nodes
|
||||||
shared_memory_object::remove(ShmName);
|
for(int i = 0; i < MaxElem; ++i) (*pshm_vect)[i].set(i);
|
||||||
managed_shared_memory shm(create_only, ShmName, ShmSize);
|
|
||||||
|
|
||||||
//Create all nodes in shared memory using a shared memory vector
|
//Now create the shared memory intrusive list
|
||||||
//See Boost.Interprocess documentation for more information on this
|
shm_list_t *plist = shm.construct<shm_list_t>(ip::anonymous_instance)();
|
||||||
typedef allocator< shared_memory_data
|
plist->insert(plist->end(), pshm_vect->begin(), pshm_vect->end());
|
||||||
, 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);
|
|
||||||
|
|
||||||
//Initialize all the nodes
|
//Check all the inserted nodes
|
||||||
for(int i = 0; i < MaxElem; ++i){
|
int checker = 0;
|
||||||
(*pshm_vect)[i].set(i);
|
for( shm_list_t::const_iterator it = plist->begin(), itend(plist->end())
|
||||||
}
|
; it != itend; ++it, ++checker){
|
||||||
|
if(it->get() != checker) return false;
|
||||||
//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;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
//Now delete the list and after that, the nodes
|
//Now delete the list and after that, the nodes
|
||||||
shm.destroy_ptr(plist);
|
shm.destroy_ptr(plist);
|
||||||
shm.destroy_ptr(pshm_vect);
|
shm.destroy_ptr(pshm_vect);
|
||||||
|
}
|
||||||
|
ip::shared_memory_object::remove(ShmName);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
//]
|
//]
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
using namespace boost::intrusive;
|
using namespace boost::intrusive;
|
||||||
|
|
||||||
//This is a base hook
|
//This is a base hook
|
||||||
class MyClass : public set_base_hook<>
|
class MyClass : public set_base_hook<>
|
||||||
{
|
{
|
||||||
int int_;
|
int int_;
|
||||||
|
|
||||||
@ -28,69 +28,54 @@ class MyClass : public set_base_hook<>
|
|||||||
MyClass(int i)
|
MyClass(int i)
|
||||||
: int_(i)
|
: int_(i)
|
||||||
{}
|
{}
|
||||||
int get() const
|
|
||||||
{ return int_; }
|
|
||||||
friend bool operator< (const MyClass &a, const MyClass &b)
|
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)
|
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)
|
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
|
//Define an set using the base hook that will store values in reverse order
|
||||||
//in reverse order using the public base hook
|
typedef set< MyClass, compare<std::greater<MyClass> > > BaseSet;
|
||||||
typedef set< set_base_hook<>::value_traits<MyClass>
|
|
||||||
, std::greater<MyClass> > BaseSet;
|
|
||||||
|
|
||||||
//Define an multiset that will store MyClass
|
//Define an multiset using the member hook
|
||||||
//using the public member hook
|
typedef member_hook<MyClass, set_member_hook<>, &MyClass::member_hook_> MemberOption;
|
||||||
typedef multiset< set_member_hook<>::
|
typedef multiset< MyClass, MemberOption> MemberIMultiset;
|
||||||
value_traits<MyClass, &MyClass::member_hook_>
|
|
||||||
, std::less<MyClass> > MemberIMultiset;
|
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
typedef std::vector<MyClass> Vect;
|
typedef std::vector<MyClass>::iterator VectIt;
|
||||||
typedef Vect::iterator VectIt;
|
typedef std::vector<MyClass>::reverse_iterator VectRit;
|
||||||
typedef Vect::reverse_iterator VectRit;
|
|
||||||
|
|
||||||
//Create several MyClass objects, each one
|
//Create several MyClass objects, each one with a different value
|
||||||
//with a different internal number
|
std::vector<MyClass> values;
|
||||||
Vect myclassvector;
|
for(int i = 0; i < 100; ++i) values.push_back(MyClass(i));
|
||||||
for(int i = 0; i < 100; ++i)
|
|
||||||
myclassvector.push_back(MyClass(i));
|
|
||||||
|
|
||||||
BaseSet baseset;
|
BaseSet baseset;
|
||||||
MemberIMultiset membermultiset;
|
MemberIMultiset membermultiset;
|
||||||
|
|
||||||
//Now insert them in the reverse order
|
//Now insert them in the reverse order in the base hook set
|
||||||
//in the base hook intrusive set
|
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it)
|
||||||
for(VectIt it(myclassvector.begin()), itend(myclassvector.end())
|
|
||||||
; it != itend; ++it)
|
|
||||||
baseset.insert(*it);
|
baseset.insert(*it);
|
||||||
|
|
||||||
//Now insert them in the same order as in vector in the
|
//Now insert them in the same order as in vector in the member hook set
|
||||||
//member hook intrusive set
|
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it)
|
||||||
for(VectIt it(myclassvector.begin()), itend(myclassvector.end())
|
|
||||||
; it != itend; ++it)
|
|
||||||
membermultiset.insert(*it);
|
membermultiset.insert(*it);
|
||||||
|
|
||||||
//Now test sets
|
//Now test sets
|
||||||
{
|
{
|
||||||
BaseSet::reverse_iterator rbit(baseset.rbegin()), rbitend(baseset.rend());
|
BaseSet::reverse_iterator rbit(baseset.rbegin()), rbitend(baseset.rend());
|
||||||
MemberIMultiset::iterator mit(membermultiset.begin()), mitend(membermultiset.end());
|
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
|
//Test the objects inserted in the base hook set
|
||||||
for(; it != itend; ++it, ++rbit){
|
for(; it != itend; ++it, ++rbit)
|
||||||
if(&*rbit != &*it) return 1;
|
if(&*rbit != &*it) return 1;
|
||||||
}
|
|
||||||
|
|
||||||
//Test the objects inserted in the member hook set
|
//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;
|
if(&*mit != &*it) return 1;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
using namespace boost::intrusive;
|
using namespace boost::intrusive;
|
||||||
|
|
||||||
//This is a base hook
|
//This is a base hook
|
||||||
class MyClass : public slist_base_hook<>
|
class MyClass : public slist_base_hook<>
|
||||||
{
|
{
|
||||||
int int_;
|
int int_;
|
||||||
|
|
||||||
@ -27,45 +27,34 @@ class MyClass : public slist_base_hook<>
|
|||||||
MyClass(int i)
|
MyClass(int i)
|
||||||
: int_(i)
|
: int_(i)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
int get() const
|
|
||||||
{ return int_; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//Define an slist that will store MyClass using the public base hook
|
//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
|
//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()
|
int main()
|
||||||
{
|
{
|
||||||
typedef std::vector<MyClass> Vect;
|
typedef std::vector<MyClass>::iterator VectIt;
|
||||||
typedef Vect::iterator VectIt;
|
typedef std::vector<MyClass>::reverse_iterator VectRit;
|
||||||
typedef Vect::reverse_iterator VectRit;
|
|
||||||
|
|
||||||
//Create several MyClass objects, each one
|
//Create several MyClass objects, each one with a different value
|
||||||
//with a different internal number
|
std::vector<MyClass> values;
|
||||||
Vect myclassvector;
|
for(int i = 0; i < 100; ++i) values.push_back(MyClass(i));
|
||||||
for(int i = 0; i < 100; ++i)
|
|
||||||
myclassvector.push_back(MyClass(i));
|
|
||||||
|
|
||||||
BaseList baselist;
|
BaseList baselist;
|
||||||
MemberList memberlist;
|
MemberList memberlist;
|
||||||
|
|
||||||
//Now insert them in the reverse order
|
//Now insert them in the reverse order in the base hook list
|
||||||
//in the base hook intrusive list
|
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it)
|
||||||
for(VectIt it(myclassvector.begin()), itend(myclassvector.end())
|
|
||||||
; it != itend
|
|
||||||
; ++it){
|
|
||||||
baselist.push_front(*it);
|
baselist.push_front(*it);
|
||||||
}
|
|
||||||
|
|
||||||
//Now insert them in the same order as in vector in the
|
//Now insert them in the same order as in vector in the member hook list
|
||||||
//member hook intrusive list
|
|
||||||
for(BaseList::iterator it(baselist.begin()), itend(baselist.end())
|
for(BaseList::iterator it(baselist.begin()), itend(baselist.end())
|
||||||
; it != itend
|
; it != itend; ++it){
|
||||||
; ++it){
|
|
||||||
memberlist.push_front(*it);
|
memberlist.push_front(*it);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,18 +62,16 @@ int main()
|
|||||||
{
|
{
|
||||||
BaseList::iterator bit(baselist.begin()), bitend(baselist.end());
|
BaseList::iterator bit(baselist.begin()), bitend(baselist.end());
|
||||||
MemberList::iterator mit(memberlist.begin()), mitend(memberlist.end());
|
MemberList::iterator mit(memberlist.begin()), mitend(memberlist.end());
|
||||||
VectRit rit(myclassvector.rbegin()), ritend(myclassvector.rend());
|
VectRit rit(values.rbegin()), ritend(values.rend());
|
||||||
VectIt it(myclassvector.begin()), itend(myclassvector.end());
|
VectIt it(values.begin()), itend(values.end());
|
||||||
|
|
||||||
//Test the objects inserted in the base hook list
|
//Test the objects inserted in the base hook list
|
||||||
for(; rit != ritend; ++rit, ++bit){
|
for(; rit != ritend; ++rit, ++bit)
|
||||||
if(&*bit != &*rit) return 1;
|
if(&*bit != &*rit) return 1;
|
||||||
}
|
|
||||||
|
|
||||||
//Test the objects inserted in the member hook list
|
//Test the objects inserted in the member hook list
|
||||||
for(; it != itend; ++it, ++mit){
|
for(; it != itend; ++it, ++mit)
|
||||||
if(&*mit != &*it) return 1;
|
if(&*mit != &*it) return 1;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
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;
|
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_;
|
int int_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
//This is a member hook
|
unordered_set_member_hook<> member_hook_; //This is a member hook
|
||||||
unordered_set_member_hook<> member_hook_;
|
|
||||||
|
|
||||||
MyClass(int i)
|
MyClass(int i)
|
||||||
: int_(i)
|
: int_(i)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
int get() const
|
|
||||||
{ return int_; }
|
|
||||||
|
|
||||||
friend bool operator== (const MyClass &a, const MyClass &b)
|
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)
|
friend std::size_t hash_value(const MyClass &value)
|
||||||
{ return a.get() > b.get(); }
|
{ return std::size_t(value.int_); }
|
||||||
};
|
};
|
||||||
|
|
||||||
std::size_t hash_value(const MyClass &value)
|
//Define an unordered_set that will store MyClass objects using the base hook
|
||||||
{ return std::size_t(value.get()); }
|
typedef unordered_set<MyClass> BaseSet;
|
||||||
|
|
||||||
//Define an unordered_set that will store MyClass
|
//Define an unordered_multiset that will store MyClass using the member hook
|
||||||
//in reverse order using the public base hook
|
typedef member_hook<MyClass, unordered_set_member_hook<>, &MyClass::member_hook_>
|
||||||
typedef unordered_set< unordered_set_base_hook<>::
|
MemberOption;
|
||||||
value_traits<MyClass> > BaseSet;
|
typedef unordered_multiset< MyClass, MemberOption> MemberMultiSet;
|
||||||
|
|
||||||
//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;
|
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
typedef std::vector<MyClass> Vect;
|
typedef std::vector<MyClass>::iterator VectIt;
|
||||||
typedef Vect::iterator VectIt;
|
typedef std::vector<MyClass>::reverse_iterator VectRit;
|
||||||
typedef Vect::reverse_iterator VectRit;
|
|
||||||
|
|
||||||
//Create a vector with 100 different MyClass objects,
|
//Create a vector with 100 different MyClass objects
|
||||||
//each one with a different internal number
|
std::vector<MyClass> values;
|
||||||
Vect myclassvector;
|
for(int i = 0; i < 100; ++i) values.push_back(MyClass(i));
|
||||||
for(int i = 0; i < 100; ++i)
|
|
||||||
myclassvector.push_back(MyClass(i));
|
|
||||||
|
|
||||||
//Create a copy of the vector
|
//Create a copy of the vector
|
||||||
Vect myclassvector2(myclassvector);
|
std::vector<MyClass> values2(values);
|
||||||
|
|
||||||
//Create a bucket array for base_set
|
//Create a bucket array for base_set
|
||||||
BaseSet::bucket_type base_buckets[100];
|
BaseSet::bucket_type base_buckets[100];
|
||||||
@ -74,20 +61,18 @@ int main()
|
|||||||
//Create a bucket array for member_multi_set
|
//Create a bucket array for member_multi_set
|
||||||
MemberMultiSet::bucket_type member_buckets[200];
|
MemberMultiSet::bucket_type member_buckets[200];
|
||||||
|
|
||||||
//Create a the unordered_set and unordered_multiset,
|
//Create unordered containers taking buckets as arguments
|
||||||
//taking buckets as arguments
|
BaseSet base_set(BaseSet::bucket_traits(base_buckets, 100));
|
||||||
BaseSet base_set(base_buckets, 100);
|
MemberMultiSet member_multi_set
|
||||||
MemberMultiSet member_multi_set(member_buckets, 200);
|
(MemberMultiSet::bucket_traits(member_buckets, 200));
|
||||||
|
|
||||||
//Now insert myclassvector's elements in the unordered_set
|
//Now insert values's elements in the unordered_set
|
||||||
for(VectIt it(myclassvector.begin()), itend(myclassvector.end())
|
for(VectIt it(values.begin()), itend(values.end()); it != itend; ++it)
|
||||||
; it != itend; ++it){
|
|
||||||
base_set.insert(*it);
|
base_set.insert(*it);
|
||||||
}
|
|
||||||
|
|
||||||
//Now insert myclassvector's and myclassvector2's elements in the unordered_multiset
|
//Now insert values's and values2's elements in the unordered_multiset
|
||||||
for(VectIt it(myclassvector.begin()), itend(myclassvector.end()),
|
for(VectIt it(values.begin()), itend(values.end()),
|
||||||
it2(myclassvector2.begin()),itend2(myclassvector2.end())
|
it2(values2.begin()),itend2(values2.end())
|
||||||
; it != itend; ++it, ++it2){
|
; it != itend; ++it, ++it2){
|
||||||
member_multi_set.insert(*it);
|
member_multi_set.insert(*it);
|
||||||
member_multi_set.insert(*it2);
|
member_multi_set.insert(*it2);
|
||||||
@ -95,7 +80,7 @@ int main()
|
|||||||
|
|
||||||
//Now find every element
|
//Now find every element
|
||||||
{
|
{
|
||||||
VectIt it(myclassvector.begin()), itend(myclassvector.end());
|
VectIt it(values.begin()), itend(values.end());
|
||||||
|
|
||||||
for(; it != itend; ++it){
|
for(; it != itend; ++it){
|
||||||
//base_set should contain one element for each key
|
//base_set should contain one element for each key
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
//
|
//
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
//[doc_value_traits_code_legacy
|
//[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/list.hpp>
|
||||||
#include <boost/intrusive/slist.hpp>
|
#include <boost/intrusive/slist.hpp>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -30,6 +30,9 @@ struct legacy_value
|
|||||||
//Define our own NodeTraits that will configure singly and doubly linked
|
//Define our own NodeTraits that will configure singly and doubly linked
|
||||||
//list algorithms. Note that this node traits is compatible with
|
//list algorithms. Note that this node traits is compatible with
|
||||||
//circular_slist_algorithms and circular_list_algorithms.
|
//circular_slist_algorithms and circular_list_algorithms.
|
||||||
|
|
||||||
|
namespace bi = boost::intrusive;
|
||||||
|
|
||||||
struct legacy_node_traits
|
struct legacy_node_traits
|
||||||
{
|
{
|
||||||
typedef legacy_value node;
|
typedef legacy_value node;
|
||||||
@ -54,7 +57,7 @@ struct legacy_value_traits
|
|||||||
typedef legacy_value value_type;
|
typedef legacy_value value_type;
|
||||||
typedef legacy_value * pointer;
|
typedef legacy_value * pointer;
|
||||||
typedef const legacy_value * const_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 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 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); }
|
static pointer to_value_ptr(node_ptr n) { return pointer(n); }
|
||||||
@ -65,8 +68,9 @@ struct legacy_value_traits
|
|||||||
|
|
||||||
//[doc_value_traits_test
|
//[doc_value_traits_test
|
||||||
//Now define an intrusive list and slist that will store legacy_value objects
|
//Now define an intrusive list and slist that will store legacy_value objects
|
||||||
typedef boost::intrusive::list <legacy_value_traits> LegacyAbiList;
|
typedef bi::value_traits<legacy_value_traits> ValueTraitsOption;
|
||||||
typedef boost::intrusive::slist<legacy_value_traits> LegacyAbiSlist;
|
typedef bi::list<legacy_value, ValueTraitsOption> LegacyAbiList;
|
||||||
|
typedef bi::slist<legacy_value, ValueTraitsOption> LegacyAbiSlist;
|
||||||
|
|
||||||
template<class List>
|
template<class List>
|
||||||
bool test_list()
|
bool test_list()
|
||||||
@ -87,9 +91,8 @@ bool test_list()
|
|||||||
typename Vect::const_iterator it(legacy_vector.begin()), itend(legacy_vector.end());
|
typename Vect::const_iterator it(legacy_vector.begin()), itend(legacy_vector.end());
|
||||||
|
|
||||||
//Test the objects inserted in our list
|
//Test the objects inserted in our list
|
||||||
for(; it != itend; ++it, ++bit){
|
for(; it != itend; ++it, ++bit)
|
||||||
if(&*bit != &*it) return false;
|
if(&*bit != &*it) return false;
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,11 +15,11 @@
|
|||||||
using namespace boost::intrusive;
|
using namespace boost::intrusive;
|
||||||
|
|
||||||
//An abstract class that can be inserted in an intrusive list
|
//An abstract class that can be inserted in an intrusive list
|
||||||
class Window : public list_base_hook<>
|
class Window : public list_base_hook<>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
//This is a container those value is an abstract class: you can't do this with std::list.
|
//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
|
//An static intrusive list declaration
|
||||||
static win_list all_windows;
|
static win_list all_windows;
|
||||||
@ -27,7 +27,7 @@ class Window : public list_base_hook<>
|
|||||||
//Constructor. Includes this window in the list
|
//Constructor. Includes this window in the list
|
||||||
Window() { all_windows.push_back(*this); }
|
Window() { all_windows.push_back(*this); }
|
||||||
//Destructor. Removes this node from the list
|
//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
|
//Pure virtual function to be implemented by derived classes
|
||||||
virtual void Paint() = 0;
|
virtual void Paint() = 0;
|
||||||
};
|
};
|
||||||
@ -71,15 +71,13 @@ class MainWindow : public Window
|
|||||||
//Main function
|
//Main function
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
//When each Window class is created, is
|
//When a Window class is created, is automatically registered in the global list
|
||||||
//automatically registered in the global list
|
|
||||||
MainWindow window;
|
MainWindow window;
|
||||||
|
|
||||||
//Paint all the windows, sub-windows and so on
|
//Paint all the windows, sub-windows and so on
|
||||||
paint_all_windows();
|
paint_all_windows();
|
||||||
|
|
||||||
//All the windows are automatically unregistered
|
//All the windows are automatically unregistered in their destructors.
|
||||||
//in their destructors.
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
//]
|
//]
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//Includes for tests
|
//Includes for tests
|
||||||
|
#include <boost/config.hpp>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@ -26,11 +27,8 @@ const int NumElements = 100000;
|
|||||||
|
|
||||||
using namespace boost::intrusive;
|
using namespace boost::intrusive;
|
||||||
|
|
||||||
template<bool BigSize>
|
template<bool BigSize> struct filler { int dummy[10]; };
|
||||||
struct filler { int dummy[10]; };
|
template <> struct filler<false> {};
|
||||||
|
|
||||||
template <>
|
|
||||||
struct filler<false> {};
|
|
||||||
|
|
||||||
template<bool BigSize> //The object for non-intrusive containers
|
template<bool BigSize> //The object for non-intrusive containers
|
||||||
struct test_class : private filler<BigSize>
|
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_; }
|
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
|
template <bool BigSize, link_mode_type LinkMode>
|
||||||
struct itest_class : public list_base_hook<tag, Policy>, public test_class<BigSize>
|
struct itest_class //The object for intrusive containers
|
||||||
|
: public list_base_hook<link_mode<LinkMode> >, public test_class<BigSize>
|
||||||
{
|
{
|
||||||
itest_class() {}
|
itest_class() {}
|
||||||
itest_class(int i) : test_class<BigSize>(i) {}
|
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
|
struct get_ilist //Helps to define an intrusive list from a policy
|
||||||
{
|
{
|
||||||
typedef list_base_hook<tag, Policy> hook;
|
typedef list<itest_class<BigSize, LinkMode>, constant_time_size<false> > type;
|
||||||
typedef list<typename hook::template value_traits<itest_class<BigSize, Policy> >, false> type;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <bool BigSize> //Helps to define an std list
|
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
|
template <bool BigSize> //Helps to define an std pointer list
|
||||||
struct get_ptrlist { typedef std::list<test_class<BigSize>*> type; };
|
struct get_ptrlist { typedef std::list<test_class<BigSize>*> type; };
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// PUSH_BACK
|
// PUSH_BACK
|
||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
template <bool BigSize, linking_policy Policy>
|
template <bool BigSize, link_mode_type LinkMode>
|
||||||
void test_intrusive_list_push_back()
|
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();
|
ptime tini = microsec_clock::universal_time();
|
||||||
for(int i = 0; i < NumIter; ++i){
|
for(int i = 0; i < NumIter; ++i){
|
||||||
//First create the elements and insert them in the intrusive list
|
//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)
|
for(int i = 0; i < NumElements; ++i)
|
||||||
l.push_back(objects[i]);
|
l.push_back(objects[i]);
|
||||||
//Elements are unlinked in ilist's destructor
|
//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();
|
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>
|
template <bool BigSize>
|
||||||
@ -111,11 +109,12 @@ void test_std_list_push_back()
|
|||||||
stdlist l;
|
stdlist l;
|
||||||
for(int i = 0; i < NumElements; ++i)
|
for(int i = 0; i < NumElements; ++i)
|
||||||
l.push_back(typename stdlist::value_type(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();
|
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>
|
template <bool BigSize>
|
||||||
@ -132,12 +131,13 @@ void test_compact_std_ptrlist_push_back()
|
|||||||
stdptrlist l;
|
stdptrlist l;
|
||||||
for(int i = 0; i < NumElements; ++i)
|
for(int i = 0; i < NumElements; ++i)
|
||||||
l.push_back(&objects[i]);
|
l.push_back(&objects[i]);
|
||||||
//Pointers to elements unlinked and disposed in stdptrlist's destructor
|
//Pointers to elements unlinked and destroyed in stdptrlist's destructor
|
||||||
//Elements disposed in vector's destructor
|
//Elements destroyed in vector's destructor
|
||||||
//]
|
//]
|
||||||
}
|
}
|
||||||
ptime tend = microsec_clock::universal_time();
|
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>
|
template <bool BigSize>
|
||||||
@ -155,12 +155,13 @@ void test_disperse_std_ptrlist_push_back()
|
|||||||
objects.push_back(typename stdlist::value_type(i));
|
objects.push_back(typename stdlist::value_type(i));
|
||||||
l.push_back(&objects.back());
|
l.push_back(&objects.back());
|
||||||
}
|
}
|
||||||
//Pointers to elements unlinked and disposed in stdptrlist's destructor
|
//Pointers to elements unlinked and destroyed in stdptrlist's destructor
|
||||||
//Elements unlinked and disposed in stdlist's destructor
|
//Elements unlinked and destroyed in stdlist's destructor
|
||||||
//]
|
//]
|
||||||
}
|
}
|
||||||
ptime tend = microsec_clock::universal_time();
|
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
|
//[perf_list_reverse
|
||||||
template <bool BigSize, linking_policy Policy>
|
template <bool BigSize, link_mode_type LinkMode>
|
||||||
void test_intrusive_list_reverse()
|
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
|
//First create the elements
|
||||||
std::vector<typename ilist::value_type> objects(NumElements);
|
std::vector<typename ilist::value_type> objects(NumElements);
|
||||||
|
|
||||||
@ -186,7 +187,8 @@ void test_intrusive_list_reverse()
|
|||||||
l.reverse();
|
l.reverse();
|
||||||
}
|
}
|
||||||
ptime tend = microsec_clock::universal_time();
|
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>
|
template <bool BigSize>
|
||||||
@ -205,7 +207,8 @@ void test_std_list_reverse()
|
|||||||
l.reverse();
|
l.reverse();
|
||||||
}
|
}
|
||||||
ptime tend = microsec_clock::universal_time();
|
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>
|
template <bool BigSize>
|
||||||
@ -228,7 +231,8 @@ void test_compact_std_ptrlist_reverse()
|
|||||||
l.reverse();
|
l.reverse();
|
||||||
}
|
}
|
||||||
ptime tend = microsec_clock::universal_time();
|
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>
|
template <bool BigSize>
|
||||||
@ -252,7 +256,8 @@ void test_disperse_std_ptrlist_reverse()
|
|||||||
l.reverse();
|
l.reverse();
|
||||||
}
|
}
|
||||||
ptime tend = microsec_clock::universal_time();
|
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
|
//[perf_list_sort
|
||||||
template <bool BigSize, linking_policy Policy>
|
template <bool BigSize, link_mode_type LinkMode>
|
||||||
void test_intrusive_list_sort()
|
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
|
//First create the elements
|
||||||
std::vector<typename ilist::value_type> objects(NumElements);
|
std::vector<typename ilist::value_type> objects(NumElements);
|
||||||
@ -287,7 +292,8 @@ void test_intrusive_list_sort()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ptime tend = microsec_clock::universal_time();
|
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>
|
template <bool BigSize>
|
||||||
@ -311,7 +317,8 @@ void test_std_list_sort()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ptime tend = microsec_clock::universal_time();
|
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>
|
template <bool BigSize>
|
||||||
@ -340,7 +347,8 @@ void test_compact_std_ptrlist_sort()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ptime tend = microsec_clock::universal_time();
|
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>
|
template <bool BigSize>
|
||||||
@ -368,7 +376,8 @@ void test_disperse_std_ptrlist_sort()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ptime tend = microsec_clock::universal_time();
|
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
|
//[perf_list_write_access
|
||||||
template <bool BigSize, linking_policy Policy>
|
template <bool BigSize, link_mode_type LinkMode>
|
||||||
void test_intrusive_list_write_access()
|
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
|
//First create the elements
|
||||||
std::vector<typename ilist::value_type> objects(NumElements);
|
std::vector<typename ilist::value_type> objects(NumElements);
|
||||||
@ -401,7 +410,8 @@ void test_intrusive_list_write_access()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ptime tend = microsec_clock::universal_time();
|
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>
|
template <bool BigSize>
|
||||||
@ -423,7 +433,8 @@ void test_std_list_write_access()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ptime tend = microsec_clock::universal_time();
|
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>
|
template <bool BigSize>
|
||||||
@ -452,7 +463,8 @@ void test_compact_std_ptrlist_write_access()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ptime tend = microsec_clock::universal_time();
|
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>
|
template <bool BigSize>
|
||||||
@ -479,7 +491,8 @@ void test_disperse_std_ptrlist_write_access()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ptime tend = microsec_clock::universal_time();
|
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>
|
template<bool BigSize>
|
||||||
void do_all_tests()
|
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, normal_link>();
|
||||||
test_intrusive_list_push_back<BigSize, safe_link>();
|
test_intrusive_list_push_back<BigSize, safe_link>();
|
||||||
test_intrusive_list_push_back<BigSize, auto_unlink>();
|
test_intrusive_list_push_back<BigSize, auto_unlink>();
|
||||||
@ -499,7 +512,7 @@ void do_all_tests()
|
|||||||
test_compact_std_ptrlist_push_back<BigSize>();
|
test_compact_std_ptrlist_push_back<BigSize>();
|
||||||
test_disperse_std_ptrlist_push_back<BigSize>();
|
test_disperse_std_ptrlist_push_back<BigSize>();
|
||||||
//reverse
|
//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, normal_link>();
|
||||||
test_intrusive_list_reverse<BigSize, safe_link>();
|
test_intrusive_list_reverse<BigSize, safe_link>();
|
||||||
test_intrusive_list_reverse<BigSize, auto_unlink>();
|
test_intrusive_list_reverse<BigSize, auto_unlink>();
|
||||||
@ -507,7 +520,7 @@ void do_all_tests()
|
|||||||
test_compact_std_ptrlist_reverse<BigSize>();
|
test_compact_std_ptrlist_reverse<BigSize>();
|
||||||
test_disperse_std_ptrlist_reverse<BigSize>();
|
test_disperse_std_ptrlist_reverse<BigSize>();
|
||||||
//sort
|
//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, normal_link>();
|
||||||
test_intrusive_list_sort<BigSize, safe_link>();
|
test_intrusive_list_sort<BigSize, safe_link>();
|
||||||
test_intrusive_list_sort<BigSize, auto_unlink>();
|
test_intrusive_list_sort<BigSize, auto_unlink>();
|
||||||
@ -515,7 +528,7 @@ void do_all_tests()
|
|||||||
test_compact_std_ptrlist_sort<BigSize>();
|
test_compact_std_ptrlist_sort<BigSize>();
|
||||||
test_disperse_std_ptrlist_sort<BigSize>();
|
test_disperse_std_ptrlist_sort<BigSize>();
|
||||||
//write_access
|
//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, normal_link>();
|
||||||
test_intrusive_list_write_access<BigSize, safe_link>();
|
test_intrusive_list_write_access<BigSize, safe_link>();
|
||||||
test_intrusive_list_write_access<BigSize, auto_unlink>();
|
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_shift(std::vector<value_type>& values);
|
||||||
static void test_swap(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_clone(std::vector<value_type>& values);
|
||||||
|
static void test_container_from_end(std::vector<value_type>& values);
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class ValueTraits>
|
template<class ValueTraits>
|
||||||
void test_list<ValueTraits>::test_all(std::vector<typename ValueTraits::value_type>& values)
|
void test_list<ValueTraits>::test_all(std::vector<typename ValueTraits::value_type>& values)
|
||||||
{
|
{
|
||||||
typedef boost::intrusive::list
|
typedef typename ValueTraits::value_type value_type;
|
||||||
< ValueTraits
|
typedef list
|
||||||
, ValueTraits::value_type::constant_time_size
|
< value_type
|
||||||
, std::size_t
|
, value_traits<ValueTraits>
|
||||||
|
, size_type<std::size_t>
|
||||||
|
, constant_time_size<value_type::constant_time_size>
|
||||||
> list_type;
|
> list_type;
|
||||||
|
|
||||||
{
|
{
|
||||||
list_type list(values.begin(), values.end());
|
list_type list(values.begin(), values.end());
|
||||||
test::test_container(list);
|
test::test_container(list);
|
||||||
@ -60,9 +62,15 @@ void test_list<ValueTraits>::test_all(std::vector<typename ValueTraits::value_ty
|
|||||||
test_shift(values);
|
test_shift(values);
|
||||||
test_swap(values);
|
test_swap(values);
|
||||||
test_clone(values);
|
test_clone(values);
|
||||||
|
test_container_from_end(values);
|
||||||
list_type testlist(values.begin(), values.end());
|
/*
|
||||||
list_type testlist2;
|
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:
|
//test: push_front, pop_front, push_back, pop_back, front, back, size, empty:
|
||||||
@ -70,10 +78,12 @@ template<class ValueTraits>
|
|||||||
void test_list<ValueTraits>
|
void test_list<ValueTraits>
|
||||||
::test_front_back(std::vector<typename ValueTraits::value_type>& values)
|
::test_front_back(std::vector<typename ValueTraits::value_type>& values)
|
||||||
{
|
{
|
||||||
typedef boost::intrusive::list
|
typedef typename ValueTraits::value_type value_type;
|
||||||
< ValueTraits
|
typedef list
|
||||||
, ValueTraits::value_type::constant_time_size
|
< value_type
|
||||||
, std::size_t
|
, value_traits<ValueTraits>
|
||||||
|
, size_type<std::size_t>
|
||||||
|
, constant_time_size<value_type::constant_time_size>
|
||||||
> list_type;
|
> list_type;
|
||||||
list_type testlist;
|
list_type testlist;
|
||||||
BOOST_TEST (testlist.empty());
|
BOOST_TEST (testlist.empty());
|
||||||
@ -104,12 +114,12 @@ template<class ValueTraits>
|
|||||||
void test_list<ValueTraits>
|
void test_list<ValueTraits>
|
||||||
::test_sort(std::vector<typename ValueTraits::value_type>& values)
|
::test_sort(std::vector<typename ValueTraits::value_type>& values)
|
||||||
{
|
{
|
||||||
typedef typename ValueTraits::value_type testvalue_t;
|
typedef typename ValueTraits::value_type value_type;
|
||||||
std::vector<int> expected;
|
typedef list
|
||||||
typedef boost::intrusive::list
|
< value_type
|
||||||
< ValueTraits
|
, value_traits<ValueTraits>
|
||||||
, ValueTraits::value_type::constant_time_size
|
, size_type<std::size_t>
|
||||||
, std::size_t
|
, constant_time_size<value_type::constant_time_size>
|
||||||
> list_type;
|
> list_type;
|
||||||
list_type testlist(values.begin(), values.end());
|
list_type testlist(values.begin(), values.end());
|
||||||
|
|
||||||
@ -125,17 +135,17 @@ void test_list<ValueTraits>
|
|||||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist.begin() ); }
|
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>
|
template<class ValueTraits>
|
||||||
void test_list<ValueTraits>
|
void test_list<ValueTraits>
|
||||||
::test_insert(std::vector<typename ValueTraits::value_type>& values)
|
::test_insert(std::vector<typename ValueTraits::value_type>& values)
|
||||||
{
|
{
|
||||||
typedef typename ValueTraits::value_type testvalue_t;
|
typedef typename ValueTraits::value_type value_type;
|
||||||
std::vector<int> expected;
|
typedef list
|
||||||
typedef boost::intrusive::list
|
< value_type
|
||||||
< ValueTraits
|
, value_traits<ValueTraits>
|
||||||
, ValueTraits::value_type::constant_time_size
|
, size_type<std::size_t>
|
||||||
, std::size_t
|
, constant_time_size<value_type::constant_time_size>
|
||||||
> list_type;
|
> list_type;
|
||||||
list_type testlist;
|
list_type testlist;
|
||||||
testlist.assign (&values[0] + 2, &values[0] + 5);
|
testlist.assign (&values[0] + 2, &values[0] + 5);
|
||||||
@ -159,6 +169,9 @@ void test_list<ValueTraits>
|
|||||||
i = testlist.iterator_to (values[4]);
|
i = testlist.iterator_to (values[4]);
|
||||||
BOOST_TEST (&*i == &values[4]);
|
BOOST_TEST (&*i == &values[4]);
|
||||||
|
|
||||||
|
i = list_type::s_iterator_to (values[4]);
|
||||||
|
BOOST_TEST (&*i == &values[4]);
|
||||||
|
|
||||||
i = testlist.erase (i);
|
i = testlist.erase (i);
|
||||||
BOOST_TEST (i == testlist.end());
|
BOOST_TEST (i == testlist.end());
|
||||||
|
|
||||||
@ -170,15 +183,14 @@ template<class ValueTraits>
|
|||||||
void test_list<ValueTraits>
|
void test_list<ValueTraits>
|
||||||
::test_shift(std::vector<typename ValueTraits::value_type>& values)
|
::test_shift(std::vector<typename ValueTraits::value_type>& values)
|
||||||
{
|
{
|
||||||
typedef typename ValueTraits::value_type testvalue_t;
|
typedef typename ValueTraits::value_type value_type;
|
||||||
typedef boost::intrusive::list
|
typedef list
|
||||||
< ValueTraits
|
< value_type
|
||||||
, ValueTraits::value_type::constant_time_size
|
, value_traits<ValueTraits>
|
||||||
, std::size_t
|
, size_type<std::size_t>
|
||||||
|
, constant_time_size<value_type::constant_time_size>
|
||||||
> list_type;
|
> list_type;
|
||||||
list_type testlist;
|
list_type testlist;
|
||||||
std::vector<int> expected;
|
|
||||||
|
|
||||||
const int num_values = (int)values.size();
|
const int num_values = (int)values.size();
|
||||||
std::vector<int> expected_values(num_values);
|
std::vector<int> expected_values(num_values);
|
||||||
|
|
||||||
@ -210,12 +222,13 @@ template<class ValueTraits>
|
|||||||
void test_list<ValueTraits>
|
void test_list<ValueTraits>
|
||||||
::test_swap(std::vector<typename ValueTraits::value_type>& values)
|
::test_swap(std::vector<typename ValueTraits::value_type>& values)
|
||||||
{
|
{
|
||||||
typedef typename ValueTraits::value_type testvalue_t;
|
typedef typename ValueTraits::value_type value_type;
|
||||||
typedef boost::intrusive::list
|
typedef list
|
||||||
<ValueTraits
|
< value_type
|
||||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
, value_traits<ValueTraits>
|
||||||
|
, size_type<std::size_t>
|
||||||
|
, constant_time_size<value_type::constant_time_size>
|
||||||
> list_type;
|
> list_type;
|
||||||
std::vector<int> expected;
|
|
||||||
{
|
{
|
||||||
list_type testlist1 (&values[0], &values[0] + 2);
|
list_type testlist1 (&values[0], &values[0] + 2);
|
||||||
list_type testlist2;
|
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>
|
template<class ValueTraits>
|
||||||
void test_list<ValueTraits>
|
void test_list<ValueTraits>
|
||||||
::test_clone(std::vector<typename ValueTraits::value_type>& values)
|
::test_clone(std::vector<typename ValueTraits::value_type>& values)
|
||||||
{
|
{
|
||||||
typedef typename ValueTraits::value_type testvalue_t;
|
typedef typename ValueTraits::value_type value_type;
|
||||||
std::vector<int> expected;
|
typedef list
|
||||||
typedef boost::intrusive::list
|
< value_type
|
||||||
<ValueTraits
|
, value_traits<ValueTraits>
|
||||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
, size_type<std::size_t>
|
||||||
|
, constant_time_size<value_type::constant_time_size>
|
||||||
> list_type;
|
> list_type;
|
||||||
|
|
||||||
list_type testlist1 (&values[0], &values[0] + values.size());
|
list_type testlist1 (&values[0], &values[0] + values.size());
|
||||||
list_type testlist2;
|
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);
|
BOOST_TEST (testlist2 == testlist1);
|
||||||
testlist2.clear_and_dispose(test::delete_disposer());
|
testlist2.clear_and_dispose(test::delete_disposer<value_type>());
|
||||||
BOOST_TEST (testlist2.empty());
|
BOOST_TEST (testlist2.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -293,17 +323,24 @@ class test_main_template
|
|||||||
public:
|
public:
|
||||||
int operator()()
|
int operator()()
|
||||||
{
|
{
|
||||||
typedef testvalue<VoidPointer, constant_time_size> testvalue_t;
|
typedef testvalue<VoidPointer, constant_time_size> value_type;
|
||||||
std::vector<testvalue_t> data (5);
|
std::vector<value_type> data (5);
|
||||||
for (int i = 0; i < 5; ++i)
|
for (int i = 0; i < 5; ++i)
|
||||||
data[i].value_ = i + 1;
|
data[i].value_ = i + 1;
|
||||||
|
|
||||||
test_list <typename testvalue_t::list_base_hook_t::template
|
test_list < typename detail::get_base_value_traits
|
||||||
value_traits<testvalue_t> >::test_all(data);
|
< value_type
|
||||||
|
, typename value_type::list_base_hook_t
|
||||||
test_list <typename testvalue_t::list_member_hook_t::template
|
>::type
|
||||||
value_traits<testvalue_t, &testvalue_t::list_node_> >::test_all(data);
|
>::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;
|
return 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -314,48 +351,64 @@ class test_main_template<VoidPointer, false>
|
|||||||
public:
|
public:
|
||||||
int operator()()
|
int operator()()
|
||||||
{
|
{
|
||||||
typedef testvalue<VoidPointer, false> testvalue_t;
|
typedef testvalue<VoidPointer, false> value_type;
|
||||||
std::vector<testvalue_t> data (5);
|
std::vector<value_type> data (5);
|
||||||
for (int i = 0; i < 5; ++i)
|
for (int i = 0; i < 5; ++i)
|
||||||
data[i].value_ = i + 1;
|
data[i].value_ = i + 1;
|
||||||
|
|
||||||
test_list <typename testvalue_t::list_base_hook_t::template
|
test_list < typename detail::get_base_value_traits
|
||||||
value_traits<testvalue_t> >::test_all(data);
|
< value_type
|
||||||
|
, typename value_type::list_base_hook_t
|
||||||
|
>::type
|
||||||
|
>::test_all(data);
|
||||||
|
|
||||||
test_list <typename testvalue_t::list_member_hook_t::template
|
test_list < typename detail::get_member_value_traits
|
||||||
value_traits<testvalue_t, &testvalue_t::list_node_> >::test_all(data);
|
< 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
|
test_list < typename detail::get_member_value_traits
|
||||||
value_traits<testvalue_t> >::test_all(data);
|
< value_type
|
||||||
|
, member_hook< value_type
|
||||||
test_list <typename testvalue_t::list_auto_member_hook_t::template
|
, typename value_type::list_auto_member_hook_t
|
||||||
value_traits<testvalue_t, &testvalue_t::list_auto_node_> >::test_all(data);
|
, &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;
|
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* [] )
|
int main( int, char* [] )
|
||||||
{
|
{
|
||||||
test_main_template<void*, false>()();
|
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<void*, true>()();
|
||||||
test_main_template<boost::intrusive::smart_ptr<void>, true>()();
|
test_main_template<smart_ptr<void>, true>()();
|
||||||
|
|
||||||
return boost::report_errors();
|
return boost::report_errors();
|
||||||
}
|
}
|
||||||
#include <boost/intrusive/detail/config_end.hpp>
|
#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.
|
// See http://www.boost.org/libs/intrusive for documentation.
|
||||||
//
|
//
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include <boost/intrusive/detail/config_begin.hpp>
|
#include <boost/intrusive/detail/config_begin.hpp>
|
||||||
#include <boost/intrusive/set.hpp>
|
#include <boost/intrusive/set.hpp>
|
||||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||||
@ -22,7 +23,6 @@
|
|||||||
#include "test_container.hpp"
|
#include "test_container.hpp"
|
||||||
|
|
||||||
using namespace boost::intrusive;
|
using namespace boost::intrusive;
|
||||||
|
|
||||||
template<class ValueTraits>
|
template<class ValueTraits>
|
||||||
struct test_multiset
|
struct test_multiset
|
||||||
{
|
{
|
||||||
@ -34,15 +34,17 @@ struct test_multiset
|
|||||||
static void test_find(std::vector<value_type>& values);
|
static void test_find(std::vector<value_type>& values);
|
||||||
static void test_impl();
|
static void test_impl();
|
||||||
static void test_clone(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>
|
template<class ValueTraits>
|
||||||
void test_multiset<ValueTraits>::test_all (std::vector<typename ValueTraits::value_type>& values)
|
void test_multiset<ValueTraits>::test_all (std::vector<typename ValueTraits::value_type>& values)
|
||||||
{
|
{
|
||||||
|
typedef typename ValueTraits::value_type value_type;
|
||||||
typedef multiset
|
typedef multiset
|
||||||
<ValueTraits
|
< value_type
|
||||||
,std::less<typename ValueTraits::value_type>
|
, value_traits<ValueTraits>
|
||||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
, constant_time_size<value_type::constant_time_size>
|
||||||
> multiset_type;
|
> multiset_type;
|
||||||
{
|
{
|
||||||
multiset_type testset(values.begin(), values.end());
|
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_find(values);
|
||||||
test_impl();
|
test_impl();
|
||||||
test_clone(values);
|
test_clone(values);
|
||||||
|
test_container_from_end(values);
|
||||||
}
|
}
|
||||||
|
|
||||||
//test case due to an error in tree implementation:
|
//test case due to an error in tree implementation:
|
||||||
template<class ValueTraits>
|
template<class ValueTraits>
|
||||||
void test_multiset<ValueTraits>::test_impl()
|
void test_multiset<ValueTraits>::test_impl()
|
||||||
{
|
{
|
||||||
typedef typename ValueTraits::value_type testvalue_t;
|
typedef typename ValueTraits::value_type value_type;
|
||||||
std::vector<testvalue_t> values (5);
|
std::vector<value_type> values (5);
|
||||||
for (int i = 0; i < 5; ++i)
|
for (int i = 0; i < 5; ++i)
|
||||||
values[i].value_ = i;
|
values[i].value_ = i;
|
||||||
|
typedef typename ValueTraits::value_type value_type;
|
||||||
typedef multiset
|
typedef multiset
|
||||||
<ValueTraits
|
< value_type
|
||||||
,std::less<typename ValueTraits::value_type>
|
, value_traits<ValueTraits>
|
||||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
, constant_time_size<value_type::constant_time_size>
|
||||||
> multiset_type;
|
> multiset_type;
|
||||||
|
|
||||||
multiset_type testset;
|
multiset_type testset;
|
||||||
for (int i = 0; i < 5; ++i)
|
for (int i = 0; i < 5; ++i)
|
||||||
testset.insert (values[i]);
|
testset.insert (values[i]);
|
||||||
@ -94,12 +99,13 @@ void test_multiset<ValueTraits>::test_impl()
|
|||||||
template<class ValueTraits>
|
template<class ValueTraits>
|
||||||
void test_multiset<ValueTraits>::test_sort(std::vector<typename ValueTraits::value_type>& values)
|
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
|
typedef multiset
|
||||||
<ValueTraits
|
< value_type
|
||||||
,std::less<typename ValueTraits::value_type>
|
, value_traits<ValueTraits>
|
||||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
, constant_time_size<value_type::constant_time_size>
|
||||||
> multiset_type;
|
> multiset_type;
|
||||||
|
|
||||||
multiset_type testset1 (values.begin(), values.end());
|
multiset_type testset1 (values.begin(), values.end());
|
||||||
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
||||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
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());
|
BOOST_TEST (testset1.empty());
|
||||||
|
|
||||||
typedef multiset
|
typedef multiset
|
||||||
<ValueTraits
|
<value_type
|
||||||
,even_odd
|
, compare<even_odd>
|
||||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
, value_traits<ValueTraits>
|
||||||
|
, constant_time_size<value_type::constant_time_size>
|
||||||
> multiset_type2;
|
> multiset_type2;
|
||||||
multiset_type2 testset2 (&values[0], &values[0] + 6);
|
multiset_type2 testset2 (&values[0], &values[0] + 6);
|
||||||
{ int init_values [] = { 5, 3, 1, 4, 2, 2 };
|
{ 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>
|
template<class ValueTraits>
|
||||||
void test_multiset<ValueTraits>::test_insert(std::vector<typename ValueTraits::value_type>& values)
|
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
|
typedef multiset
|
||||||
<ValueTraits
|
< value_type
|
||||||
,std::less<typename ValueTraits::value_type>
|
, value_traits<ValueTraits>
|
||||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
, size_type<std::size_t>
|
||||||
|
, constant_time_size<value_type::constant_time_size>
|
||||||
> multiset_type;
|
> multiset_type;
|
||||||
|
|
||||||
multiset_type testset;
|
multiset_type testset;
|
||||||
@ -147,6 +155,10 @@ void test_multiset<ValueTraits>::test_insert(std::vector<typename ValueTraits::v
|
|||||||
|
|
||||||
i = testset.iterator_to (values[2]);
|
i = testset.iterator_to (values[2]);
|
||||||
BOOST_TEST (&*i == &values[2]);
|
BOOST_TEST (&*i == &values[2]);
|
||||||
|
|
||||||
|
i = multiset_type::s_iterator_to (values[2]);
|
||||||
|
BOOST_TEST (&*i == &values[2]);
|
||||||
|
|
||||||
testset.erase(i);
|
testset.erase(i);
|
||||||
|
|
||||||
{ int init_values [] = { 1, 3, 5 };
|
{ int init_values [] = { 1, 3, 5 };
|
||||||
@ -157,11 +169,12 @@ void test_multiset<ValueTraits>::test_insert(std::vector<typename ValueTraits::v
|
|||||||
template<class ValueTraits>
|
template<class ValueTraits>
|
||||||
void test_multiset<ValueTraits>::test_swap(std::vector<typename ValueTraits::value_type>& values)
|
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
|
typedef multiset
|
||||||
<ValueTraits
|
< value_type
|
||||||
,std::less<typename ValueTraits::value_type>
|
, value_traits<ValueTraits>
|
||||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
, size_type<std::size_t>
|
||||||
|
, constant_time_size<value_type::constant_time_size>
|
||||||
> multiset_type;
|
> multiset_type;
|
||||||
multiset_type testset1 (&values[0], &values[0] + 2);
|
multiset_type testset1 (&values[0], &values[0] + 2);
|
||||||
multiset_type testset2;
|
multiset_type testset2;
|
||||||
@ -182,16 +195,17 @@ void test_multiset<ValueTraits>::test_swap(std::vector<typename ValueTraits::val
|
|||||||
template<class ValueTraits>
|
template<class ValueTraits>
|
||||||
void test_multiset<ValueTraits>::test_find(std::vector<typename ValueTraits::value_type>& values)
|
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
|
typedef multiset
|
||||||
<ValueTraits
|
< value_type
|
||||||
,std::less<typename ValueTraits::value_type>
|
, value_traits<ValueTraits>
|
||||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
, size_type<std::size_t>
|
||||||
|
, constant_time_size<value_type::constant_time_size>
|
||||||
> multiset_type;
|
> multiset_type;
|
||||||
multiset_type testset (values.begin(), values.end());
|
multiset_type testset (values.begin(), values.end());
|
||||||
typedef typename multiset_type::iterator iterator;
|
typedef typename multiset_type::iterator iterator;
|
||||||
|
|
||||||
testvalue_t cmp_val;
|
value_type cmp_val;
|
||||||
cmp_val.value_ = 2;
|
cmp_val.value_ = 2;
|
||||||
iterator i = testset.find (cmp_val);
|
iterator i = testset.find (cmp_val);
|
||||||
BOOST_TEST (i->value_ == 2);
|
BOOST_TEST (i->value_ == 2);
|
||||||
@ -210,20 +224,37 @@ template<class ValueTraits>
|
|||||||
void test_multiset<ValueTraits>
|
void test_multiset<ValueTraits>
|
||||||
::test_clone(std::vector<typename ValueTraits::value_type>& values)
|
::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
|
typedef multiset
|
||||||
<ValueTraits
|
< value_type
|
||||||
,std::less<typename ValueTraits::value_type>
|
, value_traits<ValueTraits>
|
||||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
, 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;
|
||||||
|
|
||||||
multiset_type testmultiset1 (&values[0], &values[0] + values.size());
|
multiset_type testmultiset (&values[0], &values[0] + values.size());
|
||||||
multiset_type testmultiset2;
|
BOOST_TEST (testmultiset == multiset_type::container_from_end_iterator(testmultiset.end()));
|
||||||
|
BOOST_TEST (testmultiset == multiset_type::container_from_end_iterator(testmultiset.cend()));
|
||||||
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());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class VoidPointer, bool constant_time_size>
|
template<class VoidPointer, bool constant_time_size>
|
||||||
@ -232,18 +263,25 @@ class test_main_template
|
|||||||
public:
|
public:
|
||||||
int operator()()
|
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 };
|
static const int random_init[6] = { 3, 2, 4, 1, 5, 2 };
|
||||||
std::vector<testvalue<VoidPointer, constant_time_size> > data (6);
|
std::vector<testvalue<VoidPointer, constant_time_size> > data (6);
|
||||||
for (int i = 0; i < 6; ++i)
|
for (int i = 0; i < 6; ++i)
|
||||||
data[i].value_ = random_init[i];
|
data[i].value_ = random_init[i];
|
||||||
|
|
||||||
test_multiset <typename testvalue_t::set_base_hook_t::template
|
test_multiset < typename detail::get_base_value_traits
|
||||||
value_traits<testvalue_t> >::test_all(data);
|
< value_type
|
||||||
|
, typename value_type::set_base_hook_t
|
||||||
test_multiset <typename testvalue_t::set_member_hook_t::template
|
>::type
|
||||||
value_traits<testvalue_t, &testvalue_t::set_node_> >::test_all(data);
|
>::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;
|
return 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -254,55 +292,73 @@ class test_main_template<VoidPointer, false>
|
|||||||
public:
|
public:
|
||||||
int operator()()
|
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 };
|
static const int random_init[6] = { 3, 2, 4, 1, 5, 2 };
|
||||||
std::vector<testvalue<VoidPointer, false> > data (6);
|
std::vector<testvalue<VoidPointer, false> > data (6);
|
||||||
for (int i = 0; i < 6; ++i)
|
for (int i = 0; i < 6; ++i)
|
||||||
data[i].value_ = random_init[i];
|
data[i].value_ = random_init[i];
|
||||||
|
|
||||||
test_multiset <typename testvalue_t::set_base_hook_t::template
|
test_multiset < typename detail::get_base_value_traits
|
||||||
value_traits<testvalue_t> >::test_all(data);
|
< value_type
|
||||||
|
, typename value_type::set_base_hook_t
|
||||||
|
>::type
|
||||||
|
>::test_all(data);
|
||||||
|
|
||||||
test_multiset <typename testvalue_t::set_member_hook_t::template
|
test_multiset < typename detail::get_member_value_traits
|
||||||
value_traits<testvalue_t, &testvalue_t::set_node_> >::test_all(data);
|
< 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
|
test_multiset < typename detail::get_base_value_traits
|
||||||
value_traits<testvalue_t> >::test_all(data);
|
< 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
|
test_multiset < typename detail::get_member_value_traits
|
||||||
value_traits<testvalue_t, &testvalue_t::set_auto_node_> >::test_all(data);
|
< 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;
|
return 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
/*
|
|
||||||
//Explicit instantiations of non-counted classes
|
//Explicit instantiations of non-counted classes
|
||||||
template class multiset
|
//template class multiset
|
||||||
<set_base_raw, std::less<set_base_raw::value_type>, false>;
|
// <set_base_raw, std::less<set_base_raw::value_type>, false>;
|
||||||
template class multiset
|
//template class multiset
|
||||||
<set_member_raw, std::less<set_member_raw::value_type>, false>;
|
// <set_member_raw, std::less<set_member_raw::value_type>, false>;
|
||||||
template class multiset
|
//template class multiset
|
||||||
<set_auto_base_raw, std::less<set_auto_base_raw::value_type>, false>;
|
// <set_auto_base_raw, std::less<set_auto_base_raw::value_type>, false>;
|
||||||
template class multiset
|
//template class multiset
|
||||||
<set_auto_member_raw, std::less<set_auto_member_raw::value_type>, false>;
|
// <set_auto_member_raw, std::less<set_auto_member_raw::value_type>, false>;
|
||||||
template class multiset
|
//template class multiset
|
||||||
<set_base_smart, std::less<set_base_smart::value_type>, false>;
|
// <set_base_smart, std::less<set_base_smart::value_type>, false>;
|
||||||
template class multiset
|
//template class multiset
|
||||||
<set_member_smart, std::less<set_member_smart::value_type>, false>;
|
// <set_member_smart, std::less<set_member_smart::value_type>, false>;
|
||||||
template class multiset
|
//template class multiset
|
||||||
<set_auto_base_smart, std::less<set_auto_base_smart::value_type>, false>;
|
// <set_auto_base_smart, std::less<set_auto_base_smart::value_type>, false>;
|
||||||
template class multiset
|
//template class multiset
|
||||||
<set_auto_member_smart, std::less<set_auto_member_smart::value_type>, false>;
|
// <set_auto_member_smart, std::less<set_auto_member_smart::value_type>, false>;
|
||||||
|
|
||||||
//Explicit instantiation of counted classes
|
//Explicit instantiation of counted classes
|
||||||
template class multiset
|
//template class multiset
|
||||||
<set_base_raw_t, std::less<set_base_raw_t::value_type>, true>;
|
// <set_base_raw_t, std::less<set_base_raw_t::value_type>, true>;
|
||||||
template class multiset
|
//template class multiset
|
||||||
<set_member_raw_t, std::less<set_member_raw_t::value_type>, true>;
|
// <set_member_raw_t, std::less<set_member_raw_t::value_type>, true>;
|
||||||
template class multiset
|
//template class multiset
|
||||||
<set_base_smart_t, std::less<set_base_smart_t::value_type>, true>;
|
// <set_base_smart_t, std::less<set_base_smart_t::value_type>, true>;
|
||||||
template class multiset
|
//template class multiset
|
||||||
<set_member_smart_t, std::less<set_member_smart_t::value_type>, true>;
|
// <set_member_smart_t, std::less<set_member_smart_t::value_type>, true>;
|
||||||
*/
|
|
||||||
int main( int, char* [] )
|
int main( int, char* [] )
|
||||||
{
|
{
|
||||||
test_main_template<void*, false>()();
|
test_main_template<void*, false>()();
|
||||||
@ -311,5 +367,3 @@ int main( int, char* [] )
|
|||||||
test_main_template<smart_ptr<void>, true>()();
|
test_main_template<smart_ptr<void>, true>()();
|
||||||
return boost::report_errors();
|
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_find(std::vector<value_type>& values);
|
||||||
static void test_impl();
|
static void test_impl();
|
||||||
static void test_clone(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>
|
template<class ValueTraits>
|
||||||
void test_set<ValueTraits>::test_all(std::vector<typename ValueTraits::value_type>& values)
|
void test_set<ValueTraits>::test_all(std::vector<typename ValueTraits::value_type>& values)
|
||||||
{
|
{
|
||||||
typedef boost::intrusive::set
|
typedef typename ValueTraits::value_type value_type;
|
||||||
<ValueTraits
|
typedef set
|
||||||
,std::less<typename ValueTraits::value_type>
|
< value_type
|
||||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
, value_traits<ValueTraits>
|
||||||
|
, constant_time_size<value_type::constant_time_size>
|
||||||
> set_type;
|
> set_type;
|
||||||
{
|
{
|
||||||
set_type testset(values.begin(), values.end());
|
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_find(values);
|
||||||
test_impl();
|
test_impl();
|
||||||
test_clone(values);
|
test_clone(values);
|
||||||
|
test_container_from_end(values);
|
||||||
}
|
}
|
||||||
|
|
||||||
//test case due to an error in tree implementation:
|
//test case due to an error in tree implementation:
|
||||||
template<class ValueTraits>
|
template<class ValueTraits>
|
||||||
void test_set<ValueTraits>::test_impl()
|
void test_set<ValueTraits>::test_impl()
|
||||||
{
|
{
|
||||||
typedef typename ValueTraits::value_type testvalue_t;
|
typedef typename ValueTraits::value_type value_type;
|
||||||
std::vector<testvalue_t> values (5);
|
std::vector<value_type> values (5);
|
||||||
for (int i = 0; i < 5; ++i)
|
for (int i = 0; i < 5; ++i)
|
||||||
values[i].value_ = i;
|
values[i].value_ = i;
|
||||||
|
|
||||||
typedef boost::intrusive::set
|
typedef typename ValueTraits::value_type value_type;
|
||||||
<ValueTraits
|
typedef set
|
||||||
,std::less<typename ValueTraits::value_type>
|
< value_type
|
||||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
, value_traits<ValueTraits>
|
||||||
|
, constant_time_size<value_type::constant_time_size>
|
||||||
> set_type;
|
> set_type;
|
||||||
set_type testset;
|
set_type testset;
|
||||||
for (int i = 0; i < 5; ++i)
|
for (int i = 0; i < 5; ++i)
|
||||||
@ -95,11 +99,11 @@ void test_set<ValueTraits>::test_impl()
|
|||||||
template<class ValueTraits>
|
template<class ValueTraits>
|
||||||
void test_set<ValueTraits>::test_sort(std::vector<typename ValueTraits::value_type>& values)
|
void test_set<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 boost::intrusive::set
|
typedef set
|
||||||
<ValueTraits
|
< value_type
|
||||||
,std::less<typename ValueTraits::value_type>
|
, value_traits<ValueTraits>
|
||||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
, constant_time_size<value_type::constant_time_size>
|
||||||
> set_type;
|
> set_type;
|
||||||
set_type testset1 (values.begin(), values.end());
|
set_type testset1 (values.begin(), values.end());
|
||||||
{ int init_values [] = { 1, 2, 3, 4, 5 };
|
{ 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();
|
testset1.clear();
|
||||||
BOOST_TEST (testset1.empty());
|
BOOST_TEST (testset1.empty());
|
||||||
|
|
||||||
typedef boost::intrusive::set
|
typedef typename ValueTraits::value_type value_type;
|
||||||
<ValueTraits
|
typedef set
|
||||||
,even_odd
|
< value_type
|
||||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
, compare<even_odd>
|
||||||
|
, value_traits<ValueTraits>
|
||||||
|
, constant_time_size<value_type::constant_time_size>
|
||||||
> set_type2;
|
> set_type2;
|
||||||
set_type2 testset2 (&values[0], &values[0] + 6);
|
set_type2 testset2 (&values[0], &values[0] + 6);
|
||||||
{ int init_values [] = { 5, 3, 1, 4, 2 };
|
{ 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);
|
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>
|
template<class ValueTraits>
|
||||||
void test_set<ValueTraits>::test_insert(std::vector<typename ValueTraits::value_type>& values)
|
void test_set<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 boost::intrusive::set
|
typedef set
|
||||||
<ValueTraits
|
< value_type
|
||||||
,std::less<typename ValueTraits::value_type>
|
, value_traits<ValueTraits>
|
||||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
, constant_time_size<value_type::constant_time_size>
|
||||||
> set_type;
|
> set_type;
|
||||||
set_type testset;
|
set_type testset;
|
||||||
testset.insert(&values[0] + 2, &values[0] + 5);
|
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]);
|
i = testset.iterator_to (values[2]);
|
||||||
BOOST_TEST (&*i == &values[2]);
|
BOOST_TEST (&*i == &values[2]);
|
||||||
|
|
||||||
|
i = set_type::s_iterator_to(values[2]);
|
||||||
|
BOOST_TEST (&*i == &values[2]);
|
||||||
|
|
||||||
testset.erase (i);
|
testset.erase (i);
|
||||||
{ int init_values [] = { 1, 3, 5 };
|
{ int init_values [] = { 1, 3, 5 };
|
||||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset.begin() ); }
|
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>
|
template<class ValueTraits>
|
||||||
void test_set<ValueTraits>::test_swap(std::vector<typename ValueTraits::value_type>& values)
|
void test_set<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 boost::intrusive::set
|
typedef set
|
||||||
<ValueTraits
|
< value_type
|
||||||
,std::less<typename ValueTraits::value_type>
|
, value_traits<ValueTraits>
|
||||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
, constant_time_size<value_type::constant_time_size>
|
||||||
> set_type;
|
> set_type;
|
||||||
set_type testset1 (&values[0], &values[0] + 2);
|
set_type testset1 (&values[0], &values[0] + 2);
|
||||||
set_type testset2;
|
set_type testset2;
|
||||||
@ -185,16 +194,16 @@ void test_set<ValueTraits>::test_swap(std::vector<typename ValueTraits::value_ty
|
|||||||
template<class ValueTraits>
|
template<class ValueTraits>
|
||||||
void test_set<ValueTraits>::test_find(std::vector<typename ValueTraits::value_type>& values)
|
void test_set<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 boost::intrusive::set
|
typedef set
|
||||||
<ValueTraits
|
< value_type
|
||||||
,std::less<typename ValueTraits::value_type>
|
, value_traits<ValueTraits>
|
||||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
, constant_time_size<value_type::constant_time_size>
|
||||||
> set_type;
|
> set_type;
|
||||||
set_type testset (values.begin(), values.end());
|
set_type testset (values.begin(), values.end());
|
||||||
typedef typename set_type::iterator iterator;
|
typedef typename set_type::iterator iterator;
|
||||||
|
|
||||||
testvalue_t cmp_val;
|
value_type cmp_val;
|
||||||
cmp_val.value_ = 2;
|
cmp_val.value_ = 2;
|
||||||
iterator i = testset.find (cmp_val);
|
iterator i = testset.find (cmp_val);
|
||||||
BOOST_TEST (i->value_ == 2);
|
BOOST_TEST (i->value_ == 2);
|
||||||
@ -213,20 +222,35 @@ template<class ValueTraits>
|
|||||||
void test_set<ValueTraits>
|
void test_set<ValueTraits>
|
||||||
::test_clone(std::vector<typename ValueTraits::value_type>& values)
|
::test_clone(std::vector<typename ValueTraits::value_type>& values)
|
||||||
{
|
{
|
||||||
typedef typename ValueTraits::value_type testvalue_t;
|
typedef typename ValueTraits::value_type value_type;
|
||||||
typedef boost::intrusive::set
|
typedef set
|
||||||
<ValueTraits
|
< value_type
|
||||||
,std::less<typename ValueTraits::value_type>
|
, value_traits<ValueTraits>
|
||||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
, constant_time_size<value_type::constant_time_size>
|
||||||
> set_type;
|
> set_type;
|
||||||
|
|
||||||
set_type testset1 (&values[0], &values[0] + values.size());
|
set_type testset1 (&values[0], &values[0] + values.size());
|
||||||
set_type testset2;
|
set_type testset2;
|
||||||
|
|
||||||
testset2.clone_from(testset1, test::new_cloner(), test::delete_disposer());
|
testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
|
||||||
BOOST_TEST (testset2 == testset1);
|
BOOST_TEST (testset2 == testset1);
|
||||||
testset2.clear_and_dispose(test::delete_disposer());
|
testset2.clear_and_dispose(test::delete_disposer<value_type>());
|
||||||
BOOST_TEST (testset2.empty());
|
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>
|
template<class VoidPointer, bool constant_time_size>
|
||||||
@ -235,18 +259,25 @@ class test_main_template
|
|||||||
public:
|
public:
|
||||||
int operator()()
|
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 };
|
static const int random_init[6] = { 3, 2, 4, 1, 5, 2 };
|
||||||
std::vector<testvalue<VoidPointer, constant_time_size> > data (6);
|
std::vector<testvalue<VoidPointer, constant_time_size> > data (6);
|
||||||
for (int i = 0; i < 6; ++i)
|
for (int i = 0; i < 6; ++i)
|
||||||
data[i].value_ = random_init[i];
|
data[i].value_ = random_init[i];
|
||||||
|
|
||||||
test_set <typename testvalue_t::set_base_hook_t::template
|
test_set < typename detail::get_base_value_traits
|
||||||
value_traits<testvalue_t> >::test_all(data);
|
< value_type
|
||||||
|
, typename value_type::set_base_hook_t
|
||||||
test_set <typename testvalue_t::set_member_hook_t::template
|
>::type
|
||||||
value_traits<testvalue_t, &testvalue_t::set_node_> >::test_all(data);
|
>::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;
|
return 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -257,61 +288,53 @@ class test_main_template<VoidPointer, false>
|
|||||||
public:
|
public:
|
||||||
int operator()()
|
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 };
|
static const int random_init[6] = { 3, 2, 4, 1, 5, 2 };
|
||||||
std::vector<testvalue<VoidPointer, false> > data (6);
|
std::vector<testvalue<VoidPointer, false> > data (6);
|
||||||
for (int i = 0; i < 6; ++i)
|
for (int i = 0; i < 6; ++i)
|
||||||
data[i].value_ = random_init[i];
|
data[i].value_ = random_init[i];
|
||||||
|
|
||||||
test_set <typename testvalue_t::set_base_hook_t::template
|
test_set < typename detail::get_base_value_traits
|
||||||
value_traits<testvalue_t> >::test_all(data);
|
< value_type
|
||||||
|
, typename value_type::set_base_hook_t
|
||||||
|
>::type
|
||||||
|
>::test_all(data);
|
||||||
|
|
||||||
test_set <typename testvalue_t::set_member_hook_t::template
|
test_set < typename detail::get_member_value_traits
|
||||||
value_traits<testvalue_t, &testvalue_t::set_node_> >::test_all(data);
|
< 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
|
test_set < typename detail::get_base_value_traits
|
||||||
value_traits<testvalue_t> >::test_all(data);
|
< 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;
|
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* [] )
|
int main( int, char* [] )
|
||||||
{
|
{
|
||||||
|
|
||||||
test_main_template<void*, false>()();
|
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<void*, true>()();
|
||||||
test_main_template<boost::intrusive::smart_ptr<void>, true>()();
|
test_main_template<smart_ptr<void>, true>()();
|
||||||
return boost::report_errors();
|
return boost::report_errors();
|
||||||
}
|
}
|
||||||
#include <boost/intrusive/detail/config_end.hpp>
|
#include <boost/intrusive/detail/config_end.hpp>
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
// See http://www.boost.org/libs/intrusive for documentation.
|
// See http://www.boost.org/libs/intrusive for documentation.
|
||||||
//
|
//
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include <boost/intrusive/detail/config_begin.hpp>
|
#include <boost/intrusive/detail/config_begin.hpp>
|
||||||
#include <boost/intrusive/slist.hpp>
|
#include <boost/intrusive/slist.hpp>
|
||||||
#include <boost/intrusive/detail/pointer_to_other.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_swap(std::vector<value_type>& values);
|
||||||
static void test_slow_insert (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_clone (std::vector<value_type>& values);
|
||||||
|
static void test_container_from_end(std::vector<value_type> &values);
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class ValueTraits>
|
template<class ValueTraits>
|
||||||
void test_slist<ValueTraits>
|
void test_slist<ValueTraits>
|
||||||
::test_all (std::vector<typename ValueTraits::value_type>& values)
|
::test_all (std::vector<typename ValueTraits::value_type>& values)
|
||||||
{
|
{
|
||||||
typedef boost::intrusive::slist
|
typedef typename ValueTraits::value_type value_type;
|
||||||
<ValueTraits
|
typedef slist
|
||||||
,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>
|
||||||
> list_type;
|
> list_type;
|
||||||
{
|
{
|
||||||
list_type list(values.begin(), values.end());
|
list_type list(values.begin(), values.end());
|
||||||
@ -61,6 +66,7 @@ void test_slist<ValueTraits>
|
|||||||
test_slow_insert (values);
|
test_slow_insert (values);
|
||||||
test_swap(values);
|
test_swap(values);
|
||||||
test_clone(values);
|
test_clone(values);
|
||||||
|
test_container_from_end(values);
|
||||||
}
|
}
|
||||||
|
|
||||||
//test: push_front, pop_front, front, size, empty:
|
//test: push_front, pop_front, front, size, empty:
|
||||||
@ -68,9 +74,12 @@ template<class ValueTraits>
|
|||||||
void test_slist<ValueTraits>
|
void test_slist<ValueTraits>
|
||||||
::test_front_back (std::vector<typename ValueTraits::value_type>& values)
|
::test_front_back (std::vector<typename ValueTraits::value_type>& values)
|
||||||
{
|
{
|
||||||
typedef boost::intrusive::slist
|
typedef typename ValueTraits::value_type value_type;
|
||||||
<ValueTraits
|
typedef slist
|
||||||
,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>
|
||||||
> list_type;
|
> list_type;
|
||||||
list_type testlist;
|
list_type testlist;
|
||||||
BOOST_TEST (testlist.empty());
|
BOOST_TEST (testlist.empty());
|
||||||
@ -96,10 +105,12 @@ template<class ValueTraits>
|
|||||||
void test_slist<ValueTraits>
|
void test_slist<ValueTraits>
|
||||||
::test_merge (std::vector<typename ValueTraits::value_type>& values)
|
::test_merge (std::vector<typename ValueTraits::value_type>& values)
|
||||||
{
|
{
|
||||||
typedef typename ValueTraits::value_type testvalue_t;
|
typedef typename ValueTraits::value_type value_type;
|
||||||
typedef boost::intrusive::slist
|
typedef slist
|
||||||
<ValueTraits
|
< value_type
|
||||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
, value_traits<ValueTraits>
|
||||||
|
, size_type<std::size_t>
|
||||||
|
, constant_time_size<value_type::constant_time_size>
|
||||||
> list_type;
|
> list_type;
|
||||||
list_type testlist1, testlist2;
|
list_type testlist1, testlist2;
|
||||||
testlist1.push_front (values[0]);
|
testlist1.push_front (values[0]);
|
||||||
@ -117,10 +128,12 @@ template<class ValueTraits>
|
|||||||
void test_slist<ValueTraits>
|
void test_slist<ValueTraits>
|
||||||
::test_sort(std::vector<typename ValueTraits::value_type>& values)
|
::test_sort(std::vector<typename ValueTraits::value_type>& values)
|
||||||
{
|
{
|
||||||
typedef typename ValueTraits::value_type testvalue_t;
|
typedef typename ValueTraits::value_type value_type;
|
||||||
typedef boost::intrusive::slist
|
typedef slist
|
||||||
<ValueTraits
|
< value_type
|
||||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
, value_traits<ValueTraits>
|
||||||
|
, size_type<std::size_t>
|
||||||
|
, constant_time_size<value_type::constant_time_size>
|
||||||
> list_type;
|
> list_type;
|
||||||
list_type testlist (values.begin(), values.end());
|
list_type testlist (values.begin(), values.end());
|
||||||
|
|
||||||
@ -136,15 +149,17 @@ void test_slist<ValueTraits>
|
|||||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist.begin() ); }
|
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>
|
template<class ValueTraits>
|
||||||
void test_slist<ValueTraits>
|
void test_slist<ValueTraits>
|
||||||
::test_insert(std::vector<typename ValueTraits::value_type>& values)
|
::test_insert(std::vector<typename ValueTraits::value_type>& values)
|
||||||
{
|
{
|
||||||
typedef typename ValueTraits::value_type testvalue_t;
|
typedef typename ValueTraits::value_type value_type;
|
||||||
typedef boost::intrusive::slist
|
typedef slist
|
||||||
<ValueTraits
|
< value_type
|
||||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
, value_traits<ValueTraits>
|
||||||
|
, size_type<std::size_t>
|
||||||
|
, constant_time_size<value_type::constant_time_size>
|
||||||
> list_type;
|
> list_type;
|
||||||
list_type testlist;
|
list_type testlist;
|
||||||
testlist.assign (&values[0] + 2, &values[0] + 5);
|
testlist.assign (&values[0] + 2, &values[0] + 5);
|
||||||
@ -162,6 +177,8 @@ void test_slist<ValueTraits>
|
|||||||
|
|
||||||
i = testlist.iterator_to (values[4]);
|
i = testlist.iterator_to (values[4]);
|
||||||
BOOST_TEST (&*i == &values[4]);
|
BOOST_TEST (&*i == &values[4]);
|
||||||
|
i = list_type::s_iterator_to (values[4]);
|
||||||
|
BOOST_TEST (&*i == &values[4]);
|
||||||
i = testlist.previous (i);
|
i = testlist.previous (i);
|
||||||
BOOST_TEST (&*i == &values[0]);
|
BOOST_TEST (&*i == &values[0]);
|
||||||
|
|
||||||
@ -171,15 +188,17 @@ void test_slist<ValueTraits>
|
|||||||
TEST_INTRUSIVE_SEQUENCE( init_values, const_testlist.begin() ); }
|
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>
|
template<class ValueTraits>
|
||||||
void test_slist<ValueTraits>
|
void test_slist<ValueTraits>
|
||||||
::test_slow_insert (std::vector<typename ValueTraits::value_type>& values)
|
::test_slow_insert (std::vector<typename ValueTraits::value_type>& values)
|
||||||
{
|
{
|
||||||
typedef typename ValueTraits::value_type testvalue_t;
|
typedef typename ValueTraits::value_type value_type;
|
||||||
typedef boost::intrusive::slist
|
typedef slist
|
||||||
<ValueTraits
|
< value_type
|
||||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
, value_traits<ValueTraits>
|
||||||
|
, size_type<std::size_t>
|
||||||
|
, constant_time_size<value_type::constant_time_size>
|
||||||
> list_type;
|
> list_type;
|
||||||
list_type testlist;
|
list_type testlist;
|
||||||
testlist.push_front (values[4]);
|
testlist.push_front (values[4]);
|
||||||
@ -199,6 +218,9 @@ void test_slist<ValueTraits>
|
|||||||
i = testlist.iterator_to (values[4]);
|
i = testlist.iterator_to (values[4]);
|
||||||
BOOST_TEST (&*i == &values[4]);
|
BOOST_TEST (&*i == &values[4]);
|
||||||
|
|
||||||
|
i = list_type::s_iterator_to (values[4]);
|
||||||
|
BOOST_TEST (&*i == &values[4]);
|
||||||
|
|
||||||
i = testlist.erase (i);
|
i = testlist.erase (i);
|
||||||
BOOST_TEST (i == testlist.end());
|
BOOST_TEST (i == testlist.end());
|
||||||
|
|
||||||
@ -214,10 +236,12 @@ template<class ValueTraits>
|
|||||||
void test_slist<ValueTraits>
|
void test_slist<ValueTraits>
|
||||||
::test_shift(std::vector<typename ValueTraits::value_type>& values)
|
::test_shift(std::vector<typename ValueTraits::value_type>& values)
|
||||||
{
|
{
|
||||||
typedef typename ValueTraits::value_type testvalue_t;
|
typedef typename ValueTraits::value_type value_type;
|
||||||
typedef boost::intrusive::slist
|
typedef slist
|
||||||
<ValueTraits
|
< value_type
|
||||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
, value_traits<ValueTraits>
|
||||||
|
, size_type<std::size_t>
|
||||||
|
, constant_time_size<value_type::constant_time_size>
|
||||||
> list_type;
|
> list_type;
|
||||||
list_type testlist;
|
list_type testlist;
|
||||||
|
|
||||||
@ -254,10 +278,12 @@ template<class ValueTraits>
|
|||||||
void test_slist<ValueTraits>
|
void test_slist<ValueTraits>
|
||||||
::test_swap(std::vector<typename ValueTraits::value_type>& values)
|
::test_swap(std::vector<typename ValueTraits::value_type>& values)
|
||||||
{
|
{
|
||||||
typedef typename ValueTraits::value_type testvalue_t;
|
typedef typename ValueTraits::value_type value_type;
|
||||||
typedef boost::intrusive::slist
|
typedef slist
|
||||||
<ValueTraits
|
< value_type
|
||||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
, value_traits<ValueTraits>
|
||||||
|
, size_type<std::size_t>
|
||||||
|
, constant_time_size<value_type::constant_time_size>
|
||||||
> list_type;
|
> list_type;
|
||||||
{
|
{
|
||||||
list_type testlist1 (&values[0], &values[0] + 2);
|
list_type testlist1 (&values[0], &values[0] + 2);
|
||||||
@ -306,37 +332,63 @@ template<class ValueTraits>
|
|||||||
void test_slist<ValueTraits>
|
void test_slist<ValueTraits>
|
||||||
::test_clone(std::vector<typename ValueTraits::value_type>& values)
|
::test_clone(std::vector<typename ValueTraits::value_type>& values)
|
||||||
{
|
{
|
||||||
typedef typename ValueTraits::value_type testvalue_t;
|
typedef typename ValueTraits::value_type value_type;
|
||||||
typedef boost::intrusive::slist
|
typedef slist
|
||||||
<ValueTraits
|
< value_type
|
||||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
, value_traits<ValueTraits>
|
||||||
|
, size_type<std::size_t>
|
||||||
|
, constant_time_size<value_type::constant_time_size>
|
||||||
> list_type;
|
> list_type;
|
||||||
|
|
||||||
list_type testlist1 (&values[0], &values[0] + values.size());
|
list_type testlist1 (&values[0], &values[0] + values.size());
|
||||||
list_type testlist2;
|
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);
|
BOOST_TEST (testlist2 == testlist1);
|
||||||
testlist2.clear_and_dispose(test::delete_disposer());
|
testlist2.clear_and_dispose(test::delete_disposer<value_type>());
|
||||||
BOOST_TEST (testlist2.empty());
|
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>
|
template<class VoidPointer, bool constant_time_size>
|
||||||
class test_main_template
|
class test_main_template
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
int operator()()
|
int operator()()
|
||||||
{
|
{
|
||||||
typedef testvalue<VoidPointer, constant_time_size> testvalue_t;
|
typedef testvalue<VoidPointer, constant_time_size> value_type;
|
||||||
std::vector<testvalue_t> data (5);
|
std::vector<value_type> data (5);
|
||||||
for (int i = 0; i < 5; ++i)
|
for (int i = 0; i < 5; ++i)
|
||||||
data[i].value_ = i + 1;
|
data[i].value_ = i + 1;
|
||||||
|
|
||||||
test_slist <typename testvalue_t::slist_base_hook_t::template
|
test_slist < typename detail::get_base_value_traits
|
||||||
value_traits<testvalue_t> >::test_all(data);
|
< value_type
|
||||||
|
, typename value_type::slist_base_hook_t
|
||||||
test_slist <typename testvalue_t::slist_member_hook_t::template
|
>::type
|
||||||
value_traits<testvalue_t, &testvalue_t::slist_node_> >::test_all(data);
|
>::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;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -348,48 +400,50 @@ class test_main_template<VoidPointer, false>
|
|||||||
public:
|
public:
|
||||||
int operator()()
|
int operator()()
|
||||||
{
|
{
|
||||||
typedef testvalue<VoidPointer, false> testvalue_t;
|
typedef testvalue<VoidPointer, false> value_type;
|
||||||
std::vector<testvalue_t> data (5);
|
std::vector<value_type> data (5);
|
||||||
for (int i = 0; i < 5; ++i)
|
for (int i = 0; i < 5; ++i)
|
||||||
data[i].value_ = i + 1;
|
data[i].value_ = i + 1;
|
||||||
|
|
||||||
test_slist <typename testvalue_t::slist_base_hook_t::template
|
test_slist < typename detail::get_base_value_traits
|
||||||
value_traits<testvalue_t> >::test_all(data);
|
< value_type
|
||||||
|
, typename value_type::slist_base_hook_t
|
||||||
|
>::type
|
||||||
|
>::test_all(data);
|
||||||
|
|
||||||
test_slist <typename testvalue_t::slist_member_hook_t::template
|
test_slist < typename detail::get_member_value_traits
|
||||||
value_traits<testvalue_t, &testvalue_t::slist_node_> >::test_all(data);
|
< 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
|
test_slist < typename detail::get_base_value_traits
|
||||||
value_traits<testvalue_t> >::test_all(data);
|
< 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
|
test_slist < typename detail::get_member_value_traits
|
||||||
value_traits<testvalue_t, &testvalue_t::slist_auto_node_> >::test_all(data);
|
< 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;
|
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* [])
|
int main(int, char* [])
|
||||||
{
|
{
|
||||||
test_main_template<void*, false>()();
|
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<void*, true>()();
|
||||||
test_main_template<boost::intrusive::smart_ptr<void>, true>()();
|
test_main_template<smart_ptr<void>, true>()();
|
||||||
return boost::report_errors();
|
return boost::report_errors();
|
||||||
}
|
}
|
||||||
#include <boost/intrusive/detail/config_end.hpp>
|
#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>
|
template<class ValueTraits>
|
||||||
void test_unordered_multiset<ValueTraits>::test_all (std::vector<typename ValueTraits::value_type>& values)
|
void test_unordered_multiset<ValueTraits>::test_all (std::vector<typename ValueTraits::value_type>& values)
|
||||||
{
|
{
|
||||||
typedef boost::intrusive::unordered_multiset
|
typedef typename ValueTraits::value_type value_type;
|
||||||
<ValueTraits
|
typedef unordered_multiset
|
||||||
,boost::hash<typename ValueTraits::value_type>
|
<value_type
|
||||||
,std::equal_to<typename ValueTraits::value_type>
|
, value_traits<ValueTraits>
|
||||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
, constant_time_size<value_type::constant_time_size>
|
||||||
> unordered_multiset_type;
|
> unordered_multiset_type;
|
||||||
{
|
{
|
||||||
|
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
||||||
typename unordered_multiset_type::bucket_type buckets [BucketSize];
|
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());
|
testset.insert(values.begin(), values.end());
|
||||||
test::test_container(testset);
|
test::test_container(testset);
|
||||||
testset.clear();
|
testset.clear();
|
||||||
@ -78,18 +79,20 @@ void test_unordered_multiset<ValueTraits>::test_all (std::vector<typename ValueT
|
|||||||
template<class ValueTraits>
|
template<class ValueTraits>
|
||||||
void test_unordered_multiset<ValueTraits>::test_impl()
|
void test_unordered_multiset<ValueTraits>::test_impl()
|
||||||
{
|
{
|
||||||
typedef typename ValueTraits::value_type testvalue_t;
|
typedef typename ValueTraits::value_type value_type;
|
||||||
std::vector<testvalue_t> values (5);
|
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)
|
for (int i = 0; i < 5; ++i)
|
||||||
values[i].value_ = 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];
|
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)
|
for (int i = 0; i < 5; ++i)
|
||||||
testset.insert (values[i]);
|
testset.insert (values[i]);
|
||||||
@ -106,15 +109,16 @@ void test_unordered_multiset<ValueTraits>::test_impl()
|
|||||||
template<class ValueTraits>
|
template<class ValueTraits>
|
||||||
void test_unordered_multiset<ValueTraits>::test_sort(std::vector<typename ValueTraits::value_type>& values)
|
void test_unordered_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 boost::intrusive::unordered_multiset
|
typedef unordered_multiset
|
||||||
<ValueTraits
|
<value_type
|
||||||
,boost::hash<typename ValueTraits::value_type>
|
, value_traits<ValueTraits>
|
||||||
,std::equal_to<typename ValueTraits::value_type>
|
, constant_time_size<value_type::constant_time_size>
|
||||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
|
||||||
> unordered_multiset_type;
|
> unordered_multiset_type;
|
||||||
|
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
||||||
|
|
||||||
typename unordered_multiset_type::bucket_type buckets [BucketSize];
|
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 };
|
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
||||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
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>
|
template<class ValueTraits>
|
||||||
void test_unordered_multiset<ValueTraits>::test_insert(std::vector<typename ValueTraits::value_type>& values)
|
void test_unordered_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 boost::intrusive::unordered_multiset
|
typedef unordered_multiset
|
||||||
<ValueTraits
|
<value_type
|
||||||
,boost::hash<typename ValueTraits::value_type>
|
, value_traits<ValueTraits>
|
||||||
,std::equal_to<typename ValueTraits::value_type>
|
, constant_time_size<value_type::constant_time_size>
|
||||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
|
||||||
> unordered_multiset_type;
|
> unordered_multiset_type;
|
||||||
|
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
||||||
|
|
||||||
typename unordered_multiset_type::bucket_type buckets [BucketSize];
|
typename unordered_multiset_type::bucket_type buckets [BucketSize];
|
||||||
unordered_multiset_type testset(buckets, BucketSize);
|
unordered_multiset_type testset(bucket_traits(buckets, BucketSize));
|
||||||
typedef typename unordered_multiset_type::value_type value_type;
|
|
||||||
|
|
||||||
testset.insert(&values[0] + 2, &values[0] + 5);
|
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
|
//Now with a single bucket
|
||||||
typename unordered_multiset_type::bucket_type single_bucket[1];
|
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());
|
testset2.insert(&values[0], &values[0] + values.size());
|
||||||
BOOST_TEST (testset2.erase(5) == 1);
|
BOOST_TEST (testset2.erase(5) == 1);
|
||||||
BOOST_TEST (testset2.erase(2) == 2);
|
BOOST_TEST (testset2.erase(2) == 2);
|
||||||
@ -184,18 +188,18 @@ void test_unordered_multiset<ValueTraits>::test_insert(std::vector<typename Valu
|
|||||||
template<class ValueTraits>
|
template<class ValueTraits>
|
||||||
void test_unordered_multiset<ValueTraits>::test_swap(std::vector<typename ValueTraits::value_type>& values)
|
void test_unordered_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 boost::intrusive::unordered_multiset
|
typedef unordered_multiset
|
||||||
<ValueTraits
|
<value_type
|
||||||
,boost::hash<typename ValueTraits::value_type>
|
, value_traits<ValueTraits>
|
||||||
,std::equal_to<typename ValueTraits::value_type>
|
, constant_time_size<value_type::constant_time_size>
|
||||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
|
||||||
> unordered_multiset_type;
|
> unordered_multiset_type;
|
||||||
typename unordered_multiset_type::bucket_type buckets [BucketSize];
|
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
||||||
unordered_multiset_type testset1(buckets, BucketSize, &values[0], &values[0] + 2);
|
|
||||||
|
|
||||||
|
typename unordered_multiset_type::bucket_type buckets [BucketSize];
|
||||||
typename unordered_multiset_type::bucket_type buckets2 [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);
|
testset2.insert (&values[0] + 2, &values[0] + 6);
|
||||||
testset1.swap (testset2);
|
testset1.swap (testset2);
|
||||||
@ -216,40 +220,41 @@ void test_unordered_multiset<ValueTraits>::test_swap(std::vector<typename ValueT
|
|||||||
template<class ValueTraits>
|
template<class ValueTraits>
|
||||||
void test_unordered_multiset<ValueTraits>::test_rehash(std::vector<typename ValueTraits::value_type>& values)
|
void test_unordered_multiset<ValueTraits>::test_rehash(std::vector<typename ValueTraits::value_type>& values)
|
||||||
{
|
{
|
||||||
typedef typename ValueTraits::value_type testvalue_t;
|
typedef typename ValueTraits::value_type value_type;
|
||||||
typedef boost::intrusive::unordered_multiset
|
typedef unordered_multiset
|
||||||
<ValueTraits
|
<value_type
|
||||||
,boost::hash<typename ValueTraits::value_type>
|
, value_traits<ValueTraits>
|
||||||
,std::equal_to<typename ValueTraits::value_type>
|
, constant_time_size<value_type::constant_time_size>
|
||||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
|
||||||
> unordered_multiset_type;
|
> unordered_multiset_type;
|
||||||
|
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
||||||
|
|
||||||
typename unordered_multiset_type::bucket_type buckets1 [BucketSize];
|
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);
|
BOOST_TEST (testset1.size() == 6);
|
||||||
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
||||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||||
|
|
||||||
typename unordered_multiset_type::bucket_type buckets2 [2];
|
testset1.rehash(bucket_traits(buckets2, 2));
|
||||||
testset1.rehash(buckets2, 2);
|
|
||||||
BOOST_TEST (testset1.size() == 6);
|
BOOST_TEST (testset1.size() == 6);
|
||||||
{ int init_values [] = { 4, 2, 2, 5, 3, 1 };
|
{ int init_values [] = { 4, 2, 2, 5, 3, 1 };
|
||||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||||
|
|
||||||
typename unordered_multiset_type::bucket_type buckets3 [BucketSize*2];
|
testset1.rehash(bucket_traits(buckets3, BucketSize*2));
|
||||||
testset1.rehash(buckets3, BucketSize*2);
|
|
||||||
BOOST_TEST (testset1.size() == 6);
|
BOOST_TEST (testset1.size() == 6);
|
||||||
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
||||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||||
|
|
||||||
//Now rehash reducing the buckets
|
//Now rehash reducing the buckets
|
||||||
testset1.rehash(buckets3, 2);
|
testset1.rehash(bucket_traits(buckets3, 2));
|
||||||
BOOST_TEST (testset1.size() == 6);
|
BOOST_TEST (testset1.size() == 6);
|
||||||
{ int init_values [] = { 4, 2, 2, 5, 3, 1 };
|
{ int init_values [] = { 4, 2, 2, 5, 3, 1 };
|
||||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||||
|
|
||||||
//Now rehash increasing the buckets
|
//Now rehash increasing the buckets
|
||||||
testset1.rehash(buckets3, BucketSize*2);
|
testset1.rehash(bucket_traits(buckets3, BucketSize*2));
|
||||||
BOOST_TEST (testset1.size() == 6);
|
BOOST_TEST (testset1.size() == 6);
|
||||||
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
||||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
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>
|
template<class ValueTraits>
|
||||||
void test_unordered_multiset<ValueTraits>::test_find(std::vector<typename ValueTraits::value_type>& values)
|
void test_unordered_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 boost::intrusive::unordered_multiset
|
typedef unordered_multiset
|
||||||
<ValueTraits
|
<value_type
|
||||||
,boost::hash<typename ValueTraits::value_type>
|
, value_traits<ValueTraits>
|
||||||
,std::equal_to<typename ValueTraits::value_type>
|
, constant_time_size<value_type::constant_time_size>
|
||||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
|
||||||
> unordered_multiset_type;
|
> unordered_multiset_type;
|
||||||
|
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
||||||
|
|
||||||
typename unordered_multiset_type::bucket_type buckets[BucketSize];
|
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;
|
typedef typename unordered_multiset_type::iterator iterator;
|
||||||
|
|
||||||
testvalue_t cmp_val;
|
value_type cmp_val;
|
||||||
cmp_val.value_ = 2;
|
cmp_val.value_ = 2;
|
||||||
iterator i = testset.find (cmp_val);
|
iterator i = testset.find (cmp_val);
|
||||||
BOOST_TEST (i->value_ == 2);
|
BOOST_TEST (i->value_ == 2);
|
||||||
@ -291,61 +297,62 @@ template<class ValueTraits>
|
|||||||
void test_unordered_multiset<ValueTraits>
|
void test_unordered_multiset<ValueTraits>
|
||||||
::test_clone(std::vector<typename ValueTraits::value_type>& values)
|
::test_clone(std::vector<typename ValueTraits::value_type>& values)
|
||||||
{
|
{
|
||||||
typedef boost::intrusive::unordered_multiset
|
typedef typename ValueTraits::value_type value_type;
|
||||||
<ValueTraits
|
typedef unordered_multiset
|
||||||
,boost::hash<typename ValueTraits::value_type>
|
<value_type
|
||||||
,std::equal_to<typename ValueTraits::value_type>
|
, value_traits<ValueTraits>
|
||||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
, constant_time_size<value_type::constant_time_size>
|
||||||
> unordered_multiset_type;
|
> unordered_multiset_type;
|
||||||
|
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
||||||
{
|
{
|
||||||
//Test with equal bucket arrays
|
//Test with equal bucket arrays
|
||||||
typename unordered_multiset_type::bucket_type buckets1 [BucketSize];
|
typename unordered_multiset_type::bucket_type buckets1 [BucketSize];
|
||||||
typename unordered_multiset_type::bucket_type buckets2 [BucketSize];
|
typename unordered_multiset_type::bucket_type buckets2 [BucketSize];
|
||||||
unordered_multiset_type testset1 (buckets1, BucketSize, values.begin(), values.end());
|
unordered_multiset_type testset1 (values.begin(), values.end(), bucket_traits(buckets1, BucketSize));
|
||||||
unordered_multiset_type testset2 (buckets2, 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
|
//Ordering is not guarantee in the cloning so insert data in a set and test
|
||||||
std::multiset<typename ValueTraits::value_type>
|
std::multiset<typename ValueTraits::value_type>
|
||||||
src(testset1.begin(), testset1.end());
|
src(testset1.begin(), testset1.end());
|
||||||
std::multiset<typename ValueTraits::value_type>
|
std::multiset<typename ValueTraits::value_type>
|
||||||
dst(testset2.begin(), testset2.end());
|
dst(testset2.begin(), testset2.end());
|
||||||
BOOST_TEST (src == dst);
|
BOOST_TEST (src == dst);
|
||||||
testset2.clear_and_dispose(test::delete_disposer());
|
testset2.clear_and_dispose(test::delete_disposer<value_type>());
|
||||||
BOOST_TEST (testset2.empty());
|
BOOST_TEST (testset2.empty());
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
//Test with bigger source bucket arrays
|
//Test with bigger source bucket arrays
|
||||||
typename unordered_multiset_type::bucket_type buckets1 [BucketSize*2];
|
typename unordered_multiset_type::bucket_type buckets1 [BucketSize*2];
|
||||||
typename unordered_multiset_type::bucket_type buckets2 [BucketSize];
|
typename unordered_multiset_type::bucket_type buckets2 [BucketSize];
|
||||||
unordered_multiset_type testset1 (buckets1, BucketSize*2, values.begin(), values.end());
|
unordered_multiset_type testset1 (values.begin(), values.end(), bucket_traits(buckets1, BucketSize*2));
|
||||||
unordered_multiset_type testset2 (buckets2, 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
|
//Ordering is not guarantee in the cloning so insert data in a set and test
|
||||||
std::multiset<typename ValueTraits::value_type>
|
std::multiset<typename ValueTraits::value_type>
|
||||||
src(testset1.begin(), testset1.end());
|
src(testset1.begin(), testset1.end());
|
||||||
std::multiset<typename ValueTraits::value_type>
|
std::multiset<typename ValueTraits::value_type>
|
||||||
dst(testset2.begin(), testset2.end());
|
dst(testset2.begin(), testset2.end());
|
||||||
BOOST_TEST (src == dst);
|
BOOST_TEST (src == dst);
|
||||||
testset2.clear_and_dispose(test::delete_disposer());
|
testset2.clear_and_dispose(test::delete_disposer<value_type>());
|
||||||
BOOST_TEST (testset2.empty());
|
BOOST_TEST (testset2.empty());
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
//Test with smaller source bucket arrays
|
//Test with smaller source bucket arrays
|
||||||
typename unordered_multiset_type::bucket_type buckets1 [BucketSize];
|
typename unordered_multiset_type::bucket_type buckets1 [BucketSize];
|
||||||
typename unordered_multiset_type::bucket_type buckets2 [BucketSize*2];
|
typename unordered_multiset_type::bucket_type buckets2 [BucketSize*2];
|
||||||
unordered_multiset_type testset1 (buckets1, BucketSize, values.begin(), values.end());
|
unordered_multiset_type testset1 (values.begin(), values.end(), bucket_traits(buckets1, BucketSize));
|
||||||
unordered_multiset_type testset2 (buckets2, BucketSize*2);
|
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
|
//Ordering is not guarantee in the cloning so insert data in a set and test
|
||||||
std::multiset<typename ValueTraits::value_type>
|
std::multiset<typename ValueTraits::value_type>
|
||||||
src(testset1.begin(), testset1.end());
|
src(testset1.begin(), testset1.end());
|
||||||
std::multiset<typename ValueTraits::value_type>
|
std::multiset<typename ValueTraits::value_type>
|
||||||
dst(testset2.begin(), testset2.end());
|
dst(testset2.begin(), testset2.end());
|
||||||
BOOST_TEST (src == dst);
|
BOOST_TEST (src == dst);
|
||||||
testset2.clear_and_dispose(test::delete_disposer());
|
testset2.clear_and_dispose(test::delete_disposer<value_type>());
|
||||||
BOOST_TEST (testset2.empty());
|
BOOST_TEST (testset2.empty());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -356,17 +363,26 @@ class test_main_template
|
|||||||
public:
|
public:
|
||||||
int operator()()
|
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 };
|
static const int random_init[6] = { 3, 2, 4, 1, 5, 2 };
|
||||||
std::vector<testvalue<VoidPointer, constant_time_size> > data (6);
|
std::vector<testvalue<VoidPointer, constant_time_size> > data (6);
|
||||||
for (int i = 0; i < 6; ++i)
|
for (int i = 0; i < 6; ++i)
|
||||||
data[i].value_ = random_init[i];
|
data[i].value_ = random_init[i];
|
||||||
|
|
||||||
test_unordered_multiset <typename testvalue_t::unordered_set_base_hook_t::template
|
test_unordered_multiset < typename detail::get_base_value_traits
|
||||||
value_traits<testvalue_t> >::test_all(data);
|
< 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
|
test_unordered_multiset < typename detail::get_member_value_traits
|
||||||
value_traits<testvalue_t, &testvalue_t::unordered_set_node_> >::test_all(data);
|
< 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;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -378,87 +394,51 @@ class test_main_template<VoidPointer, false>
|
|||||||
public:
|
public:
|
||||||
int operator()()
|
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 };
|
static const int random_init[6] = { 3, 2, 4, 1, 5, 2 };
|
||||||
std::vector<testvalue<VoidPointer, false> > data (6);
|
std::vector<testvalue<VoidPointer, false> > data (6);
|
||||||
for (int i = 0; i < 6; ++i)
|
for (int i = 0; i < 6; ++i)
|
||||||
data[i].value_ = random_init[i];
|
data[i].value_ = random_init[i];
|
||||||
|
|
||||||
test_unordered_multiset <typename testvalue_t::unordered_set_base_hook_t::template
|
test_unordered_multiset < typename detail::get_base_value_traits
|
||||||
value_traits<testvalue_t> >::test_all(data);
|
< 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
|
test_unordered_multiset < typename detail::get_member_value_traits
|
||||||
value_traits<testvalue_t, &testvalue_t::unordered_set_node_> >::test_all(data);
|
< 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
|
test_unordered_multiset < typename detail::get_base_value_traits
|
||||||
value_traits<testvalue_t> >::test_all(data);
|
< 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
|
test_unordered_multiset < typename detail::get_member_value_traits
|
||||||
value_traits<testvalue_t, &testvalue_t::unordered_set_auto_node_> >::test_all(data);
|
< 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;
|
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* [] )
|
int main( int, char* [] )
|
||||||
{
|
{
|
||||||
test_main_template<void*, false>()();
|
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<void*, true>()();
|
||||||
test_main_template<boost::intrusive::smart_ptr<void>, true>()();
|
test_main_template<smart_ptr<void>, true>()();
|
||||||
return boost::report_errors();
|
return boost::report_errors();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,15 +43,16 @@ struct test_unordered_set
|
|||||||
template<class ValueTraits>
|
template<class ValueTraits>
|
||||||
void test_unordered_set<ValueTraits>::test_all(std::vector<typename ValueTraits::value_type>& values)
|
void test_unordered_set<ValueTraits>::test_all(std::vector<typename ValueTraits::value_type>& values)
|
||||||
{
|
{
|
||||||
typedef boost::intrusive::unordered_set
|
typedef typename ValueTraits::value_type value_type;
|
||||||
<ValueTraits
|
typedef unordered_set
|
||||||
,boost::hash<typename ValueTraits::value_type>
|
<value_type
|
||||||
,std::equal_to<typename ValueTraits::value_type>
|
, value_traits<ValueTraits>
|
||||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
, constant_time_size<value_type::constant_time_size>
|
||||||
> unordered_set_type;
|
> unordered_set_type;
|
||||||
|
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
||||||
{
|
{
|
||||||
typename unordered_set_type::bucket_type buckets [BucketSize];
|
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());
|
testset.insert(values.begin(), values.end());
|
||||||
test::test_container(testset);
|
test::test_container(testset);
|
||||||
testset.clear();
|
testset.clear();
|
||||||
@ -77,19 +78,20 @@ void test_unordered_set<ValueTraits>::test_all(std::vector<typename ValueTraits:
|
|||||||
template<class ValueTraits>
|
template<class ValueTraits>
|
||||||
void test_unordered_set<ValueTraits>::test_impl()
|
void test_unordered_set<ValueTraits>::test_impl()
|
||||||
{
|
{
|
||||||
typedef typename ValueTraits::value_type testvalue_t;
|
typedef typename ValueTraits::value_type value_type;
|
||||||
std::vector<testvalue_t> values (5);
|
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)
|
for (int i = 0; i < 5; ++i)
|
||||||
values[i].value_ = 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];
|
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)
|
for (int i = 0; i < 5; ++i)
|
||||||
testset.insert (values[i]);
|
testset.insert (values[i]);
|
||||||
|
|
||||||
@ -104,15 +106,16 @@ void test_unordered_set<ValueTraits>::test_impl()
|
|||||||
template<class ValueTraits>
|
template<class ValueTraits>
|
||||||
void test_unordered_set<ValueTraits>::test_sort(std::vector<typename ValueTraits::value_type>& values)
|
void test_unordered_set<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 boost::intrusive::unordered_set
|
typedef unordered_set
|
||||||
<ValueTraits
|
<value_type
|
||||||
,boost::hash<typename ValueTraits::value_type>
|
, value_traits<ValueTraits>
|
||||||
,std::equal_to<typename ValueTraits::value_type>
|
, constant_time_size<value_type::constant_time_size>
|
||||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
|
||||||
> unordered_set_type;
|
> unordered_set_type;
|
||||||
|
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
||||||
|
|
||||||
typename unordered_set_type::bucket_type buckets [BucketSize];
|
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()));
|
BOOST_TEST (5 == std::distance(testset1.begin(), testset1.end()));
|
||||||
{ int init_values [] = { 1, 2, 3, 4, 5 };
|
{ 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>
|
template<class ValueTraits>
|
||||||
void test_unordered_set<ValueTraits>::test_insert(std::vector<typename ValueTraits::value_type>& values)
|
void test_unordered_set<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 boost::intrusive::unordered_set
|
typedef unordered_set
|
||||||
<ValueTraits
|
<value_type
|
||||||
,boost::hash<typename ValueTraits::value_type>
|
, value_traits<ValueTraits>
|
||||||
,std::equal_to<typename ValueTraits::value_type>
|
, constant_time_size<value_type::constant_time_size>
|
||||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
|
||||||
> unordered_set_type;
|
> unordered_set_type;
|
||||||
|
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
||||||
|
|
||||||
typename unordered_set_type::bucket_type buckets [BucketSize];
|
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);
|
testset.insert(&values[0] + 2, &values[0] + 5);
|
||||||
|
|
||||||
const unordered_set_type& const_testset = testset;
|
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>
|
template<class ValueTraits>
|
||||||
void test_unordered_set<ValueTraits>::test_swap(std::vector<typename ValueTraits::value_type>& values)
|
void test_unordered_set<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 boost::intrusive::unordered_set
|
typedef unordered_set
|
||||||
<ValueTraits
|
<value_type
|
||||||
,boost::hash<typename ValueTraits::value_type>
|
, value_traits<ValueTraits>
|
||||||
,std::equal_to<typename ValueTraits::value_type>
|
, constant_time_size<value_type::constant_time_size>
|
||||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
|
||||||
> unordered_set_type;
|
> unordered_set_type;
|
||||||
|
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
||||||
|
|
||||||
typename unordered_set_type::bucket_type buckets1 [BucketSize];
|
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];
|
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);
|
testset2.insert (&values[0] + 2, &values[0] + 6);
|
||||||
testset1.swap (testset2);
|
testset1.swap (testset2);
|
||||||
@ -192,40 +195,41 @@ void test_unordered_set<ValueTraits>::test_swap(std::vector<typename ValueTraits
|
|||||||
template<class ValueTraits>
|
template<class ValueTraits>
|
||||||
void test_unordered_set<ValueTraits>::test_rehash(std::vector<typename ValueTraits::value_type>& values)
|
void test_unordered_set<ValueTraits>::test_rehash(std::vector<typename ValueTraits::value_type>& values)
|
||||||
{
|
{
|
||||||
typedef typename ValueTraits::value_type testvalue_t;
|
typedef typename ValueTraits::value_type value_type;
|
||||||
typedef boost::intrusive::unordered_set
|
typedef unordered_set
|
||||||
<ValueTraits
|
<value_type
|
||||||
,boost::hash<typename ValueTraits::value_type>
|
, value_traits<ValueTraits>
|
||||||
,std::equal_to<typename ValueTraits::value_type>
|
, constant_time_size<value_type::constant_time_size>
|
||||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
|
||||||
> unordered_set_type;
|
> unordered_set_type;
|
||||||
|
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
||||||
|
|
||||||
typename unordered_set_type::bucket_type buckets1 [BucketSize];
|
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);
|
BOOST_TEST (testset1.size() == 5);
|
||||||
{ int init_values [] = { 1, 2, 3, 4, 5 };
|
{ int init_values [] = { 1, 2, 3, 4, 5 };
|
||||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||||
|
|
||||||
typename unordered_set_type::bucket_type buckets2 [2];
|
testset1.rehash(bucket_traits(buckets2, 2));
|
||||||
testset1.rehash(buckets2, 2);
|
|
||||||
BOOST_TEST (testset1.size() == 5);
|
BOOST_TEST (testset1.size() == 5);
|
||||||
{ int init_values [] = { 4, 2, 5, 3, 1 };
|
{ int init_values [] = { 4, 2, 5, 3, 1 };
|
||||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||||
|
|
||||||
typename unordered_set_type::bucket_type buckets3 [BucketSize*2];
|
testset1.rehash(bucket_traits(buckets3, BucketSize*2));
|
||||||
testset1.rehash(buckets3, BucketSize*2);
|
|
||||||
BOOST_TEST (testset1.size() == 5);
|
BOOST_TEST (testset1.size() == 5);
|
||||||
{ int init_values [] = { 1, 2, 3, 4, 5 };
|
{ int init_values [] = { 1, 2, 3, 4, 5 };
|
||||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||||
|
|
||||||
//Now rehash reducing the buckets
|
//Now rehash reducing the buckets
|
||||||
testset1.rehash(buckets3, 2);
|
testset1.rehash(bucket_traits(buckets3, 2));
|
||||||
BOOST_TEST (testset1.size() == 5);
|
BOOST_TEST (testset1.size() == 5);
|
||||||
{ int init_values [] = { 4, 2, 5, 3, 1 };
|
{ int init_values [] = { 4, 2, 5, 3, 1 };
|
||||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||||
|
|
||||||
//Now rehash increasing the buckets
|
//Now rehash increasing the buckets
|
||||||
testset1.rehash(buckets3, BucketSize*2);
|
testset1.rehash(bucket_traits(buckets3, BucketSize*2));
|
||||||
BOOST_TEST (testset1.size() == 5);
|
BOOST_TEST (testset1.size() == 5);
|
||||||
{ int init_values [] = { 1, 2, 3, 4, 5 };
|
{ int init_values [] = { 1, 2, 3, 4, 5 };
|
||||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
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>
|
template<class ValueTraits>
|
||||||
void test_unordered_set<ValueTraits>::test_find(std::vector<typename ValueTraits::value_type>& values)
|
void test_unordered_set<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 boost::intrusive::unordered_set
|
typedef unordered_set
|
||||||
<ValueTraits
|
<value_type
|
||||||
,boost::hash<typename ValueTraits::value_type>
|
, value_traits<ValueTraits>
|
||||||
,std::equal_to<typename ValueTraits::value_type>
|
, constant_time_size<value_type::constant_time_size>
|
||||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
|
||||||
> unordered_set_type;
|
> unordered_set_type;
|
||||||
|
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
||||||
|
|
||||||
typename unordered_set_type::bucket_type buckets [BucketSize];
|
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;
|
typedef typename unordered_set_type::iterator iterator;
|
||||||
|
|
||||||
testvalue_t cmp_val;
|
value_type cmp_val;
|
||||||
cmp_val.value_ = 2;
|
cmp_val.value_ = 2;
|
||||||
iterator i = testset.find (cmp_val);
|
iterator i = testset.find (cmp_val);
|
||||||
BOOST_TEST (i->value_ == 2);
|
BOOST_TEST (i->value_ == 2);
|
||||||
@ -266,61 +271,62 @@ template<class ValueTraits>
|
|||||||
void test_unordered_set<ValueTraits>
|
void test_unordered_set<ValueTraits>
|
||||||
::test_clone(std::vector<typename ValueTraits::value_type>& values)
|
::test_clone(std::vector<typename ValueTraits::value_type>& values)
|
||||||
{
|
{
|
||||||
typedef boost::intrusive::unordered_set
|
typedef typename ValueTraits::value_type value_type;
|
||||||
<ValueTraits
|
typedef unordered_set
|
||||||
,boost::hash<typename ValueTraits::value_type>
|
<value_type
|
||||||
,std::equal_to<typename ValueTraits::value_type>
|
, value_traits<ValueTraits>
|
||||||
,ValueTraits::value_type::constant_time_size, std::size_t
|
, constant_time_size<value_type::constant_time_size>
|
||||||
> unordered_set_type;
|
> unordered_set_type;
|
||||||
|
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
||||||
{
|
{
|
||||||
//Test with equal bucket arrays
|
//Test with equal bucket arrays
|
||||||
typename unordered_set_type::bucket_type buckets1 [BucketSize];
|
typename unordered_set_type::bucket_type buckets1 [BucketSize];
|
||||||
typename unordered_set_type::bucket_type buckets2 [BucketSize];
|
typename unordered_set_type::bucket_type buckets2 [BucketSize];
|
||||||
unordered_set_type testset1 (buckets1, BucketSize, values.begin(), values.end());
|
unordered_set_type testset1 (values.begin(), values.end(), bucket_traits(buckets1, BucketSize));
|
||||||
unordered_set_type testset2 (buckets2, 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
|
//Ordering is not guarantee in the cloning so insert data in a set and test
|
||||||
std::set<typename ValueTraits::value_type>
|
std::set<typename ValueTraits::value_type>
|
||||||
src(testset1.begin(), testset1.end());
|
src(testset1.begin(), testset1.end());
|
||||||
std::set<typename ValueTraits::value_type>
|
std::set<typename ValueTraits::value_type>
|
||||||
dst(testset2.begin(), testset2.end());
|
dst(testset2.begin(), testset2.end());
|
||||||
BOOST_TEST (src == dst );
|
BOOST_TEST (src == dst );
|
||||||
testset2.clear_and_dispose(test::delete_disposer());
|
testset2.clear_and_dispose(test::delete_disposer<value_type>());
|
||||||
BOOST_TEST (testset2.empty());
|
BOOST_TEST (testset2.empty());
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
//Test with bigger source bucket arrays
|
//Test with bigger source bucket arrays
|
||||||
typename unordered_set_type::bucket_type buckets1 [BucketSize*2];
|
typename unordered_set_type::bucket_type buckets1 [BucketSize*2];
|
||||||
typename unordered_set_type::bucket_type buckets2 [BucketSize];
|
typename unordered_set_type::bucket_type buckets2 [BucketSize];
|
||||||
unordered_set_type testset1 (buckets1, BucketSize*2, values.begin(), values.end());
|
unordered_set_type testset1 (values.begin(), values.end(), bucket_traits(buckets1, BucketSize*2));
|
||||||
unordered_set_type testset2 (buckets2, 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
|
//Ordering is not guarantee in the cloning so insert data in a set and test
|
||||||
std::set<typename ValueTraits::value_type>
|
std::set<typename ValueTraits::value_type>
|
||||||
src(testset1.begin(), testset1.end());
|
src(testset1.begin(), testset1.end());
|
||||||
std::set<typename ValueTraits::value_type>
|
std::set<typename ValueTraits::value_type>
|
||||||
dst(testset2.begin(), testset2.end());
|
dst(testset2.begin(), testset2.end());
|
||||||
BOOST_TEST (src == dst );
|
BOOST_TEST (src == dst );
|
||||||
testset2.clear_and_dispose(test::delete_disposer());
|
testset2.clear_and_dispose(test::delete_disposer<value_type>());
|
||||||
BOOST_TEST (testset2.empty());
|
BOOST_TEST (testset2.empty());
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
//Test with smaller source bucket arrays
|
//Test with smaller source bucket arrays
|
||||||
typename unordered_set_type::bucket_type buckets1 [BucketSize];
|
typename unordered_set_type::bucket_type buckets1 [BucketSize];
|
||||||
typename unordered_set_type::bucket_type buckets2 [BucketSize*2];
|
typename unordered_set_type::bucket_type buckets2 [BucketSize*2];
|
||||||
unordered_set_type testset1 (buckets1, BucketSize, values.begin(), values.end());
|
unordered_set_type testset1 (values.begin(), values.end(), bucket_traits(buckets1, BucketSize));
|
||||||
unordered_set_type testset2 (buckets2, BucketSize*2);
|
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
|
//Ordering is not guarantee in the cloning so insert data in a set and test
|
||||||
std::set<typename ValueTraits::value_type>
|
std::set<typename ValueTraits::value_type>
|
||||||
src(testset1.begin(), testset1.end());
|
src(testset1.begin(), testset1.end());
|
||||||
std::set<typename ValueTraits::value_type>
|
std::set<typename ValueTraits::value_type>
|
||||||
dst(testset2.begin(), testset2.end());
|
dst(testset2.begin(), testset2.end());
|
||||||
BOOST_TEST (src == dst );
|
BOOST_TEST (src == dst );
|
||||||
testset2.clear_and_dispose(test::delete_disposer());
|
testset2.clear_and_dispose(test::delete_disposer<value_type>());
|
||||||
BOOST_TEST (testset2.empty());
|
BOOST_TEST (testset2.empty());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -331,17 +337,25 @@ class test_main_template
|
|||||||
public:
|
public:
|
||||||
int operator()()
|
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 };
|
static const int random_init[6] = { 3, 2, 4, 1, 5, 2 };
|
||||||
std::vector<testvalue<VoidPointer, constant_time_size> > data (6);
|
std::vector<testvalue<VoidPointer, constant_time_size> > data (6);
|
||||||
for (int i = 0; i < 6; ++i)
|
for (int i = 0; i < 6; ++i)
|
||||||
data[i].value_ = random_init[i];
|
data[i].value_ = random_init[i];
|
||||||
|
|
||||||
test_unordered_set <typename testvalue_t::unordered_set_base_hook_t::template
|
test_unordered_set < typename detail::get_base_value_traits
|
||||||
value_traits<testvalue_t> >::test_all(data);
|
< value_type
|
||||||
|
, typename value_type::unordered_set_base_hook_t
|
||||||
test_unordered_set <typename testvalue_t::unordered_set_member_hook_t::template
|
>::type
|
||||||
value_traits<testvalue_t, &testvalue_t::unordered_set_node_> >::test_all(data);
|
>::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;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -353,84 +367,51 @@ class test_main_template<VoidPointer, false>
|
|||||||
public:
|
public:
|
||||||
int operator()()
|
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 };
|
static const int random_init[6] = { 3, 2, 4, 1, 5, 2 };
|
||||||
std::vector<testvalue<VoidPointer, false> > data (6);
|
std::vector<testvalue<VoidPointer, false> > data (6);
|
||||||
for (int i = 0; i < 6; ++i)
|
for (int i = 0; i < 6; ++i)
|
||||||
data[i].value_ = random_init[i];
|
data[i].value_ = random_init[i];
|
||||||
|
|
||||||
test_unordered_set <typename testvalue_t::unordered_set_base_hook_t::template
|
test_unordered_set < typename detail::get_base_value_traits
|
||||||
value_traits<testvalue_t> >::test_all(data);
|
< 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
|
test_unordered_set < typename detail::get_member_value_traits
|
||||||
value_traits<testvalue_t, &testvalue_t::unordered_set_node_> >::test_all(data);
|
< 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
|
test_unordered_set < typename detail::get_base_value_traits
|
||||||
value_traits<testvalue_t> >::test_all(data);
|
< 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
|
test_unordered_set < typename detail::get_member_value_traits
|
||||||
value_traits<testvalue_t, &testvalue_t::unordered_set_auto_node_> >::test_all(data);
|
< 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;
|
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* [] )
|
int main( int, char* [] )
|
||||||
{
|
{
|
||||||
test_main_template<void*, false>()();
|
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<void*, true>()();
|
||||||
test_main_template<boost::intrusive::smart_ptr<void>, true>()();
|
test_main_template<smart_ptr<void>, true>()();
|
||||||
return boost::report_errors();
|
return boost::report_errors();
|
||||||
}
|
}
|
||||||
#include <boost/intrusive/detail/config_end.hpp>
|
#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