forked from boostorg/intrusive
Full merge from trunk at revision 41356 of entire boost-root tree.
[SVN r41370]
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
# Boost Intrusive Library Test Jamfile
|
||||
# (C) Copyright Ion Gaztañaga 2006.
|
||||
# Use, modification and distribution are subject to 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)
|
||||
|
||||
# Adapted from John Maddock's TR1 Jamfile.v2
|
||||
# Copyright John Maddock 2005.
|
||||
# Use, modification and distribution are subject to 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)
|
||||
|
||||
# this rule enumerates through all the sources and invokes
|
||||
# the run rule for each source, the result is a list of all
|
||||
# the run rules, which we can pass on to the test_suite rule:
|
||||
|
||||
rule test_all
|
||||
{
|
||||
local all_rules = ;
|
||||
|
||||
for local fileb in [ glob *.cpp ]
|
||||
{
|
||||
all_rules += [ run $(fileb)
|
||||
: # additional args
|
||||
: # test-files
|
||||
: # requirements
|
||||
] ;
|
||||
}
|
||||
|
||||
return $(all_rules) ;
|
||||
}
|
||||
|
||||
test-suite intrusive_test : [ test_all r ] : <threading>multi ;
|
||||
@@ -0,0 +1,118 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Olaf Krzikalla 2004-2006.
|
||||
// (C) Copyright Ion Gaztanaga 2006-2007.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/intrusive for documentation.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/avl_set.hpp>
|
||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||
#include "itestvalue.hpp"
|
||||
#include "smart_ptr.hpp"
|
||||
#include "generic_multiset_test.hpp"
|
||||
|
||||
template< class ValueType
|
||||
, class Option1 = boost::intrusive::none
|
||||
, class Option2 = boost::intrusive::none
|
||||
, class Option3 = boost::intrusive::none
|
||||
>
|
||||
struct GetContainer
|
||||
{
|
||||
typedef boost::intrusive::avl_multiset
|
||||
< ValueType
|
||||
, Option1
|
||||
, Option2
|
||||
, Option3
|
||||
> type;
|
||||
};
|
||||
|
||||
template<class VoidPointer, bool constant_time_size>
|
||||
class test_main_template
|
||||
{
|
||||
public:
|
||||
int operator()()
|
||||
{
|
||||
using namespace boost::intrusive;
|
||||
typedef testvalue<VoidPointer, constant_time_size> value_type;
|
||||
|
||||
test::test_generic_multiset < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::avl_set_base_hook_t
|
||||
>::type
|
||||
, GetContainer
|
||||
>::test_all();
|
||||
test::test_generic_multiset < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::avl_set_member_hook_t
|
||||
, &value_type::avl_set_node_
|
||||
>
|
||||
>::type
|
||||
, GetContainer
|
||||
>::test_all();
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
template<class VoidPointer>
|
||||
class test_main_template<VoidPointer, false>
|
||||
{
|
||||
public:
|
||||
int operator()()
|
||||
{
|
||||
using namespace boost::intrusive;
|
||||
typedef testvalue<VoidPointer, false> value_type;
|
||||
|
||||
test::test_generic_multiset < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::avl_set_base_hook_t
|
||||
>::type
|
||||
, GetContainer
|
||||
>::test_all();
|
||||
|
||||
test::test_generic_multiset < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::avl_set_member_hook_t
|
||||
, &value_type::avl_set_node_
|
||||
>
|
||||
>::type
|
||||
, GetContainer
|
||||
>::test_all();
|
||||
|
||||
test::test_generic_multiset < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::avl_set_auto_base_hook_t
|
||||
>::type
|
||||
, GetContainer
|
||||
>::test_all();
|
||||
|
||||
test::test_generic_multiset < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::avl_set_auto_member_hook_t
|
||||
, &value_type::avl_set_auto_node_
|
||||
>
|
||||
>::type
|
||||
, GetContainer
|
||||
>::test_all();
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
int main( int, char* [] )
|
||||
{
|
||||
test_main_template<void*, false>()();
|
||||
test_main_template<boost::intrusive::smart_ptr<void>, false>()();
|
||||
test_main_template<void*, true>()();
|
||||
test_main_template<boost::intrusive::smart_ptr<void>, true>()();
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
@@ -0,0 +1,119 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Olaf Krzikalla 2004-2006.
|
||||
// (C) Copyright Ion Gaztanaga 2006-2007.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/intrusive for documentation.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/avl_set.hpp>
|
||||
#include "itestvalue.hpp"
|
||||
#include "smart_ptr.hpp"
|
||||
#include "generic_set_test.hpp"
|
||||
|
||||
template< class ValueType
|
||||
, class Option1 = boost::intrusive::none
|
||||
, class Option2 = boost::intrusive::none
|
||||
, class Option3 = boost::intrusive::none
|
||||
>
|
||||
struct GetContainer
|
||||
{
|
||||
typedef boost::intrusive::avl_set
|
||||
< ValueType
|
||||
, Option1
|
||||
, Option2
|
||||
, Option3
|
||||
> type;
|
||||
};
|
||||
|
||||
template<class VoidPointer, bool constant_time_size>
|
||||
class test_main_template
|
||||
{
|
||||
public:
|
||||
int operator()()
|
||||
{
|
||||
using namespace boost::intrusive;
|
||||
typedef testvalue<VoidPointer, constant_time_size> value_type;
|
||||
|
||||
test::test_generic_set < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::avl_set_base_hook_t
|
||||
>::type
|
||||
, GetContainer
|
||||
>::test_all();
|
||||
test::test_generic_set < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::avl_set_member_hook_t
|
||||
, &value_type::avl_set_node_
|
||||
>
|
||||
>::type
|
||||
, GetContainer
|
||||
>::test_all();
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
template<class VoidPointer>
|
||||
class test_main_template<VoidPointer, false>
|
||||
{
|
||||
public:
|
||||
int operator()()
|
||||
{
|
||||
using namespace boost::intrusive;
|
||||
typedef testvalue<VoidPointer, false> value_type;
|
||||
|
||||
test::test_generic_set < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::avl_set_base_hook_t
|
||||
>::type
|
||||
, GetContainer
|
||||
>::test_all();
|
||||
|
||||
test::test_generic_set < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::avl_set_member_hook_t
|
||||
, &value_type::avl_set_node_
|
||||
>
|
||||
>::type
|
||||
, GetContainer
|
||||
>::test_all();
|
||||
|
||||
test::test_generic_set < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::avl_set_auto_base_hook_t
|
||||
>::type
|
||||
, GetContainer
|
||||
>::test_all();
|
||||
|
||||
test::test_generic_set < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::avl_set_auto_member_hook_t
|
||||
, &value_type::avl_set_auto_node_
|
||||
>
|
||||
>::type
|
||||
, GetContainer
|
||||
>::test_all();
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
int main( int, char* [] )
|
||||
{
|
||||
|
||||
test_main_template<void*, false>()();
|
||||
test_main_template<boost::intrusive::smart_ptr<void>, false>()();
|
||||
test_main_template<void*, true>()();
|
||||
test_main_template<boost::intrusive::smart_ptr<void>, true>()();
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
@@ -0,0 +1,48 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2006-2007
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/intrusive for documentation.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTRUSIVE_TEST_COMMON_FUNCTORS_HPP
|
||||
#define BOOST_INTRUSIVE_TEST_COMMON_FUNCTORS_HPP
|
||||
|
||||
#include<boost/intrusive/detail/utilities.hpp>
|
||||
#include<boost/intrusive/detail/mpl.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
namespace test {
|
||||
|
||||
template<class T>
|
||||
class delete_disposer
|
||||
{
|
||||
public:
|
||||
template <class Pointer>
|
||||
void operator()(Pointer p)
|
||||
{
|
||||
typedef typename std::iterator_traits<Pointer>::value_type value_type;
|
||||
BOOST_INTRUSIVE_INVARIANT_ASSERT(( detail::is_same<T, value_type>::value ));
|
||||
delete detail::get_pointer(p);
|
||||
}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class new_cloner
|
||||
{
|
||||
public:
|
||||
T *operator()(const T &t)
|
||||
{ return new T(t); }
|
||||
};
|
||||
|
||||
} //namespace test {
|
||||
} //namespace intrusive {
|
||||
} //namespace boost {
|
||||
|
||||
#endif
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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 containers
|
||||
for(MyClass * it(&values[0]), *itend(&values[NumElements])
|
||||
; it != itend; ++it){
|
||||
my_list.push_front(*it);
|
||||
my_slist.push_front(*it);
|
||||
my_rbtree.insert_unique(*it);
|
||||
my_hash.insert_unique(*it);
|
||||
}
|
||||
|
||||
//Now test containers
|
||||
{
|
||||
List::const_iterator list_it (my_list.cbegin());
|
||||
Slist::const_iterator slist_it (my_slist.cbegin());
|
||||
Rbtree::const_iterator rbtree_it (my_rbtree.cbegin());
|
||||
Hash::const_iterator hash_it (my_hash.cbegin());
|
||||
MyClass *it_val(&values[NumElements] - 1), *it_rbeg_val(&values[0]-1);
|
||||
|
||||
//Test inserted objects
|
||||
for(; it_val != it_rbeg_val; --it_val, ++list_it, ++slist_it, ++rbtree_it){
|
||||
if(&*list_it != &*it_val) return 1;
|
||||
if(&*slist_it != &*it_val) return 1;
|
||||
if(&*rbtree_it != &*it_val) return 1;
|
||||
hash_it = my_hash.find(*it_val);
|
||||
if(hash_it == my_hash.cend() || &*hash_it != &*it_val)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,328 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Olaf Krzikalla 2004-2006.
|
||||
// (C) Copyright Ion Gaztanaga 2006-2007.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/intrusive for documentation.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#include <vector> //vector
|
||||
#include <algorithm> //sort, random_shuffle
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include "common_functors.hpp"
|
||||
#include <boost/intrusive/options.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include "test_macros.hpp"
|
||||
#include "test_container.hpp"
|
||||
|
||||
namespace boost{
|
||||
namespace intrusive{
|
||||
namespace test{
|
||||
|
||||
template<class T>
|
||||
struct has_splay
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct has_rebalance
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
|
||||
struct test_generic_assoc
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
static void test_all(std::vector<value_type>& values);
|
||||
static void test_clone(std::vector<value_type>& values);
|
||||
static void test_insert_erase_burst();
|
||||
static void test_container_from_end(std::vector<value_type>& values);
|
||||
static void test_splay_up(std::vector<value_type>& values);
|
||||
static void test_splay_up(std::vector<value_type>& values, boost::intrusive::detail::true_type);
|
||||
static void test_splay_up(std::vector<value_type>& values, boost::intrusive::detail::false_type);
|
||||
static void test_splay_down(std::vector<value_type>& values);
|
||||
static void test_splay_down(std::vector<value_type>& values, boost::intrusive::detail::true_type);
|
||||
static void test_splay_down(std::vector<value_type>& values, boost::intrusive::detail::false_type);
|
||||
static void test_rebalance(std::vector<value_type>& values);
|
||||
static void test_rebalance(std::vector<value_type>& values, boost::intrusive::detail::true_type);
|
||||
static void test_rebalance(std::vector<value_type>& values, boost::intrusive::detail::false_type);
|
||||
};
|
||||
|
||||
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
|
||||
void test_generic_assoc<ValueTraits, ContainerDefiner>::test_insert_erase_burst()
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
|
||||
std::vector<value_type> values;
|
||||
const int MaxValues = 100;
|
||||
for(int i = 0; i != MaxValues; ++i){
|
||||
values.push_back(value_type(i));
|
||||
}
|
||||
|
||||
typedef typename ContainerDefiner
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
>::type assoc_type;
|
||||
typedef typename assoc_type::iterator iterator;
|
||||
|
||||
//First ordered insertions
|
||||
assoc_type testset (&values[0], &values[0] + values.size());
|
||||
TEST_INTRUSIVE_SEQUENCE_EXPECTED(testset, testset.begin());
|
||||
|
||||
//Ordered erasure
|
||||
iterator it(testset.begin()), itend(testset.end());
|
||||
for(int i = 0; it != itend; ++i){
|
||||
BOOST_TEST(&*it == &values[i]);
|
||||
it = testset.erase(it);
|
||||
}
|
||||
|
||||
BOOST_TEST(testset.empty());
|
||||
|
||||
//Now random insertions
|
||||
std::random_shuffle(values.begin(), values.end());
|
||||
testset.insert(&values[0], &values[0] + values.size());
|
||||
std::sort(values.begin(), values.end());
|
||||
TEST_INTRUSIVE_SEQUENCE_EXPECTED(testset, testset.begin());
|
||||
|
||||
//Random erasure
|
||||
std::random_shuffle(values.begin(), values.end());
|
||||
for(int i = 0; i != MaxValues; ++i){
|
||||
it = testset.erase(testset.iterator_to(values[i]));
|
||||
}
|
||||
|
||||
BOOST_TEST(testset.empty());
|
||||
}
|
||||
|
||||
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
|
||||
void test_generic_assoc<ValueTraits, ContainerDefiner>::test_all(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
test_clone(values);
|
||||
test_container_from_end(values);
|
||||
test_splay_up(values);
|
||||
test_splay_down(values);
|
||||
test_rebalance(values);
|
||||
test_insert_erase_burst();
|
||||
}
|
||||
|
||||
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
|
||||
void test_generic_assoc<ValueTraits, ContainerDefiner>
|
||||
::test_clone(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef typename ContainerDefiner
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
>::type assoc_type;
|
||||
|
||||
assoc_type testset1 (&values[0], &values[0] + values.size());
|
||||
assoc_type testset2;
|
||||
|
||||
testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
|
||||
BOOST_TEST (testset2 == testset1);
|
||||
testset2.clear_and_dispose(test::delete_disposer<value_type>());
|
||||
BOOST_TEST (testset2.empty());
|
||||
}
|
||||
|
||||
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
|
||||
void test_generic_assoc<ValueTraits, ContainerDefiner>
|
||||
::test_container_from_end(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef typename ContainerDefiner
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
>::type assoc_type;
|
||||
assoc_type testset (&values[0], &values[0] + values.size());
|
||||
BOOST_TEST (testset == assoc_type::container_from_end_iterator(testset.end()));
|
||||
BOOST_TEST (testset == assoc_type::container_from_end_iterator(testset.cend()));
|
||||
}
|
||||
|
||||
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
|
||||
void test_generic_assoc<ValueTraits, ContainerDefiner>::test_splay_up
|
||||
(std::vector<typename ValueTraits::value_type>& values, boost::intrusive::detail::true_type)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef typename ContainerDefiner
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
>::type assoc_type;
|
||||
typedef typename assoc_type::iterator iterator;
|
||||
typedef std::vector<value_type> orig_set_t;
|
||||
std::size_t num_values;
|
||||
orig_set_t original_testset;
|
||||
{
|
||||
assoc_type testset (values.begin(), values.end());
|
||||
num_values = testset.size();
|
||||
original_testset.insert(original_testset.end(), testset.begin(), testset.end());
|
||||
}
|
||||
|
||||
for(std::size_t i = 0; i != num_values; ++i){
|
||||
assoc_type testset (values.begin(), values.end());
|
||||
{
|
||||
iterator it = testset.begin();
|
||||
for(std::size_t j = 0; j != i; ++j, ++it){}
|
||||
testset.splay_up(it);
|
||||
}
|
||||
BOOST_TEST (testset.size() == num_values);
|
||||
iterator it = testset.begin();
|
||||
for( typename orig_set_t::const_iterator origit = original_testset.begin()
|
||||
, origitend = original_testset.end()
|
||||
; origit != origitend
|
||||
; ++origit, ++it){
|
||||
BOOST_TEST(*origit == *it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
|
||||
void test_generic_assoc<ValueTraits, ContainerDefiner>::test_splay_up
|
||||
(std::vector<typename ValueTraits::value_type>&, boost::intrusive::detail::false_type)
|
||||
{}
|
||||
|
||||
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
|
||||
void test_generic_assoc<ValueTraits, ContainerDefiner>::test_splay_up
|
||||
(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ContainerDefiner
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
>::type assoc_type;
|
||||
typedef typename detail::remove_const<assoc_type>::type Type;
|
||||
typedef detail::bool_<has_splay<Type>::value> enabler;
|
||||
test_splay_up(values, enabler());
|
||||
}
|
||||
|
||||
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
|
||||
void test_generic_assoc<ValueTraits, ContainerDefiner>::test_splay_down
|
||||
(std::vector<typename ValueTraits::value_type>& values, boost::intrusive::detail::true_type)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef typename ContainerDefiner
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
>::type assoc_type;
|
||||
typedef typename assoc_type::iterator iterator;
|
||||
typedef std::vector<value_type> orig_set_t;
|
||||
std::size_t num_values;
|
||||
orig_set_t original_testset;
|
||||
{
|
||||
assoc_type testset (values.begin(), values.end());
|
||||
num_values = testset.size();
|
||||
original_testset.insert(original_testset.end(), testset.begin(), testset.end());
|
||||
}
|
||||
|
||||
for(std::size_t i = 0; i != num_values; ++i){
|
||||
assoc_type testset (values.begin(), values.end());
|
||||
BOOST_TEST(testset.size() == num_values);
|
||||
{
|
||||
iterator it = testset.begin();
|
||||
for(std::size_t j = 0; j != i; ++j, ++it){}
|
||||
BOOST_TEST(*it == *testset.splay_down(*it));
|
||||
}
|
||||
BOOST_TEST (testset.size() == num_values);
|
||||
iterator it = testset.begin();
|
||||
for( typename orig_set_t::const_iterator origit = original_testset.begin()
|
||||
, origitend = original_testset.end()
|
||||
; origit != origitend
|
||||
; ++origit, ++it){
|
||||
BOOST_TEST(*origit == *it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
|
||||
void test_generic_assoc<ValueTraits, ContainerDefiner>::test_splay_down
|
||||
(std::vector<typename ValueTraits::value_type>&, boost::intrusive::detail::false_type)
|
||||
{}
|
||||
|
||||
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
|
||||
void test_generic_assoc<ValueTraits, ContainerDefiner>::test_splay_down
|
||||
(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ContainerDefiner
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
>::type assoc_type;
|
||||
typedef typename detail::remove_const<assoc_type>::type Type;
|
||||
typedef detail::bool_<has_splay<Type>::value> enabler;
|
||||
test_splay_down(values, enabler());
|
||||
}
|
||||
|
||||
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
|
||||
void test_generic_assoc<ValueTraits, ContainerDefiner>::test_rebalance
|
||||
(std::vector<typename ValueTraits::value_type>& values, boost::intrusive::detail::true_type)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef typename ContainerDefiner
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
>::type assoc_type;
|
||||
typedef std::vector<value_type> orig_set_t;
|
||||
typedef typename orig_set_t::iterator iterator_t;
|
||||
std::size_t num_values;
|
||||
orig_set_t original_testset;
|
||||
{
|
||||
assoc_type testset (values.begin(), values.end());
|
||||
num_values = testset.size();
|
||||
original_testset.insert(original_testset.end(), testset.begin(), testset.end());
|
||||
}
|
||||
{
|
||||
assoc_type testset(values.begin(), values.end());
|
||||
testset.rebalance();
|
||||
iterator_t it = original_testset.begin();
|
||||
TEST_INTRUSIVE_SEQUENCE_EXPECTED(original_testset, testset.begin());
|
||||
}
|
||||
|
||||
{
|
||||
std::size_t numdata;
|
||||
{
|
||||
assoc_type testset(values.begin(), values.end());
|
||||
numdata = testset.size();
|
||||
}
|
||||
|
||||
for(int i = 0; i != (int)numdata; ++i){
|
||||
assoc_type testset(values.begin(), values.end());
|
||||
typename assoc_type::iterator it = testset.begin();
|
||||
for(int j = 0; j != i; ++j) ++it;
|
||||
testset.rebalance_subtree(it);
|
||||
TEST_INTRUSIVE_SEQUENCE_EXPECTED(original_testset, testset.begin());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
|
||||
void test_generic_assoc<ValueTraits, ContainerDefiner>::test_rebalance
|
||||
(std::vector<typename ValueTraits::value_type>&, boost::intrusive::detail::false_type)
|
||||
{}
|
||||
|
||||
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
|
||||
void test_generic_assoc<ValueTraits, ContainerDefiner>::test_rebalance
|
||||
(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ContainerDefiner
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
>::type assoc_type;
|
||||
typedef typename detail::remove_const<assoc_type>::type Type;
|
||||
typedef detail::bool_<has_rebalance<Type>::value> enabler;
|
||||
test_rebalance(values, enabler());
|
||||
}
|
||||
|
||||
}}} //namespace boost::intrusive::test
|
||||
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
@@ -0,0 +1,227 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Olaf Krzikalla 2004-2006.
|
||||
// (C) Copyright Ion Gaztanaga 2006-2007.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/intrusive for documentation.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#include <vector>
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include "common_functors.hpp"
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <boost/intrusive/options.hpp>
|
||||
#include "test_macros.hpp"
|
||||
#include "test_container.hpp"
|
||||
#include "generic_assoc_test.hpp"
|
||||
|
||||
namespace boost{
|
||||
namespace intrusive{
|
||||
namespace test{
|
||||
|
||||
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
|
||||
struct test_generic_multiset
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
static void test_all ();
|
||||
static void test_sort(std::vector<value_type>& values);
|
||||
static void test_insert(std::vector<value_type>& values);
|
||||
static void test_swap(std::vector<value_type>& values);
|
||||
static void test_find(std::vector<value_type>& values);
|
||||
static void test_impl();
|
||||
};
|
||||
|
||||
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
|
||||
void test_generic_multiset<ValueTraits, ContainerDefiner>::test_all ()
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
static const int random_init[6] = { 3, 2, 4, 1, 5, 2 };
|
||||
std::vector<value_type> values (6);
|
||||
for (int i = 0; i < 6; ++i)
|
||||
values[i].value_ = random_init[i];
|
||||
|
||||
typedef typename ContainerDefiner
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
>::type multiset_type;
|
||||
{
|
||||
multiset_type testset(values.begin(), values.end());
|
||||
test::test_container(testset);
|
||||
testset.clear();
|
||||
testset.insert(values.begin(), values.end());
|
||||
test::test_common_unordered_and_associative_container(testset, values);
|
||||
testset.clear();
|
||||
testset.insert(values.begin(), values.end());
|
||||
test::test_associative_container(testset, values);
|
||||
testset.clear();
|
||||
testset.insert(values.begin(), values.end());
|
||||
test::test_non_unique_container(testset, values);
|
||||
}
|
||||
test_sort(values);
|
||||
test_insert(values);
|
||||
test_swap(values);
|
||||
test_find(values);
|
||||
test_impl();
|
||||
test_generic_assoc<ValueTraits, ContainerDefiner>::test_all(values);
|
||||
}
|
||||
|
||||
//test case due to an error in tree implementation:
|
||||
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
|
||||
void test_generic_multiset<ValueTraits, ContainerDefiner>::test_impl()
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
std::vector<value_type> values (5);
|
||||
for (int i = 0; i < 5; ++i)
|
||||
values[i].value_ = i;
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef typename ContainerDefiner
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
>::type multiset_type;
|
||||
|
||||
multiset_type testset;
|
||||
for (int i = 0; i < 5; ++i)
|
||||
testset.insert (values[i]);
|
||||
|
||||
testset.erase (testset.iterator_to (values[0]));
|
||||
testset.erase (testset.iterator_to (values[1]));
|
||||
testset.insert (values[1]);
|
||||
|
||||
testset.erase (testset.iterator_to (values[2]));
|
||||
testset.erase (testset.iterator_to (values[3]));
|
||||
}
|
||||
|
||||
//test: constructor, iterator, clear, reverse_iterator, front, back, size:
|
||||
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
|
||||
void test_generic_multiset<ValueTraits, ContainerDefiner>::test_sort(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef typename ContainerDefiner
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
>::type multiset_type;
|
||||
|
||||
multiset_type testset1 (values.begin(), values.end());
|
||||
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
|
||||
testset1.clear();
|
||||
BOOST_TEST (testset1.empty());
|
||||
|
||||
typedef typename ContainerDefiner
|
||||
<value_type
|
||||
, compare<even_odd>
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
>::type multiset_type2;
|
||||
multiset_type2 testset2 (&values[0], &values[0] + 6);
|
||||
{ int init_values [] = { 5, 3, 1, 4, 2, 2 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset2.rbegin() ); }
|
||||
|
||||
BOOST_TEST (testset2.begin()->value_ == 2);
|
||||
BOOST_TEST (testset2.rbegin()->value_ == 5);
|
||||
}
|
||||
|
||||
//test: insert, const_iterator, const_reverse_iterator, erase, iterator_to:
|
||||
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
|
||||
void test_generic_multiset<ValueTraits, ContainerDefiner>::test_insert(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef typename ContainerDefiner
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, size_type<std::size_t>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
>::type multiset_type;
|
||||
|
||||
multiset_type testset;
|
||||
testset.insert(&values[0] + 2, &values[0] + 5);
|
||||
{ int init_values [] = { 1, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset.begin() ); }
|
||||
|
||||
typename multiset_type::iterator i = testset.begin();
|
||||
BOOST_TEST (i->value_ == 1);
|
||||
|
||||
i = testset.insert (i, values[0]);
|
||||
BOOST_TEST (&*i == &values[0]);
|
||||
|
||||
{ int init_values [] = { 5, 4, 3, 1 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset.rbegin() ); }
|
||||
|
||||
i = testset.iterator_to (values[2]);
|
||||
BOOST_TEST (&*i == &values[2]);
|
||||
|
||||
i = multiset_type::s_iterator_to (values[2]);
|
||||
BOOST_TEST (&*i == &values[2]);
|
||||
|
||||
testset.erase(i);
|
||||
|
||||
{ int init_values [] = { 1, 3, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset.begin() ); }
|
||||
}
|
||||
|
||||
//test: insert (seq-version), swap, erase (seq-version), size:
|
||||
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
|
||||
void test_generic_multiset<ValueTraits, ContainerDefiner>::test_swap(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef typename ContainerDefiner
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, size_type<std::size_t>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
>::type multiset_type;
|
||||
multiset_type testset1 (&values[0], &values[0] + 2);
|
||||
multiset_type testset2;
|
||||
testset2.insert (&values[0] + 2, &values[0] + 6);
|
||||
testset1.swap (testset2);
|
||||
|
||||
{ int init_values [] = { 1, 2, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
{ int init_values [] = { 2, 3 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset2.begin() ); }
|
||||
|
||||
testset1.erase (testset1.iterator_to(values[5]), testset1.end());
|
||||
BOOST_TEST (testset1.size() == 1);
|
||||
BOOST_TEST (&*testset1.begin() == &values[3]);
|
||||
}
|
||||
|
||||
//test: find, equal_range (lower_bound, upper_bound):
|
||||
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
|
||||
void test_generic_multiset<ValueTraits, ContainerDefiner>::test_find(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef typename ContainerDefiner
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, size_type<std::size_t>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
>::type multiset_type;
|
||||
multiset_type testset (values.begin(), values.end());
|
||||
typedef typename multiset_type::iterator iterator;
|
||||
|
||||
value_type cmp_val;
|
||||
cmp_val.value_ = 2;
|
||||
iterator i = testset.find (cmp_val);
|
||||
BOOST_TEST (i->value_ == 2);
|
||||
BOOST_TEST ((++i)->value_ == 2);
|
||||
std::pair<iterator,iterator> range = testset.equal_range (cmp_val);
|
||||
|
||||
BOOST_TEST (range.first->value_ == 2);
|
||||
BOOST_TEST (range.second->value_ == 3);
|
||||
BOOST_TEST (std::distance (range.first, range.second) == 2);
|
||||
|
||||
cmp_val.value_ = 7;
|
||||
BOOST_TEST (testset.find (cmp_val) == testset.end());
|
||||
}
|
||||
|
||||
}}} //namespace boost::intrusive::test
|
||||
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
@@ -0,0 +1,225 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Olaf Krzikalla 2004-2006.
|
||||
// (C) Copyright Ion Gaztanaga 2006-2007.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/intrusive for documentation.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#include <vector>
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include "common_functors.hpp"
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <boost/intrusive/options.hpp>
|
||||
#include "test_macros.hpp"
|
||||
#include "test_container.hpp"
|
||||
#include "generic_assoc_test.hpp"
|
||||
|
||||
namespace boost{
|
||||
namespace intrusive{
|
||||
namespace test{
|
||||
|
||||
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
|
||||
struct test_generic_set
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
static void test_all();
|
||||
static void test_sort(std::vector<value_type>& values);
|
||||
static void test_insert(std::vector<value_type>& values);
|
||||
static void test_swap(std::vector<value_type>& values);
|
||||
static void test_find(std::vector<value_type>& values);
|
||||
static void test_impl();
|
||||
};
|
||||
|
||||
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
|
||||
void test_generic_set<ValueTraits, ContainerDefiner>::test_all()
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
static const int random_init[6] = { 3, 2, 4, 1, 5, 2 };
|
||||
std::vector<value_type> values (6);
|
||||
for (int i = 0; i < 6; ++i)
|
||||
values[i].value_ = random_init[i];
|
||||
|
||||
typedef typename ContainerDefiner
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
>::type set_type;
|
||||
{
|
||||
set_type testset(values.begin(), values.end());
|
||||
test::test_container(testset);
|
||||
testset.clear();
|
||||
testset.insert(values.begin(), values.end());
|
||||
test::test_common_unordered_and_associative_container(testset, values);
|
||||
testset.clear();
|
||||
testset.insert(values.begin(), values.end());
|
||||
test::test_associative_container(testset, values);
|
||||
testset.clear();
|
||||
testset.insert(values.begin(), values.end());
|
||||
test::test_unique_container(testset, values);
|
||||
}
|
||||
test_sort(values);
|
||||
test_insert(values);
|
||||
test_swap(values);
|
||||
test_find(values);
|
||||
test_impl();
|
||||
test_generic_assoc<ValueTraits, ContainerDefiner>::test_all(values);
|
||||
}
|
||||
|
||||
//test case due to an error in tree implementation:
|
||||
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
|
||||
void test_generic_set<ValueTraits, ContainerDefiner>::test_impl()
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
std::vector<value_type> values (5);
|
||||
for (int i = 0; i < 5; ++i)
|
||||
values[i].value_ = i;
|
||||
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef typename ContainerDefiner
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
>::type set_type;
|
||||
set_type testset;
|
||||
for (int i = 0; i < 5; ++i)
|
||||
testset.insert (values[i]);
|
||||
|
||||
testset.erase (testset.iterator_to (values[0]));
|
||||
testset.erase (testset.iterator_to (values[1]));
|
||||
testset.insert (values[1]);
|
||||
|
||||
testset.erase (testset.iterator_to (values[2]));
|
||||
testset.erase (testset.iterator_to (values[3]));
|
||||
}
|
||||
|
||||
//test: constructor, iterator, clear, reverse_iterator, front, back, size:
|
||||
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
|
||||
void test_generic_set<ValueTraits, ContainerDefiner>::test_sort(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef typename ContainerDefiner
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
>::type set_type;
|
||||
set_type testset1 (values.begin(), values.end());
|
||||
{ int init_values [] = { 1, 2, 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
|
||||
testset1.clear();
|
||||
BOOST_TEST (testset1.empty());
|
||||
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef typename ContainerDefiner
|
||||
< value_type
|
||||
, compare<even_odd>
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
>::type set_type2;
|
||||
set_type2 testset2 (&values[0], &values[0] + 6);
|
||||
{ int init_values [] = { 5, 3, 1, 4, 2 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset2.rbegin() ); }
|
||||
BOOST_TEST (testset2.begin()->value_ == 2);
|
||||
BOOST_TEST (testset2.rbegin()->value_ == 5);
|
||||
}
|
||||
|
||||
//test: insert, const_iterator, const_reverse_iterator, erase, s_iterator_to:
|
||||
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
|
||||
void test_generic_set<ValueTraits, ContainerDefiner>::test_insert(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef typename ContainerDefiner
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
>::type set_type;
|
||||
set_type testset;
|
||||
testset.insert(&values[0] + 2, &values[0] + 5);
|
||||
|
||||
const set_type& const_testset = testset;
|
||||
{ int init_values [] = { 1, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); }
|
||||
|
||||
typename set_type::iterator i = testset.begin();
|
||||
BOOST_TEST (i->value_ == 1);
|
||||
|
||||
i = testset.insert (i, values[0]);
|
||||
BOOST_TEST (&*i == &values[0]);
|
||||
|
||||
{ int init_values [] = { 5, 4, 3, 1 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset.rbegin() ); }
|
||||
|
||||
i = testset.iterator_to (values[2]);
|
||||
BOOST_TEST (&*i == &values[2]);
|
||||
|
||||
i = set_type::s_iterator_to(values[2]);
|
||||
BOOST_TEST (&*i == &values[2]);
|
||||
|
||||
testset.erase (i);
|
||||
{ int init_values [] = { 1, 3, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset.begin() ); }
|
||||
}
|
||||
|
||||
//test: insert (seq-version), swap, erase (seq-version), size:
|
||||
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
|
||||
void test_generic_set<ValueTraits, ContainerDefiner>::test_swap(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef typename ContainerDefiner
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
>::type set_type;
|
||||
set_type testset1 (&values[0], &values[0] + 2);
|
||||
set_type testset2;
|
||||
testset2.insert (&values[0] + 2, &values[0] + 6);
|
||||
testset1.swap (testset2);
|
||||
|
||||
{ int init_values [] = { 1, 2, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
|
||||
{ int init_values [] = { 2, 3 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset2.begin() ); }
|
||||
|
||||
testset1.erase (testset1.iterator_to(values[5]), testset1.end());
|
||||
BOOST_TEST (testset1.size() == 1);
|
||||
// BOOST_TEST (&testset1.front() == &values[3]);
|
||||
BOOST_TEST (&*testset1.begin() == &values[3]);
|
||||
}
|
||||
|
||||
//test: find, equal_range (lower_bound, upper_bound):
|
||||
template<class ValueTraits, template <class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none, class = ::boost::intrusive::none> class ContainerDefiner>
|
||||
void test_generic_set<ValueTraits, ContainerDefiner>::test_find(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef typename ContainerDefiner
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
>::type set_type;
|
||||
set_type testset (values.begin(), values.end());
|
||||
typedef typename set_type::iterator iterator;
|
||||
|
||||
value_type cmp_val;
|
||||
cmp_val.value_ = 2;
|
||||
iterator i = testset.find (cmp_val);
|
||||
BOOST_TEST (i->value_ == 2);
|
||||
BOOST_TEST ((++i)->value_ != 2);
|
||||
std::pair<iterator,iterator> range = testset.equal_range (cmp_val);
|
||||
|
||||
BOOST_TEST (range.first->value_ == 2);
|
||||
BOOST_TEST (range.second->value_ == 3);
|
||||
BOOST_TEST (std::distance (range.first, range.second) == 1);
|
||||
|
||||
cmp_val.value_ = 7;
|
||||
BOOST_TEST (testset.find (cmp_val) == testset.end());
|
||||
}
|
||||
|
||||
}}} //namespace boost::intrusive::test
|
||||
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
@@ -0,0 +1,372 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Olaf Krzikalla 2004-2006.
|
||||
// (C) Copyright Ion Gaztanaga 2006-2007.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/intrusive for documentation.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef BOOST_INTRUSIVE_DETAIL_ITESTVALUE_HPP
|
||||
#define BOOST_INTRUSIVE_DETAIL_ITESTVALUE_HPP
|
||||
|
||||
#include <iostream>
|
||||
#include <boost/intrusive/set_hook.hpp>
|
||||
#include <boost/intrusive/list_hook.hpp>
|
||||
#include <boost/intrusive/slist_hook.hpp>
|
||||
#include <boost/intrusive/unordered_set_hook.hpp>
|
||||
#include <boost/intrusive/splay_set_hook.hpp>
|
||||
#include <boost/intrusive/avl_set_hook.hpp>
|
||||
#include <boost/intrusive/bs_set_hook.hpp>
|
||||
#include <boost/intrusive/options.hpp>
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include "smart_ptr.hpp"
|
||||
|
||||
namespace boost{
|
||||
namespace intrusive{
|
||||
|
||||
struct my_tag;
|
||||
|
||||
template<class VoidPointer>
|
||||
struct set_base_hook_type
|
||||
{ typedef set_base_hook<void_pointer<VoidPointer> > type; };
|
||||
|
||||
template<class VoidPointer>
|
||||
struct set_auto_base_hook_type
|
||||
{ typedef set_base_hook<link_mode<auto_unlink>, void_pointer<VoidPointer>, tag<my_tag>, optimize_size<true> > type; };
|
||||
|
||||
template<class VoidPointer>
|
||||
struct set_member_hook_type
|
||||
{ typedef set_member_hook<void_pointer<VoidPointer>, optimize_size<true> > type; };
|
||||
|
||||
template<class VoidPointer>
|
||||
struct set_auto_member_hook_type
|
||||
{ typedef set_member_hook<link_mode<auto_unlink>, void_pointer<VoidPointer> > type; };
|
||||
|
||||
template<class VoidPointer>
|
||||
struct splay_set_base_hook_type
|
||||
{ typedef splay_set_base_hook<void_pointer<VoidPointer> > type; };
|
||||
|
||||
template<class VoidPointer>
|
||||
struct splay_set_auto_base_hook_type
|
||||
{ typedef splay_set_base_hook<link_mode<auto_unlink>, void_pointer<VoidPointer>, tag<my_tag> > type; };
|
||||
|
||||
template<class VoidPointer>
|
||||
struct splay_set_member_hook_type
|
||||
{ typedef splay_set_member_hook<void_pointer<VoidPointer> > type; };
|
||||
|
||||
template<class VoidPointer>
|
||||
struct splay_set_auto_member_hook_type
|
||||
{ typedef splay_set_member_hook<link_mode<auto_unlink>, void_pointer<VoidPointer> > type; };
|
||||
|
||||
template<class VoidPointer>
|
||||
struct bs_set_base_hook_type
|
||||
{ typedef bs_set_base_hook<void_pointer<VoidPointer> > type; };
|
||||
|
||||
template<class VoidPointer>
|
||||
struct bs_set_member_hook_type
|
||||
{ typedef bs_set_member_hook<void_pointer<VoidPointer> > type; };
|
||||
|
||||
template<class VoidPointer>
|
||||
struct avl_set_base_hook_type
|
||||
{ typedef avl_set_base_hook<void_pointer<VoidPointer> > type; };
|
||||
|
||||
template<class VoidPointer>
|
||||
struct avl_set_auto_base_hook_type
|
||||
{ typedef avl_set_base_hook<link_mode<auto_unlink>, void_pointer<VoidPointer>, tag<my_tag>, optimize_size<true> > type; };
|
||||
|
||||
template<class VoidPointer>
|
||||
struct avl_set_member_hook_type
|
||||
{ typedef avl_set_member_hook<void_pointer<VoidPointer>, optimize_size<true> > type; };
|
||||
|
||||
template<class VoidPointer>
|
||||
struct avl_set_auto_member_hook_type
|
||||
{ typedef avl_set_member_hook<link_mode<auto_unlink>, void_pointer<VoidPointer> > type; };
|
||||
|
||||
template<class VoidPointer>
|
||||
struct list_base_hook_type
|
||||
{ typedef list_base_hook<void_pointer<VoidPointer> > type; };
|
||||
|
||||
template<class VoidPointer>
|
||||
struct list_auto_base_hook_type
|
||||
{ typedef list_base_hook<link_mode<auto_unlink>, void_pointer<VoidPointer>, tag<my_tag> > type; };
|
||||
|
||||
template<class VoidPointer>
|
||||
struct list_member_hook_type
|
||||
{ typedef list_member_hook<void_pointer<VoidPointer> > type; };
|
||||
|
||||
template<class VoidPointer>
|
||||
struct list_auto_member_hook_type
|
||||
{ typedef list_member_hook<link_mode<auto_unlink>, void_pointer<VoidPointer> > type; };
|
||||
|
||||
template<class VoidPointer>
|
||||
struct slist_base_hook_type
|
||||
{ typedef slist_base_hook<void_pointer<VoidPointer> > type; };
|
||||
|
||||
template<class VoidPointer>
|
||||
struct slist_auto_base_hook_type
|
||||
{ typedef slist_base_hook<link_mode<auto_unlink>, void_pointer<VoidPointer>, tag<my_tag> > type; };
|
||||
|
||||
template<class VoidPointer>
|
||||
struct slist_member_hook_type
|
||||
{ typedef slist_member_hook<void_pointer<VoidPointer> > type; };
|
||||
|
||||
template<class VoidPointer>
|
||||
struct slist_auto_member_hook_type
|
||||
{ typedef slist_member_hook<link_mode<auto_unlink>, void_pointer<VoidPointer> > type; };
|
||||
|
||||
template<class VoidPointer>
|
||||
struct uset_base_hook_type
|
||||
{ typedef unordered_set_base_hook<void_pointer<VoidPointer> > type; };
|
||||
|
||||
template<class VoidPointer>
|
||||
struct uset_auto_base_hook_type
|
||||
{
|
||||
typedef unordered_set_base_hook
|
||||
< link_mode<auto_unlink>, void_pointer<VoidPointer>
|
||||
, tag<my_tag>, store_hash<true> > type;
|
||||
};
|
||||
|
||||
template<class VoidPointer>
|
||||
struct uset_member_hook_type
|
||||
{ typedef unordered_set_member_hook<void_pointer<VoidPointer> > type; };
|
||||
|
||||
template<class VoidPointer>
|
||||
struct uset_auto_member_hook_type
|
||||
{
|
||||
typedef unordered_set_member_hook
|
||||
< link_mode<auto_unlink>, void_pointer<VoidPointer>
|
||||
, store_hash<true> > type;
|
||||
};
|
||||
|
||||
template<class VoidPointer, bool ConstantTimeSize>
|
||||
struct testvalue
|
||||
: set_base_hook_type<VoidPointer>::type
|
||||
, set_auto_base_hook_type<VoidPointer>::type
|
||||
, splay_set_base_hook_type<VoidPointer>::type
|
||||
, splay_set_auto_base_hook_type<VoidPointer>::type
|
||||
, bs_set_base_hook_type<VoidPointer>::type
|
||||
, avl_set_base_hook_type<VoidPointer>::type
|
||||
, avl_set_auto_base_hook_type<VoidPointer>::type
|
||||
, list_base_hook_type<VoidPointer>::type
|
||||
, list_auto_base_hook_type<VoidPointer>::type
|
||||
, slist_base_hook_type<VoidPointer>::type
|
||||
, slist_auto_base_hook_type<VoidPointer>::type
|
||||
, uset_base_hook_type<VoidPointer>::type
|
||||
, uset_auto_base_hook_type<VoidPointer>::type
|
||||
{
|
||||
typedef typename set_auto_base_hook_type<VoidPointer>::type set_auto_base_hook_t;
|
||||
typedef typename set_base_hook_type<VoidPointer>::type set_base_hook_t;
|
||||
typedef typename set_auto_member_hook_type<VoidPointer>::type set_auto_member_hook_t;
|
||||
typedef typename set_member_hook_type<VoidPointer>::type set_member_hook_t;
|
||||
|
||||
typedef typename splay_set_auto_base_hook_type<VoidPointer>::type splay_set_auto_base_hook_t;
|
||||
typedef typename splay_set_base_hook_type<VoidPointer>::type splay_set_base_hook_t;
|
||||
typedef typename splay_set_auto_member_hook_type<VoidPointer>::type splay_set_auto_member_hook_t;
|
||||
typedef typename splay_set_member_hook_type<VoidPointer>::type splay_set_member_hook_t;
|
||||
|
||||
typedef typename bs_set_base_hook_type<VoidPointer>::type bs_set_base_hook_t;
|
||||
typedef typename bs_set_member_hook_type<VoidPointer>::type bs_set_member_hook_t;
|
||||
|
||||
typedef typename avl_set_auto_base_hook_type<VoidPointer>::type avl_set_auto_base_hook_t;
|
||||
typedef typename avl_set_base_hook_type<VoidPointer>::type avl_set_base_hook_t;
|
||||
typedef typename avl_set_auto_member_hook_type<VoidPointer>::type avl_set_auto_member_hook_t;
|
||||
typedef typename avl_set_member_hook_type<VoidPointer>::type avl_set_member_hook_t;
|
||||
|
||||
typedef typename uset_auto_base_hook_type<VoidPointer>::type unordered_set_auto_base_hook_t;
|
||||
typedef typename uset_base_hook_type<VoidPointer>::type unordered_set_base_hook_t;
|
||||
typedef typename uset_auto_member_hook_type<VoidPointer>::type unordered_set_auto_member_hook_t;
|
||||
typedef typename uset_member_hook_type<VoidPointer>::type unordered_set_member_hook_t;
|
||||
|
||||
typedef typename list_auto_base_hook_type<VoidPointer>::type list_auto_base_hook_t;
|
||||
typedef typename list_base_hook_type<VoidPointer>::type list_base_hook_t;
|
||||
typedef typename list_auto_member_hook_type<VoidPointer>::type list_auto_member_hook_t;
|
||||
typedef typename list_member_hook_type<VoidPointer>::type list_member_hook_t;
|
||||
|
||||
typedef typename slist_auto_base_hook_type<VoidPointer>::type slist_auto_base_hook_t;
|
||||
typedef typename slist_base_hook_type<VoidPointer>::type slist_base_hook_t;
|
||||
typedef typename slist_auto_member_hook_type<VoidPointer>::type slist_auto_member_hook_t;
|
||||
typedef typename slist_member_hook_type<VoidPointer>::type slist_member_hook_t;
|
||||
|
||||
//Set members
|
||||
set_member_hook_t set_node_;
|
||||
set_auto_member_hook_t set_auto_node_;
|
||||
|
||||
//SplaySet members
|
||||
splay_set_member_hook_t splay_set_node_;
|
||||
splay_set_auto_member_hook_t splay_set_auto_node_;
|
||||
|
||||
//ScapegoatSet members
|
||||
bs_set_member_hook_t sg_set_node_;
|
||||
|
||||
//AvlSet members
|
||||
avl_set_member_hook_t avl_set_node_;
|
||||
avl_set_auto_member_hook_t avl_set_auto_node_;
|
||||
|
||||
//Unordered set members
|
||||
unordered_set_member_hook_t unordered_set_node_;
|
||||
unordered_set_auto_member_hook_t unordered_set_auto_node_;
|
||||
|
||||
//List members
|
||||
list_member_hook_t list_node_;
|
||||
list_auto_member_hook_t list_auto_node_;
|
||||
|
||||
//Slist members
|
||||
slist_member_hook_t slist_node_;
|
||||
slist_auto_member_hook_t slist_auto_node_;
|
||||
|
||||
int value_;
|
||||
|
||||
static const bool constant_time_size = ConstantTimeSize;
|
||||
|
||||
testvalue()
|
||||
{}
|
||||
|
||||
testvalue(int i)
|
||||
: value_(i)
|
||||
{}
|
||||
|
||||
testvalue (const testvalue& src)
|
||||
: value_ (src.value_)
|
||||
{}
|
||||
|
||||
// testvalue is used in std::vector and thus prev and next
|
||||
// have to be handled appropriately when copied:
|
||||
|
||||
testvalue & operator= (const testvalue& src)
|
||||
{
|
||||
set_base_hook_t::operator=(src);
|
||||
set_auto_base_hook_t::operator=(src);
|
||||
this->set_node_ = src.set_node_;
|
||||
this->set_auto_node_ = src.set_auto_node_;
|
||||
|
||||
splay_set_base_hook_t::operator=(src);
|
||||
splay_set_auto_base_hook_t::operator=(src);
|
||||
this->splay_set_node_ = src.splay_set_node_;
|
||||
this->splay_set_auto_node_ = src.splay_set_auto_node_;
|
||||
|
||||
bs_set_base_hook_t::operator=(src);
|
||||
this->sg_set_node_ = src.sg_set_node_;
|
||||
|
||||
avl_set_base_hook_t::operator=(src);
|
||||
avl_set_auto_base_hook_t::operator=(src);
|
||||
this->avl_set_node_ = src.avl_set_node_;
|
||||
this->avl_set_auto_node_ = src.avl_set_auto_node_;
|
||||
|
||||
unordered_set_base_hook_t::operator=(src);
|
||||
unordered_set_auto_base_hook_t::operator=(src);
|
||||
this->unordered_set_node_ = src.unordered_set_node_;
|
||||
this->unordered_set_auto_node_ = src.unordered_set_auto_node_;
|
||||
|
||||
list_base_hook_t::operator=(src);
|
||||
list_auto_base_hook_t::operator=(src);
|
||||
this->list_node_ = src.list_node_;
|
||||
this->list_auto_node_ = src.list_auto_node_;
|
||||
|
||||
slist_base_hook_t::operator=(src);
|
||||
slist_auto_base_hook_t::operator=(src);
|
||||
this->slist_node_ = src.slist_node_;
|
||||
this->slist_auto_node_ = src.slist_auto_node_;
|
||||
|
||||
value_ = src.value_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void swap_nodes(testvalue &other)
|
||||
{
|
||||
//Set
|
||||
set_base_hook_t::swap_nodes(other);
|
||||
set_auto_base_hook_t::swap_nodes(other);
|
||||
set_node_.swap_nodes(other.set_node_);
|
||||
set_auto_node_.swap_nodes(other.set_auto_node_);
|
||||
|
||||
//SplaySet
|
||||
splay_set_base_hook_t::swap_nodes(other);
|
||||
splay_set_auto_base_hook_t::swap_nodes(other);
|
||||
splay_set_node_.swap_nodes(other.splay_set_node_);
|
||||
splay_set_auto_node_.swap_nodes(other.splay_set_auto_node_);
|
||||
|
||||
//ScapeoatSet
|
||||
bs_set_base_hook_t::swap_nodes(other);
|
||||
sg_set_node_.swap_nodes(other.sg_set_node_);
|
||||
|
||||
//AvlSet
|
||||
avl_set_base_hook_t::swap_nodes(other);
|
||||
avl_set_auto_base_hook_t::swap_nodes(other);
|
||||
avl_set_node_.swap_nodes(other.avl_set_node_);
|
||||
avl_set_auto_node_.swap_nodes(other.avl_set_auto_node_);
|
||||
|
||||
//Unordered set
|
||||
unordered_set_base_hook_t::swap_nodes(other);
|
||||
unordered_set_auto_base_hook_t::swap_nodes(other);
|
||||
unordered_set_node_.swap_nodes(other.unordered_set_node_);
|
||||
unordered_set_auto_node_.swap_nodes(other.unordered_set_auto_node_);
|
||||
|
||||
//List
|
||||
list_base_hook_t::swap_nodes(other);
|
||||
list_auto_base_hook_t::swap_nodes(other);
|
||||
list_node_.swap_nodes(other.list_node_);
|
||||
list_auto_node_.swap_nodes(other.list_auto_node_);
|
||||
|
||||
//Slist
|
||||
slist_base_hook_t::swap_nodes(other);
|
||||
slist_auto_base_hook_t::swap_nodes(other);
|
||||
slist_node_.swap_nodes(other.slist_node_);
|
||||
slist_auto_node_.swap_nodes(other.slist_auto_node_);
|
||||
}
|
||||
|
||||
~testvalue()
|
||||
{}
|
||||
|
||||
bool operator< (const testvalue &other) const
|
||||
{ return value_ < other.value_; }
|
||||
|
||||
bool operator==(const testvalue &other) const
|
||||
{ return value_ == other.value_; }
|
||||
|
||||
friend bool operator< (int other1, const testvalue &other2)
|
||||
{ return other1 < other2.value_; }
|
||||
|
||||
friend bool operator< (const testvalue &other1, int other2)
|
||||
{ return other1.value_ < other2; }
|
||||
|
||||
friend bool operator== (int other1, const testvalue &other2)
|
||||
{ return other1 == other2.value_; }
|
||||
|
||||
friend bool operator== (const testvalue &other1, int other2)
|
||||
{ return other1.value_ == other2; }
|
||||
};
|
||||
|
||||
template<class VoidPointer, bool ConstantTimeSize>
|
||||
std::size_t hash_value(const testvalue<VoidPointer, ConstantTimeSize> &t)
|
||||
{
|
||||
boost::hash<int> hasher;
|
||||
return hasher(t.value_);
|
||||
}
|
||||
|
||||
template<class VoidPointer, bool constant_time_size>
|
||||
std::ostream& operator<<
|
||||
(std::ostream& s, const testvalue<VoidPointer, constant_time_size>& t)
|
||||
{ return s << t.value_; }
|
||||
|
||||
struct even_odd
|
||||
{
|
||||
template<class VoidPointer, bool constant_time_size>
|
||||
bool operator()
|
||||
(const testvalue<VoidPointer, constant_time_size>& v1
|
||||
,const testvalue<VoidPointer, constant_time_size>& v2) const
|
||||
{
|
||||
if ((v1.value_ & 1) == (v2.value_ & 1))
|
||||
return v1.value_ < v2.value_;
|
||||
else
|
||||
return v2.value_ & 1;
|
||||
}
|
||||
};
|
||||
|
||||
} //namespace boost{
|
||||
} //namespace intrusive{
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,414 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Olaf Krzikalla 2004-2006.
|
||||
// (C) Copyright Ion Gaztanaga 2006-2007.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/intrusive for documentation.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/list.hpp>
|
||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||
#include "itestvalue.hpp"
|
||||
#include "smart_ptr.hpp"
|
||||
#include "common_functors.hpp"
|
||||
#include <vector>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include "test_macros.hpp"
|
||||
#include "test_container.hpp"
|
||||
|
||||
using namespace boost::intrusive;
|
||||
|
||||
template<class ValueTraits>
|
||||
struct test_list
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
static void test_all(std::vector<value_type>& values);
|
||||
static void test_front_back(std::vector<value_type>& values);
|
||||
static void test_sort(std::vector<value_type>& values);
|
||||
static void test_insert(std::vector<value_type>& values);
|
||||
static void test_shift(std::vector<value_type>& values);
|
||||
static void test_swap(std::vector<value_type>& values);
|
||||
static void test_clone(std::vector<value_type>& values);
|
||||
static void test_container_from_end(std::vector<value_type>& values);
|
||||
};
|
||||
|
||||
template<class ValueTraits>
|
||||
void test_list<ValueTraits>::test_all(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef list
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, size_type<std::size_t>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> list_type;
|
||||
{
|
||||
list_type list(values.begin(), values.end());
|
||||
test::test_container(list);
|
||||
list.clear();
|
||||
list.insert(list.end(), values.begin(), values.end());
|
||||
test::test_sequence_container(list, values);
|
||||
}
|
||||
|
||||
test_front_back(values);
|
||||
test_sort(values);
|
||||
test_insert(values);
|
||||
test_shift(values);
|
||||
test_swap(values);
|
||||
test_clone(values);
|
||||
test_container_from_end(values);
|
||||
/*
|
||||
const char *list_name = typeid(list_type).name();
|
||||
std::cout << list_name << std::endl << strlen(list_name) << std::endl;
|
||||
const char *value_t = typeid(typename list_type::value_traits).name();
|
||||
std::cout << value_t << std::endl << strlen(value_t) << std::endl;
|
||||
const char *list_it_name = typeid(typename list_type::iterator).name();
|
||||
std::cout << list_it_name << std::endl << strlen(list_it_name ) << std::endl;
|
||||
*/
|
||||
}
|
||||
|
||||
//test: push_front, pop_front, push_back, pop_back, front, back, size, empty:
|
||||
template<class ValueTraits>
|
||||
void test_list<ValueTraits>
|
||||
::test_front_back(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 testlist;
|
||||
BOOST_TEST (testlist.empty());
|
||||
|
||||
testlist.push_back (values[0]);
|
||||
BOOST_TEST (testlist.size() == 1);
|
||||
BOOST_TEST (&testlist.front() == &values[0]);
|
||||
BOOST_TEST (&testlist.back() == &values[0]);
|
||||
|
||||
testlist.push_front (values[1]);
|
||||
BOOST_TEST (testlist.size() == 2);
|
||||
BOOST_TEST (&testlist.front() == &values[1]);
|
||||
BOOST_TEST (&testlist.back() == &values[0]);
|
||||
|
||||
testlist.pop_back();
|
||||
BOOST_TEST (testlist.size() == 1);
|
||||
const list_type &const_testlist = testlist;
|
||||
BOOST_TEST (&const_testlist.front() == &values[1]);
|
||||
BOOST_TEST (&const_testlist.back() == &values[1]);
|
||||
|
||||
testlist.pop_front();
|
||||
BOOST_TEST (testlist.empty());
|
||||
}
|
||||
|
||||
|
||||
//test: constructor, iterator, reverse_iterator, sort, reverse:
|
||||
template<class ValueTraits>
|
||||
void test_list<ValueTraits>
|
||||
::test_sort(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 testlist(values.begin(), values.end());
|
||||
|
||||
{ int init_values [] = { 1, 2, 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist.begin() ); }
|
||||
|
||||
testlist.sort (even_odd());
|
||||
{ int init_values [] = { 5, 3, 1, 4, 2 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist.rbegin() ); }
|
||||
|
||||
testlist.reverse();
|
||||
{ int init_values [] = { 5, 3, 1, 4, 2 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist.begin() ); }
|
||||
}
|
||||
|
||||
//test: assign, insert, const_iterator, const_reverse_iterator, erase, s_iterator_to:
|
||||
template<class ValueTraits>
|
||||
void test_list<ValueTraits>
|
||||
::test_insert(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef list
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, size_type<std::size_t>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> list_type;
|
||||
list_type testlist;
|
||||
testlist.assign (&values[0] + 2, &values[0] + 5);
|
||||
|
||||
const list_type& const_testlist = testlist;
|
||||
{ int init_values [] = { 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, const_testlist.begin() ); }
|
||||
|
||||
typename list_type::iterator i = ++testlist.begin();
|
||||
BOOST_TEST (i->value_ == 4);
|
||||
|
||||
{
|
||||
typename list_type::const_iterator ci = typename list_type::iterator();
|
||||
//typename list_type::iterator i = typename list_type::const_iterator();
|
||||
}
|
||||
|
||||
testlist.insert (i, values[0]);
|
||||
{ int init_values [] = { 5, 4, 1, 3 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, const_testlist.rbegin() ); }
|
||||
|
||||
i = testlist.iterator_to (values[4]);
|
||||
BOOST_TEST (&*i == &values[4]);
|
||||
|
||||
i = list_type::s_iterator_to (values[4]);
|
||||
BOOST_TEST (&*i == &values[4]);
|
||||
|
||||
i = testlist.erase (i);
|
||||
BOOST_TEST (i == testlist.end());
|
||||
|
||||
{ int init_values [] = { 3, 1, 4 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, const_testlist.begin() ); }
|
||||
}
|
||||
|
||||
template<class ValueTraits>
|
||||
void test_list<ValueTraits>
|
||||
::test_shift(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 testlist;
|
||||
const int num_values = (int)values.size();
|
||||
std::vector<int> expected_values(num_values);
|
||||
|
||||
//Shift forward all possible positions 3 times
|
||||
for(int i = 0; i < num_values*3; ++i){
|
||||
testlist.assign(values.begin(), values.end());
|
||||
testlist.shift_forward(i);
|
||||
for(int j = 0; j < num_values; ++j){
|
||||
expected_values[(j + num_values - i%num_values) % num_values] = (j + 1);
|
||||
}
|
||||
TEST_INTRUSIVE_SEQUENCE_EXPECTED(expected_values, testlist.begin());
|
||||
testlist.clear();
|
||||
}
|
||||
|
||||
//Shift backwards all possible positions
|
||||
for(int i = 0; i < num_values*3; ++i){
|
||||
testlist.assign(values.begin(), values.end());
|
||||
testlist.shift_backwards(i);
|
||||
for(int j = 0; j < num_values; ++j){
|
||||
expected_values[(j + i) % num_values] = (j + 1);
|
||||
}
|
||||
TEST_INTRUSIVE_SEQUENCE_EXPECTED(expected_values, testlist.begin());
|
||||
testlist.clear();
|
||||
}
|
||||
}
|
||||
|
||||
//test: insert (seq-version), swap, splice, erase (seq-version):
|
||||
template<class ValueTraits>
|
||||
void test_list<ValueTraits>
|
||||
::test_swap(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] + 2);
|
||||
list_type testlist2;
|
||||
testlist2.insert (testlist2.end(), &values[0] + 2, &values[0] + 5);
|
||||
testlist1.swap (testlist2);
|
||||
|
||||
{ int init_values [] = { 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
|
||||
{ int init_values [] = { 1, 2 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); }
|
||||
|
||||
testlist2.splice (++testlist2.begin(), testlist1);
|
||||
{ int init_values [] = { 1, 3, 4, 5, 2 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); }
|
||||
|
||||
BOOST_TEST (testlist1.empty());
|
||||
|
||||
testlist1.splice (testlist1.end(), testlist2, ++(++testlist2.begin()));
|
||||
{ int init_values [] = { 4 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
|
||||
|
||||
{ int init_values [] = { 1, 3, 5, 2 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); }
|
||||
|
||||
testlist1.splice (testlist1.end(), testlist2,
|
||||
testlist2.begin(), ----testlist2.end());
|
||||
{ int init_values [] = { 4, 1, 3 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
|
||||
{ int init_values [] = { 5, 2 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); }
|
||||
|
||||
testlist1.erase (testlist1.iterator_to(values[0]), testlist1.end());
|
||||
BOOST_TEST (testlist1.size() == 1);
|
||||
BOOST_TEST (&testlist1.front() == &values[3]);
|
||||
}
|
||||
{
|
||||
list_type testlist1 (&values[0], &values[0] + 2);
|
||||
list_type testlist2 (&values[0] + 3, &values[0] + 5);
|
||||
|
||||
values[0].swap_nodes(values[2]);
|
||||
{ int init_values [] = { 3, 2 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
|
||||
|
||||
values[2].swap_nodes(values[4]);
|
||||
{ int init_values [] = { 5, 2 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
|
||||
{ int init_values [] = { 4, 3 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); }
|
||||
}
|
||||
}
|
||||
|
||||
template<class ValueTraits>
|
||||
void test_list<ValueTraits>
|
||||
::test_container_from_end(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef list
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, size_type<std::size_t>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> list_type;
|
||||
list_type testlist1 (&values[0], &values[0] + values.size());
|
||||
BOOST_TEST (testlist1 == list_type::container_from_end_iterator(testlist1.end()));
|
||||
BOOST_TEST (testlist1 == list_type::container_from_end_iterator(testlist1.cend()));
|
||||
}
|
||||
|
||||
|
||||
template<class ValueTraits>
|
||||
void test_list<ValueTraits>
|
||||
::test_clone(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef list
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, size_type<std::size_t>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> list_type;
|
||||
list_type testlist1 (&values[0], &values[0] + values.size());
|
||||
list_type testlist2;
|
||||
|
||||
testlist2.clone_from(testlist1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
|
||||
BOOST_TEST (testlist2 == testlist1);
|
||||
testlist2.clear_and_dispose(test::delete_disposer<value_type>());
|
||||
BOOST_TEST (testlist2.empty());
|
||||
}
|
||||
|
||||
template<class VoidPointer, bool constant_time_size>
|
||||
class test_main_template
|
||||
{
|
||||
public:
|
||||
int operator()()
|
||||
{
|
||||
typedef testvalue<VoidPointer, constant_time_size> value_type;
|
||||
std::vector<value_type> data (5);
|
||||
for (int i = 0; i < 5; ++i)
|
||||
data[i].value_ = i + 1;
|
||||
|
||||
test_list < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::list_base_hook_t
|
||||
>::type
|
||||
>::test_all(data);
|
||||
test_list < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::list_member_hook_t
|
||||
, &value_type::list_node_
|
||||
>
|
||||
>::type
|
||||
>::test_all(data);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
template<class VoidPointer>
|
||||
class test_main_template<VoidPointer, false>
|
||||
{
|
||||
public:
|
||||
int operator()()
|
||||
{
|
||||
typedef testvalue<VoidPointer, false> value_type;
|
||||
std::vector<value_type> data (5);
|
||||
for (int i = 0; i < 5; ++i)
|
||||
data[i].value_ = i + 1;
|
||||
|
||||
test_list < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::list_base_hook_t
|
||||
>::type
|
||||
>::test_all(data);
|
||||
|
||||
test_list < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::list_member_hook_t
|
||||
, &value_type::list_node_
|
||||
>
|
||||
>::type
|
||||
>::test_all(data);
|
||||
/*
|
||||
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 detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::list_auto_member_hook_t
|
||||
, &value_type::list_auto_node_
|
||||
>
|
||||
>::type
|
||||
>::test_all(data);
|
||||
/*
|
||||
test_list<stateful_value_traits
|
||||
< value_type
|
||||
, list_node_traits<VoidPointer>
|
||||
, auto_unlink>
|
||||
>::test_all(data);
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
int main( int, char* [] )
|
||||
{
|
||||
test_main_template<void*, false>()();
|
||||
test_main_template<smart_ptr<void>, false>()();
|
||||
test_main_template<void*, true>()();
|
||||
test_main_template<smart_ptr<void>, true>()();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
@@ -0,0 +1,147 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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 containers
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Olaf Krzikalla 2004-2006.
|
||||
// (C) Copyright Ion Gaztanaga 2006-2007.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/intrusive for documentation.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/set.hpp>
|
||||
#include "itestvalue.hpp"
|
||||
#include "smart_ptr.hpp"
|
||||
#include "generic_multiset_test.hpp"
|
||||
|
||||
template< class ValueType
|
||||
, class Option1 = boost::intrusive::none
|
||||
, class Option2 = boost::intrusive::none
|
||||
, class Option3 = boost::intrusive::none
|
||||
>
|
||||
struct GetContainer
|
||||
{
|
||||
typedef boost::intrusive::multiset
|
||||
< ValueType
|
||||
, Option1
|
||||
, Option2
|
||||
, Option3
|
||||
> type;
|
||||
};
|
||||
|
||||
template<class VoidPointer, bool constant_time_size>
|
||||
class test_main_template
|
||||
{
|
||||
public:
|
||||
int operator()()
|
||||
{
|
||||
using namespace boost::intrusive;
|
||||
typedef testvalue<VoidPointer, constant_time_size> value_type;
|
||||
|
||||
test::test_generic_multiset < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::set_base_hook_t
|
||||
>::type
|
||||
, GetContainer
|
||||
>::test_all();
|
||||
test::test_generic_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
|
||||
, GetContainer
|
||||
>::test_all();
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
template<class VoidPointer>
|
||||
class test_main_template<VoidPointer, false>
|
||||
{
|
||||
public:
|
||||
int operator()()
|
||||
{
|
||||
using namespace boost::intrusive;
|
||||
typedef testvalue<VoidPointer, false> value_type;
|
||||
|
||||
test::test_generic_multiset < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::set_base_hook_t
|
||||
>::type
|
||||
, GetContainer
|
||||
>::test_all();
|
||||
|
||||
test::test_generic_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
|
||||
, GetContainer
|
||||
>::test_all();
|
||||
|
||||
test::test_generic_multiset < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::set_auto_base_hook_t
|
||||
>::type
|
||||
, GetContainer
|
||||
>::test_all();
|
||||
|
||||
test::test_generic_multiset < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::set_auto_member_hook_t
|
||||
, &value_type::set_auto_node_
|
||||
>
|
||||
>::type
|
||||
, GetContainer
|
||||
>::test_all();
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
int main( int, char* [] )
|
||||
{
|
||||
test_main_template<void*, false>()();
|
||||
test_main_template<boost::intrusive::smart_ptr<void>, false>()();
|
||||
test_main_template<void*, true>()();
|
||||
test_main_template<boost::intrusive::smart_ptr<void>, true>()();
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
@@ -0,0 +1,118 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Olaf Krzikalla 2004-2006.
|
||||
// (C) Copyright Ion Gaztanaga 2006-2007.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/intrusive for documentation.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/set.hpp>
|
||||
#include "itestvalue.hpp"
|
||||
#include "smart_ptr.hpp"
|
||||
#include "generic_set_test.hpp"
|
||||
|
||||
template< class ValueType
|
||||
, class Option1 = boost::intrusive::none
|
||||
, class Option2 = boost::intrusive::none
|
||||
, class Option3 = boost::intrusive::none
|
||||
>
|
||||
struct GetContainer
|
||||
{
|
||||
typedef boost::intrusive::set
|
||||
< ValueType
|
||||
, Option1
|
||||
, Option2
|
||||
, Option3
|
||||
> type;
|
||||
};
|
||||
|
||||
template<class VoidPointer, bool constant_time_size>
|
||||
class test_main_template
|
||||
{
|
||||
public:
|
||||
int operator()()
|
||||
{
|
||||
using namespace boost::intrusive;
|
||||
typedef testvalue<VoidPointer, constant_time_size> value_type;
|
||||
|
||||
test::test_generic_set < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::set_base_hook_t
|
||||
>::type
|
||||
, GetContainer
|
||||
>::test_all();
|
||||
test::test_generic_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
|
||||
, GetContainer
|
||||
>::test_all();
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
template<class VoidPointer>
|
||||
class test_main_template<VoidPointer, false>
|
||||
{
|
||||
public:
|
||||
int operator()()
|
||||
{
|
||||
using namespace boost::intrusive;
|
||||
typedef testvalue<VoidPointer, false> value_type;
|
||||
|
||||
test::test_generic_set < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::set_base_hook_t
|
||||
>::type
|
||||
, GetContainer
|
||||
>::test_all();
|
||||
|
||||
test::test_generic_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
|
||||
, GetContainer
|
||||
>::test_all();
|
||||
|
||||
test::test_generic_set < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::set_auto_base_hook_t
|
||||
>::type
|
||||
, GetContainer
|
||||
>::test_all();
|
||||
|
||||
test::test_generic_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
|
||||
, GetContainer
|
||||
>::test_all();
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
int main( int, char* [] )
|
||||
{
|
||||
|
||||
test_main_template<void*, false>()();
|
||||
test_main_template<boost::intrusive::smart_ptr<void>, false>()();
|
||||
test_main_template<void*, true>()();
|
||||
test_main_template<boost::intrusive::smart_ptr<void>, true>()();
|
||||
return boost::report_errors();
|
||||
}
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
@@ -0,0 +1,108 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Olaf Krzikalla 2004-2006.
|
||||
// (C) Copyright Ion Gaztanaga 2006-2007.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/intrusive for documentation.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/sg_set.hpp>
|
||||
#include "itestvalue.hpp"
|
||||
#include "smart_ptr.hpp"
|
||||
#include "generic_multiset_test.hpp"
|
||||
|
||||
namespace boost { namespace intrusive { namespace test {
|
||||
|
||||
template<class T, class O1, class O2, class O3, class O4>
|
||||
struct has_rebalance<boost::intrusive::sg_multiset<T, O1, O2, O3, O4> >
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
template< class ValueType
|
||||
, class Option1 = boost::intrusive::none
|
||||
, class Option2 = boost::intrusive::none
|
||||
, class Option3 = boost::intrusive::none
|
||||
>
|
||||
struct GetContainer
|
||||
{
|
||||
typedef boost::intrusive::sg_multiset
|
||||
< ValueType
|
||||
, Option1
|
||||
, Option2
|
||||
, Option3
|
||||
> type;
|
||||
};
|
||||
|
||||
template< class ValueType
|
||||
, class Option1 = boost::intrusive::none
|
||||
, class Option2 = boost::intrusive::none
|
||||
, class Option3 = boost::intrusive::none
|
||||
>
|
||||
struct GetContainerFixedAlpha
|
||||
{
|
||||
typedef boost::intrusive::sg_multiset
|
||||
< ValueType
|
||||
, Option1
|
||||
, Option2
|
||||
, Option3
|
||||
, boost::intrusive::floating_point<false>
|
||||
> type;
|
||||
};
|
||||
|
||||
template<class VoidPointer>
|
||||
class test_main_template
|
||||
{
|
||||
public:
|
||||
int operator()()
|
||||
{
|
||||
using namespace boost::intrusive;
|
||||
typedef testvalue<VoidPointer, true> value_type;
|
||||
|
||||
test::test_generic_multiset < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::bs_set_base_hook_t
|
||||
>::type
|
||||
, GetContainer
|
||||
>::test_all();
|
||||
test::test_generic_multiset < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::bs_set_member_hook_t
|
||||
, &value_type::sg_set_node_
|
||||
>
|
||||
>::type
|
||||
, GetContainer
|
||||
>::test_all();
|
||||
test::test_generic_multiset < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::bs_set_base_hook_t
|
||||
>::type
|
||||
, GetContainerFixedAlpha
|
||||
>::test_all();
|
||||
test::test_generic_multiset < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::bs_set_member_hook_t
|
||||
, &value_type::sg_set_node_
|
||||
>
|
||||
>::type
|
||||
, GetContainerFixedAlpha
|
||||
>::test_all();
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
int main( int, char* [] )
|
||||
{
|
||||
test_main_template<void*>()();
|
||||
test_main_template<boost::intrusive::smart_ptr<void> >()();
|
||||
return boost::report_errors();
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2007.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/intrusive for documentation.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/sg_set.hpp>
|
||||
#include "itestvalue.hpp"
|
||||
#include "smart_ptr.hpp"
|
||||
#include "generic_set_test.hpp"
|
||||
|
||||
namespace boost { namespace intrusive { namespace test {
|
||||
|
||||
template<class T, class O1, class O2, class O3, class O4>
|
||||
struct has_rebalance<boost::intrusive::sg_set<T, O1, O2, O3, O4> >
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
template< class ValueType
|
||||
, class Option1 = boost::intrusive::none
|
||||
, class Option2 = boost::intrusive::none
|
||||
, class Option3 = boost::intrusive::none
|
||||
>
|
||||
struct GetContainer
|
||||
{
|
||||
typedef boost::intrusive::sg_set
|
||||
< ValueType
|
||||
, Option1
|
||||
, Option2
|
||||
, Option3
|
||||
> type;
|
||||
};
|
||||
|
||||
template< class ValueType
|
||||
, class Option1 = boost::intrusive::none
|
||||
, class Option2 = boost::intrusive::none
|
||||
, class Option3 = boost::intrusive::none
|
||||
>
|
||||
struct GetContainerFixedAlpha
|
||||
{
|
||||
typedef boost::intrusive::sg_set
|
||||
< ValueType
|
||||
, Option1
|
||||
, Option2
|
||||
, Option3
|
||||
, boost::intrusive::floating_point<false>
|
||||
> type;
|
||||
};
|
||||
|
||||
template<class VoidPointer>
|
||||
class test_main_template
|
||||
{
|
||||
public:
|
||||
int operator()()
|
||||
{
|
||||
using namespace boost::intrusive;
|
||||
typedef testvalue<VoidPointer, true> value_type;
|
||||
|
||||
test::test_generic_set < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::bs_set_base_hook_t
|
||||
>::type
|
||||
, GetContainer
|
||||
>::test_all();
|
||||
test::test_generic_set < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::bs_set_member_hook_t
|
||||
, &value_type::sg_set_node_
|
||||
>
|
||||
>::type
|
||||
, GetContainer
|
||||
>::test_all();
|
||||
|
||||
test::test_generic_set < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::bs_set_base_hook_t
|
||||
>::type
|
||||
, GetContainerFixedAlpha
|
||||
>::test_all();
|
||||
test::test_generic_set < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::bs_set_member_hook_t
|
||||
, &value_type::sg_set_node_
|
||||
>
|
||||
>::type
|
||||
, GetContainerFixedAlpha
|
||||
>::test_all();
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
int main( int, char* [] )
|
||||
{
|
||||
test_main_template<void*>()();
|
||||
test_main_template<boost::intrusive::smart_ptr<void> >()();
|
||||
return boost::report_errors();
|
||||
}
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
@@ -0,0 +1,449 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Olaf Krzikalla 2004-2006.
|
||||
// (C) Copyright Ion Gaztanaga 2006-2007.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/intrusive for documentation.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/slist.hpp>
|
||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||
#include "itestvalue.hpp"
|
||||
#include "smart_ptr.hpp"
|
||||
#include "common_functors.hpp"
|
||||
#include <vector>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include "test_macros.hpp"
|
||||
#include "test_container.hpp"
|
||||
|
||||
using namespace boost::intrusive;
|
||||
|
||||
template<class ValueTraits>
|
||||
struct test_slist
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
static void test_all (std::vector<value_type>& values);
|
||||
static void test_front_back (std::vector<value_type>& values);
|
||||
static void test_sort(std::vector<value_type>& values);
|
||||
static void test_merge (std::vector<value_type>& values);
|
||||
static void test_insert(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_slow_insert (std::vector<value_type>& values);
|
||||
static void test_clone (std::vector<value_type>& values);
|
||||
static void test_container_from_end(std::vector<value_type> &values);
|
||||
};
|
||||
|
||||
template<class ValueTraits>
|
||||
void test_slist<ValueTraits>
|
||||
::test_all (std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef slist
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, size_type<std::size_t>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> list_type;
|
||||
{
|
||||
list_type list(values.begin(), values.end());
|
||||
test::test_container(list);
|
||||
list.clear();
|
||||
list.insert(list.end(), values.begin(), values.end());
|
||||
test::test_sequence_container(list, values);
|
||||
}
|
||||
test_front_back (values);
|
||||
test_sort(values);
|
||||
test_merge (values);
|
||||
test_insert(values);
|
||||
test_shift(values);
|
||||
test_slow_insert (values);
|
||||
test_swap(values);
|
||||
test_clone(values);
|
||||
test_container_from_end(values);
|
||||
}
|
||||
|
||||
//test: push_front, pop_front, front, size, empty:
|
||||
template<class ValueTraits>
|
||||
void test_slist<ValueTraits>
|
||||
::test_front_back (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 testlist;
|
||||
BOOST_TEST (testlist.empty());
|
||||
|
||||
testlist.push_front (values[0]);
|
||||
BOOST_TEST (testlist.size() == 1);
|
||||
BOOST_TEST (&testlist.front() == &values[0]);
|
||||
|
||||
testlist.push_front (values[1]);
|
||||
BOOST_TEST (testlist.size() == 2);
|
||||
BOOST_TEST (&testlist.front() == &values[1]);
|
||||
|
||||
testlist.pop_front();
|
||||
BOOST_TEST (testlist.size() == 1);
|
||||
BOOST_TEST (&testlist.front() == &values[0]);
|
||||
|
||||
testlist.pop_front();
|
||||
BOOST_TEST (testlist.empty());
|
||||
}
|
||||
|
||||
//test: merge due to error in merge implementation:
|
||||
template<class ValueTraits>
|
||||
void test_slist<ValueTraits>
|
||||
::test_merge (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, testlist2;
|
||||
testlist1.push_front (values[0]);
|
||||
testlist2.push_front (values[4]);
|
||||
testlist2.push_front (values[3]);
|
||||
testlist2.push_front (values[2]);
|
||||
testlist1.merge (testlist2);
|
||||
|
||||
int init_values [] = { 1, 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() );
|
||||
}
|
||||
|
||||
//test: constructor, iterator, sort, reverse:
|
||||
template<class ValueTraits>
|
||||
void test_slist<ValueTraits>
|
||||
::test_sort(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 testlist (values.begin(), values.end());
|
||||
|
||||
{ int init_values [] = { 1, 2, 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist.begin() ); }
|
||||
|
||||
testlist.sort (even_odd());
|
||||
{ int init_values [] = { 2, 4, 1, 3, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist.begin() ); }
|
||||
|
||||
testlist.reverse();
|
||||
{ int init_values [] = { 5, 3, 1, 4, 2, };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist.begin() ); }
|
||||
}
|
||||
|
||||
//test: assign, insert_after, const_iterator, erase_after, s_iterator_to, previous:
|
||||
template<class ValueTraits>
|
||||
void test_slist<ValueTraits>
|
||||
::test_insert(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef slist
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, size_type<std::size_t>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> list_type;
|
||||
list_type testlist;
|
||||
testlist.assign (&values[0] + 2, &values[0] + 5);
|
||||
|
||||
const list_type& const_testlist = testlist;
|
||||
{ int init_values [] = { 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, const_testlist.begin() ); }
|
||||
|
||||
typename list_type::iterator i = ++testlist.begin();
|
||||
BOOST_TEST (i->value_ == 4);
|
||||
|
||||
testlist.insert_after (i, values[0]);
|
||||
{ int init_values [] = { 3, 4, 1, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, const_testlist.begin() ); }
|
||||
|
||||
i = testlist.iterator_to (values[4]);
|
||||
BOOST_TEST (&*i == &values[4]);
|
||||
i = list_type::s_iterator_to (values[4]);
|
||||
BOOST_TEST (&*i == &values[4]);
|
||||
i = testlist.previous (i);
|
||||
BOOST_TEST (&*i == &values[0]);
|
||||
|
||||
testlist.erase_after (i);
|
||||
BOOST_TEST (&*i == &values[0]);
|
||||
{ int init_values [] = { 3, 4, 1 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, const_testlist.begin() ); }
|
||||
}
|
||||
|
||||
//test: insert, const_iterator, erase, siterator_to:
|
||||
template<class ValueTraits>
|
||||
void test_slist<ValueTraits>
|
||||
::test_slow_insert (std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef slist
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, size_type<std::size_t>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> list_type;
|
||||
list_type testlist;
|
||||
testlist.push_front (values[4]);
|
||||
testlist.insert (testlist.begin(), &values[0] + 2, &values[0] + 4);
|
||||
|
||||
const list_type& const_testlist = testlist;
|
||||
{ int init_values [] = { 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, const_testlist.begin() ); }
|
||||
|
||||
typename list_type::iterator i = ++testlist.begin();
|
||||
BOOST_TEST (i->value_ == 4);
|
||||
|
||||
testlist.insert (i, values[0]);
|
||||
{ int init_values [] = { 3, 1, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, const_testlist.begin() ); }
|
||||
|
||||
i = testlist.iterator_to (values[4]);
|
||||
BOOST_TEST (&*i == &values[4]);
|
||||
|
||||
i = list_type::s_iterator_to (values[4]);
|
||||
BOOST_TEST (&*i == &values[4]);
|
||||
|
||||
i = testlist.erase (i);
|
||||
BOOST_TEST (i == testlist.end());
|
||||
|
||||
{ int init_values [] = { 3, 1, 4 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, const_testlist.begin() ); }
|
||||
|
||||
testlist.erase (++testlist.begin(), testlist.end());
|
||||
BOOST_TEST (testlist.size() == 1);
|
||||
BOOST_TEST (testlist.front().value_ == 3);
|
||||
}
|
||||
|
||||
template<class ValueTraits>
|
||||
void test_slist<ValueTraits>
|
||||
::test_shift(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 testlist;
|
||||
|
||||
const int num_values = (int)values.size();
|
||||
std::vector<int> expected_values(num_values);
|
||||
|
||||
//Shift forward all possible positions 3 times
|
||||
for(int i = 0; i < num_values*3; ++i){
|
||||
testlist.assign(values.begin(), values.end());
|
||||
testlist.shift_forward(i);
|
||||
for(int j = 0; j < num_values; ++j){
|
||||
expected_values[(j + num_values - i%num_values) % num_values] = (j + 1);
|
||||
}
|
||||
|
||||
TEST_INTRUSIVE_SEQUENCE_EXPECTED(expected_values, testlist.begin())
|
||||
testlist.clear();
|
||||
}
|
||||
|
||||
//Shift backwards all possible positions
|
||||
for(int i = 0; i < num_values*3; ++i){
|
||||
testlist.assign(values.begin(), values.end());
|
||||
testlist.shift_backwards(i);
|
||||
for(int j = 0; j < num_values; ++j){
|
||||
expected_values[(j + i) % num_values] = (j + 1);
|
||||
}
|
||||
|
||||
TEST_INTRUSIVE_SEQUENCE_EXPECTED(expected_values, testlist.begin())
|
||||
testlist.clear();
|
||||
}
|
||||
}
|
||||
|
||||
//test: insert_after (seq-version), swap, splice_after:
|
||||
template<class ValueTraits>
|
||||
void test_slist<ValueTraits>
|
||||
::test_swap(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] + 2);
|
||||
list_type testlist2;
|
||||
testlist2.insert_after (testlist2.end(), &values[0] + 2, &values[0] + 5);
|
||||
testlist1.swap(testlist2);
|
||||
{ int init_values [] = { 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
|
||||
{ int init_values [] = { 1, 2 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); }
|
||||
testlist2.splice_after (testlist2.begin(), testlist1);
|
||||
{ int init_values [] = { 1, 3, 4, 5, 2 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); }
|
||||
BOOST_TEST (testlist1.empty());
|
||||
|
||||
testlist1.splice_after (testlist1.end(), testlist2, ++testlist2.begin());
|
||||
{ int init_values [] = { 4 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
|
||||
{ int init_values [] = { 1, 3, 5, 2 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); }
|
||||
|
||||
testlist1.splice_after (testlist1.begin(), testlist2,
|
||||
testlist2.end(), ++++testlist2.begin());
|
||||
{ int init_values [] = { 4, 1, 3, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
|
||||
{ int init_values [] = { 2 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); }
|
||||
}
|
||||
{
|
||||
list_type testlist1 (&values[0], &values[0] + 2);
|
||||
list_type testlist2 (&values[0] + 3, &values[0] + 5);
|
||||
|
||||
values[0].swap_nodes(values[2]);
|
||||
{ int init_values [] = { 3, 2 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
|
||||
|
||||
values[2].swap_nodes(values[4]);
|
||||
{ int init_values [] = { 5, 2 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); }
|
||||
{ int init_values [] = { 4, 3 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); }
|
||||
}
|
||||
}
|
||||
|
||||
template<class ValueTraits>
|
||||
void test_slist<ValueTraits>
|
||||
::test_clone(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());
|
||||
list_type testlist2;
|
||||
|
||||
testlist2.clone_from(testlist1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
|
||||
BOOST_TEST (testlist2 == testlist1);
|
||||
testlist2.clear_and_dispose(test::delete_disposer<value_type>());
|
||||
BOOST_TEST (testlist2.empty());
|
||||
}
|
||||
|
||||
template<class ValueTraits>
|
||||
void test_slist<ValueTraits>
|
||||
::test_container_from_end(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef slist
|
||||
< value_type
|
||||
, value_traits<ValueTraits>
|
||||
, size_type<std::size_t>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> list_type;
|
||||
list_type testlist1 (&values[0], &values[0] + values.size());
|
||||
BOOST_TEST (testlist1 == list_type::container_from_end_iterator(testlist1.end()));
|
||||
BOOST_TEST (testlist1 == list_type::container_from_end_iterator(testlist1.cend()));
|
||||
}
|
||||
|
||||
template<class VoidPointer, bool constant_time_size>
|
||||
class test_main_template
|
||||
{
|
||||
public:
|
||||
int operator()()
|
||||
{
|
||||
typedef testvalue<VoidPointer, constant_time_size> value_type;
|
||||
std::vector<value_type> data (5);
|
||||
for (int i = 0; i < 5; ++i)
|
||||
data[i].value_ = i + 1;
|
||||
|
||||
test_slist < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::slist_base_hook_t
|
||||
>::type
|
||||
>::test_all(data);
|
||||
test_slist < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::slist_member_hook_t
|
||||
, &value_type::slist_node_
|
||||
>
|
||||
>::type
|
||||
>::test_all(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
template<class VoidPointer>
|
||||
class test_main_template<VoidPointer, false>
|
||||
{
|
||||
public:
|
||||
int operator()()
|
||||
{
|
||||
typedef testvalue<VoidPointer, false> value_type;
|
||||
std::vector<value_type> data (5);
|
||||
for (int i = 0; i < 5; ++i)
|
||||
data[i].value_ = i + 1;
|
||||
|
||||
test_slist < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::slist_base_hook_t
|
||||
>::type
|
||||
>::test_all(data);
|
||||
|
||||
test_slist < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::slist_member_hook_t
|
||||
, &value_type::slist_node_
|
||||
>
|
||||
>::type
|
||||
>::test_all(data);
|
||||
|
||||
test_slist < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::slist_auto_base_hook_t
|
||||
>::type
|
||||
>::test_all(data);
|
||||
|
||||
test_slist < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::slist_auto_member_hook_t
|
||||
, &value_type::slist_auto_node_
|
||||
>
|
||||
>::type
|
||||
>::test_all(data);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
int main(int, char* [])
|
||||
{
|
||||
test_main_template<void*, false>()();
|
||||
test_main_template<smart_ptr<void>, false>()();
|
||||
test_main_template<void*, true>()();
|
||||
test_main_template<smart_ptr<void>, true>()();
|
||||
return boost::report_errors();
|
||||
}
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
@@ -0,0 +1,422 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/intrusive for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTRUSIVE_SMART_PTR_HPP
|
||||
#define BOOST_INTRUSIVE_SMART_PTR_HPP
|
||||
|
||||
#include <boost/iterator.hpp>
|
||||
#include <boost/intrusive/pointer_plus_bit.hpp>
|
||||
#include <boost/intrusive/pointer_plus_2_bits.hpp>
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
namespace boost{
|
||||
namespace intrusive{
|
||||
|
||||
namespace detail {
|
||||
|
||||
struct static_cast_tag {};
|
||||
struct const_cast_tag {};
|
||||
struct dynamic_cast_tag {};
|
||||
struct reinterpret_cast_tag {};
|
||||
|
||||
} //namespace detail {
|
||||
|
||||
//Empty class
|
||||
struct empty_type{};
|
||||
|
||||
template<class T>
|
||||
struct random_it
|
||||
: public boost::iterator<std::random_access_iterator_tag,
|
||||
T, std::ptrdiff_t, T*, T&>
|
||||
{
|
||||
typedef const T* const_pointer;
|
||||
typedef const T& const_reference;
|
||||
};
|
||||
|
||||
template<> struct random_it<void>
|
||||
{
|
||||
typedef const void * const_pointer;
|
||||
typedef empty_type& reference;
|
||||
typedef const empty_type& const_reference;
|
||||
typedef empty_type difference_type;
|
||||
typedef empty_type iterator_category;
|
||||
};
|
||||
|
||||
template<> struct random_it<const void>
|
||||
{
|
||||
typedef const void * const_pointer;
|
||||
typedef const empty_type & reference;
|
||||
typedef const empty_type & const_reference;
|
||||
typedef empty_type difference_type;
|
||||
typedef empty_type iterator_category;
|
||||
};
|
||||
|
||||
template<> struct random_it<volatile void>
|
||||
{
|
||||
typedef const volatile void * const_pointer;
|
||||
typedef empty_type& reference;
|
||||
typedef const empty_type& const_reference;
|
||||
typedef empty_type difference_type;
|
||||
typedef empty_type iterator_category;
|
||||
};
|
||||
|
||||
template<> struct random_it<const volatile void>
|
||||
{
|
||||
typedef const volatile void * const_pointer;
|
||||
typedef const empty_type & reference;
|
||||
typedef const empty_type & const_reference;
|
||||
typedef empty_type difference_type;
|
||||
typedef empty_type iterator_category;
|
||||
};
|
||||
|
||||
} //namespace intrusive {
|
||||
} //namespace boost {
|
||||
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
|
||||
template <class PointedType>
|
||||
class smart_ptr
|
||||
{
|
||||
typedef random_it<PointedType> random_it_t;
|
||||
typedef smart_ptr<PointedType> self_t;
|
||||
typedef typename random_it_t::const_pointer const_pointer_t;
|
||||
typedef typename random_it_t::const_reference const_reference_t;
|
||||
|
||||
void unspecified_bool_type_func() const {}
|
||||
typedef void (self_t::*unspecified_bool_type)() const;
|
||||
|
||||
public:
|
||||
typedef PointedType * pointer;
|
||||
typedef typename random_it_t::reference reference;
|
||||
typedef PointedType value_type;
|
||||
typedef typename random_it_t::difference_type difference_type;
|
||||
typedef typename random_it_t::iterator_category iterator_category;
|
||||
|
||||
PointedType *m_ptr;
|
||||
|
||||
public: //Public Functions
|
||||
|
||||
//!Constructor from raw pointer (allows "0" pointer conversion). Never throws.
|
||||
smart_ptr(pointer ptr = 0)
|
||||
: m_ptr(ptr)
|
||||
{}
|
||||
|
||||
//!Constructor from other pointer. Never throws.
|
||||
template <class T>
|
||||
smart_ptr(T *ptr)
|
||||
: m_ptr(ptr)
|
||||
{}
|
||||
|
||||
//!Constructor from other smart_ptr
|
||||
smart_ptr(const smart_ptr& ptr)
|
||||
: m_ptr(ptr.m_ptr)
|
||||
{}
|
||||
|
||||
//!Constructor from other smart_ptr. If pointers of pointee types are
|
||||
//!convertible, offset_ptrs will be convertibles. Never throws.
|
||||
template<class T2>
|
||||
smart_ptr(const smart_ptr<T2> &ptr)
|
||||
: m_ptr(ptr.m_ptr)
|
||||
{}
|
||||
|
||||
//!Emulates static_cast operator. Never throws.
|
||||
template<class Y>
|
||||
smart_ptr(const smart_ptr<Y> & r, detail::static_cast_tag)
|
||||
: m_ptr(static_cast<PointedType*>(r.get()))
|
||||
{}
|
||||
|
||||
//!Emulates const_cast operator. Never throws.
|
||||
template<class Y>
|
||||
smart_ptr(const smart_ptr<Y> & r, detail::const_cast_tag)
|
||||
: m_ptr(const_cast<PointedType*>(r.get()))
|
||||
{}
|
||||
|
||||
//!Emulates dynamic_cast operator. Never throws.
|
||||
template<class Y>
|
||||
smart_ptr(const smart_ptr<Y> & r, detail::dynamic_cast_tag)
|
||||
: m_ptr(dynamic_cast<PointedType*>(r.get()))
|
||||
{}
|
||||
|
||||
//!Emulates reinterpret_cast operator. Never throws.
|
||||
template<class Y>
|
||||
smart_ptr(const smart_ptr<Y> & r, detail::reinterpret_cast_tag)
|
||||
: m_ptr(reinterpret_cast<PointedType*>(r.get()))
|
||||
{}
|
||||
|
||||
//!Obtains raw pointer from offset. Never throws.
|
||||
pointer get() const
|
||||
{ return m_ptr; }
|
||||
|
||||
//!Pointer-like -> operator. It can return 0 pointer. Never throws.
|
||||
pointer operator->() const
|
||||
{ return this->get(); }
|
||||
|
||||
//!Dereferencing operator, if it is a null smart_ptr behavior
|
||||
//! is undefined. Never throws.
|
||||
reference operator* () const
|
||||
{ return *(this->get()); }
|
||||
|
||||
//!Indexing operator. Never throws.
|
||||
reference operator[](std::ptrdiff_t idx) const
|
||||
{ return this->get()[idx]; }
|
||||
|
||||
//!Assignment from pointer (saves extra conversion). Never throws.
|
||||
smart_ptr& operator= (pointer from)
|
||||
{ m_ptr = from; return *this; }
|
||||
|
||||
//!Assignment from other smart_ptr. Never throws.
|
||||
smart_ptr& operator= (const smart_ptr & pt)
|
||||
{ m_ptr = pt.m_ptr; return *this; }
|
||||
|
||||
//!Assignment from related smart_ptr. If pointers of pointee types
|
||||
//! are assignable, offset_ptrs will be assignable. Never throws.
|
||||
template <class T2>
|
||||
smart_ptr& operator= (const smart_ptr<T2> & pt)
|
||||
{ m_ptr = pt.m_ptr; return *this; }
|
||||
|
||||
//!smart_ptr + std::ptrdiff_t. Never throws.
|
||||
smart_ptr operator+ (std::ptrdiff_t offset) const
|
||||
{ return smart_ptr(this->get()+offset); }
|
||||
|
||||
//!smart_ptr - std::ptrdiff_t. Never throws.
|
||||
smart_ptr operator- (std::ptrdiff_t offset) const
|
||||
{ return smart_ptr(this->get()-offset); }
|
||||
|
||||
//!smart_ptr += std::ptrdiff_t. Never throws.
|
||||
smart_ptr &operator+= (std::ptrdiff_t offset)
|
||||
{ m_ptr += offset; return *this; }
|
||||
|
||||
//!smart_ptr -= std::ptrdiff_t. Never throws.
|
||||
smart_ptr &operator-= (std::ptrdiff_t offset)
|
||||
{ m_ptr -= offset; return *this; }
|
||||
|
||||
//!++smart_ptr. Never throws.
|
||||
smart_ptr& operator++ (void)
|
||||
{ ++m_ptr; return *this; }
|
||||
|
||||
//!smart_ptr++. Never throws.
|
||||
smart_ptr operator++ (int)
|
||||
{ smart_ptr temp(*this); ++*this; return temp; }
|
||||
|
||||
//!--smart_ptr. Never throws.
|
||||
smart_ptr& operator-- (void)
|
||||
{ --m_ptr; return *this; }
|
||||
|
||||
//!smart_ptr--. Never throws.
|
||||
smart_ptr operator-- (int)
|
||||
{ smart_ptr temp(*this); --*this; return temp; }
|
||||
|
||||
//!safe bool conversion operator. Never throws.
|
||||
operator unspecified_bool_type() const
|
||||
{ return this->get()? &self_t::unspecified_bool_type_func : 0; }
|
||||
|
||||
//!Not operator. Not needed in theory, but improves portability.
|
||||
//!Never throws.
|
||||
bool operator! () const
|
||||
{ return this->get() == 0; }
|
||||
/*
|
||||
friend void swap (smart_ptr &pt, smart_ptr &pt2)
|
||||
{
|
||||
value_type *ptr = pt.get();
|
||||
pt = pt2;
|
||||
pt2 = ptr;
|
||||
}
|
||||
*/
|
||||
};
|
||||
|
||||
//!smart_ptr<T1> == smart_ptr<T2>. Never throws.
|
||||
template<class T1, class T2>
|
||||
inline bool operator== (const smart_ptr<T1> &pt1,
|
||||
const smart_ptr<T2> &pt2)
|
||||
{ return pt1.get() == pt2.get(); }
|
||||
|
||||
//!smart_ptr<T1> != smart_ptr<T2>. Never throws.
|
||||
template<class T1, class T2>
|
||||
inline bool operator!= (const smart_ptr<T1> &pt1,
|
||||
const smart_ptr<T2> &pt2)
|
||||
{ return pt1.get() != pt2.get(); }
|
||||
|
||||
//!smart_ptr<T1> < smart_ptr<T2>. Never throws.
|
||||
template<class T1, class T2>
|
||||
inline bool operator< (const smart_ptr<T1> &pt1,
|
||||
const smart_ptr<T2> &pt2)
|
||||
{ return pt1.get() < pt2.get(); }
|
||||
|
||||
//!smart_ptr<T1> <= smart_ptr<T2>. Never throws.
|
||||
template<class T1, class T2>
|
||||
inline bool operator<= (const smart_ptr<T1> &pt1,
|
||||
const smart_ptr<T2> &pt2)
|
||||
{ return pt1.get() <= pt2.get(); }
|
||||
|
||||
//!smart_ptr<T1> > smart_ptr<T2>. Never throws.
|
||||
template<class T1, class T2>
|
||||
inline bool operator> (const smart_ptr<T1> &pt1,
|
||||
const smart_ptr<T2> &pt2)
|
||||
{ return pt1.get() > pt2.get(); }
|
||||
|
||||
//!smart_ptr<T1> >= smart_ptr<T2>. Never throws.
|
||||
template<class T1, class T2>
|
||||
inline bool operator>= (const smart_ptr<T1> &pt1,
|
||||
const smart_ptr<T2> &pt2)
|
||||
{ return pt1.get() >= pt2.get(); }
|
||||
|
||||
//!operator<<
|
||||
template<class E, class T, class Y>
|
||||
inline std::basic_ostream<E, T> & operator<<
|
||||
(std::basic_ostream<E, T> & os, smart_ptr<Y> const & p)
|
||||
{ return os << p.get(); }
|
||||
|
||||
//!operator>>
|
||||
template<class E, class T, class Y>
|
||||
inline std::basic_istream<E, T> & operator>>
|
||||
(std::basic_istream<E, T> & os, smart_ptr<Y> & p)
|
||||
{ Y * tmp; return os >> tmp; p = tmp; }
|
||||
|
||||
//!std::ptrdiff_t + smart_ptr
|
||||
template<class T>
|
||||
inline smart_ptr<T> operator+(std::ptrdiff_t diff, const smart_ptr<T>& right)
|
||||
{ return right + diff; }
|
||||
|
||||
//!smart_ptr - smart_ptr
|
||||
template<class T, class T2>
|
||||
inline std::ptrdiff_t operator- (const smart_ptr<T> &pt, const smart_ptr<T2> &pt2)
|
||||
{ return pt.get()- pt2.get(); }
|
||||
|
||||
//!swap specialization
|
||||
template<class T>
|
||||
inline void swap (smart_ptr<T> &pt,
|
||||
smart_ptr<T> &pt2)
|
||||
{
|
||||
typename smart_ptr<T>::value_type *ptr = pt.get();
|
||||
pt = pt2;
|
||||
pt2 = ptr;
|
||||
}
|
||||
|
||||
//!detail::get_pointer() enables boost::mem_fn to recognize smart_ptr.
|
||||
//!Never throws.
|
||||
template<class T>
|
||||
inline T* get_pointer(const smart_ptr<T> & p)
|
||||
{ return p.get(); }
|
||||
|
||||
//!Simulation of static_cast between pointers. Never throws.
|
||||
template<class T, class U>
|
||||
inline smart_ptr<T>
|
||||
static_pointer_cast(smart_ptr<U> const & r)
|
||||
{
|
||||
return smart_ptr<T>(r, detail::static_cast_tag());
|
||||
}
|
||||
|
||||
//!Simulation of const_cast between pointers. Never throws.
|
||||
template<class T, class U>
|
||||
inline smart_ptr<T>const_pointer_cast(smart_ptr<U> const & r)
|
||||
{
|
||||
return smart_ptr<T>(r, detail::const_cast_tag());
|
||||
}
|
||||
|
||||
//!Simulation of dynamic_cast between pointers. Never throws.
|
||||
template<class T, class U>
|
||||
inline smart_ptr<T>
|
||||
dynamic_pointer_cast(smart_ptr<U> const & r)
|
||||
{
|
||||
return smart_ptr<T>
|
||||
(r, detail::dynamic_cast_tag());
|
||||
}
|
||||
|
||||
//!Simulation of reinterpret_cast between pointers. Never throws.
|
||||
template<class T, class U>
|
||||
inline smart_ptr<T>
|
||||
reinterpret_pointer_cast(smart_ptr<U> const & r)
|
||||
{
|
||||
return smart_ptr<T>(r, detail::reinterpret_cast_tag());
|
||||
}
|
||||
|
||||
} //namespace intrusive {
|
||||
} //namespace boost {
|
||||
|
||||
namespace boost{
|
||||
|
||||
//This is to support embedding a bit in the pointer
|
||||
//for intrusive containers, saving space
|
||||
namespace intrusive {
|
||||
|
||||
template<std::size_t N>
|
||||
struct has_pointer_plus_bit<smart_ptr<void>, N>
|
||||
{
|
||||
static const bool value = has_pointer_plus_bit<void*, N>::value;
|
||||
};
|
||||
|
||||
//Specialization
|
||||
template<class T>
|
||||
struct pointer_plus_bit<smart_ptr<T> >
|
||||
{
|
||||
typedef smart_ptr<T> pointer;
|
||||
|
||||
static pointer get_pointer(const pointer &n)
|
||||
{ return pointer_plus_bit<T*>::get_pointer(n.get()); }
|
||||
|
||||
static void set_pointer(pointer &n, pointer p)
|
||||
{
|
||||
T *raw_n = n.get();
|
||||
pointer_plus_bit<T*>::set_pointer(raw_n, p.get());
|
||||
n = raw_n;
|
||||
}
|
||||
|
||||
static bool get_bit(const pointer &n)
|
||||
{ return pointer_plus_bit<T*>::get_bit(n.get()); }
|
||||
|
||||
static void set_bit(pointer &n, bool c)
|
||||
{
|
||||
T *raw_n = n.get();
|
||||
pointer_plus_bit<T*>::set_bit(raw_n, c);
|
||||
n = raw_n;
|
||||
}
|
||||
};
|
||||
|
||||
template<std::size_t N>
|
||||
struct has_pointer_plus_2_bits<smart_ptr<void>, N>
|
||||
{
|
||||
static const bool value = has_pointer_plus_2_bits<void*, N>::value;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct pointer_plus_2_bits<smart_ptr<T> >
|
||||
{
|
||||
typedef smart_ptr<T> pointer;
|
||||
|
||||
static pointer get_pointer(const pointer &n)
|
||||
{ return pointer_plus_2_bits<T*>::get_pointer(n.get()); }
|
||||
|
||||
static void set_pointer(pointer &n, pointer p)
|
||||
{
|
||||
T *raw_n = n.get();
|
||||
pointer_plus_2_bits<T*>::set_pointer(raw_n, p.get());
|
||||
n = raw_n;
|
||||
}
|
||||
|
||||
static std::size_t get_bits(const pointer &n)
|
||||
{ return pointer_plus_2_bits<T*>::get_bits(n.get()); }
|
||||
|
||||
static void set_bits(pointer &n, std::size_t c)
|
||||
{
|
||||
T *raw_n = n.get();
|
||||
pointer_plus_2_bits<T*>::set_bits(raw_n, c);
|
||||
n = raw_n;
|
||||
}
|
||||
};
|
||||
|
||||
} //namespace intrusive
|
||||
} //namespace boost{
|
||||
|
||||
#endif //#ifndef BOOST_INTRUSIVE_SMART_PTR_HPP
|
||||
@@ -0,0 +1,138 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Olaf Krzikalla 2004-2006.
|
||||
// (C) Copyright Ion Gaztanaga 2006-2007.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/intrusive for documentation.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/splay_set.hpp>
|
||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||
#include "itestvalue.hpp"
|
||||
#include "smart_ptr.hpp"
|
||||
#include "generic_multiset_test.hpp"
|
||||
|
||||
namespace boost { namespace intrusive { namespace test {
|
||||
|
||||
template<class T, class O1, class O2, class O3, class O4>
|
||||
struct has_const_overloads<boost::intrusive::splay_multiset<T, O1, O2, O3, O4> >
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template<class T, class O1, class O2, class O3, class O4>
|
||||
struct has_splay<boost::intrusive::splay_multiset<T, O1, O2, O3, O4> >
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template<class T, class O1, class O2, class O3, class O4>
|
||||
struct has_rebalance<boost::intrusive::splay_multiset<T, O1, O2, O3, O4> >
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
template< class ValueType
|
||||
, class Option1 = boost::intrusive::none
|
||||
, class Option2 = boost::intrusive::none
|
||||
, class Option3 = boost::intrusive::none
|
||||
>
|
||||
struct GetContainer
|
||||
{
|
||||
typedef boost::intrusive::splay_multiset
|
||||
< ValueType
|
||||
, Option1
|
||||
, Option2
|
||||
, Option3
|
||||
> type;
|
||||
};
|
||||
|
||||
template<class VoidPointer, bool constant_time_size>
|
||||
class test_main_template
|
||||
{
|
||||
public:
|
||||
int operator()()
|
||||
{
|
||||
using namespace boost::intrusive;
|
||||
typedef testvalue<VoidPointer, constant_time_size> value_type;
|
||||
|
||||
test::test_generic_multiset < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::splay_set_base_hook_t
|
||||
>::type
|
||||
, GetContainer
|
||||
>::test_all();
|
||||
test::test_generic_multiset < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::splay_set_member_hook_t
|
||||
, &value_type::splay_set_node_
|
||||
>
|
||||
>::type
|
||||
, GetContainer
|
||||
>::test_all();
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
template<class VoidPointer>
|
||||
class test_main_template<VoidPointer, false>
|
||||
{
|
||||
public:
|
||||
int operator()()
|
||||
{
|
||||
using namespace boost::intrusive;
|
||||
typedef testvalue<VoidPointer, false> value_type;
|
||||
|
||||
test::test_generic_multiset < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::splay_set_base_hook_t
|
||||
>::type
|
||||
, GetContainer
|
||||
>::test_all();
|
||||
|
||||
test::test_generic_multiset < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::splay_set_member_hook_t
|
||||
, &value_type::splay_set_node_
|
||||
>
|
||||
>::type
|
||||
, GetContainer
|
||||
>::test_all();
|
||||
|
||||
test::test_generic_multiset < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::splay_set_auto_base_hook_t
|
||||
>::type
|
||||
, GetContainer
|
||||
>::test_all();
|
||||
|
||||
test::test_generic_multiset < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::splay_set_auto_member_hook_t
|
||||
, &value_type::splay_set_auto_node_
|
||||
>
|
||||
>::type
|
||||
, GetContainer
|
||||
>::test_all();
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
int main( int, char* [] )
|
||||
{
|
||||
test_main_template<void*, false>()();
|
||||
test_main_template<boost::intrusive::smart_ptr<void>, false>()();
|
||||
test_main_template<void*, true>()();
|
||||
test_main_template<boost::intrusive::smart_ptr<void>, true>()();
|
||||
return boost::report_errors();
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2007.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/intrusive for documentation.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/splay_set.hpp>
|
||||
#include "itestvalue.hpp"
|
||||
#include "smart_ptr.hpp"
|
||||
#include "generic_set_test.hpp"
|
||||
|
||||
namespace boost { namespace intrusive { namespace test {
|
||||
|
||||
template<class T, class O1, class O2, class O3, class O4>
|
||||
struct has_const_overloads<boost::intrusive::splay_set<T, O1, O2, O3, O4> >
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template<class T, class O1, class O2, class O3, class O4>
|
||||
struct has_splay<boost::intrusive::splay_set<T, O1, O2, O3, O4> >
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template<class T, class O1, class O2, class O3, class O4>
|
||||
struct has_rebalance<boost::intrusive::splay_set<T, O1, O2, O3, O4> >
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
template< class ValueType
|
||||
, class Option1 = boost::intrusive::none
|
||||
, class Option2 = boost::intrusive::none
|
||||
, class Option3 = boost::intrusive::none
|
||||
>
|
||||
struct GetContainer
|
||||
{
|
||||
typedef boost::intrusive::splay_set
|
||||
< ValueType
|
||||
, Option1
|
||||
, Option2
|
||||
, Option3
|
||||
> type;
|
||||
};
|
||||
|
||||
template<class VoidPointer, bool constant_time_size>
|
||||
class test_main_template
|
||||
{
|
||||
public:
|
||||
int operator()()
|
||||
{
|
||||
using namespace boost::intrusive;
|
||||
typedef testvalue<VoidPointer, constant_time_size> value_type;
|
||||
|
||||
test::test_generic_set < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::splay_set_base_hook_t
|
||||
>::type
|
||||
, GetContainer
|
||||
>::test_all();
|
||||
test::test_generic_set < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::splay_set_member_hook_t
|
||||
, &value_type::splay_set_node_
|
||||
>
|
||||
>::type
|
||||
, GetContainer
|
||||
>::test_all();
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
template<class VoidPointer>
|
||||
class test_main_template<VoidPointer, false>
|
||||
{
|
||||
public:
|
||||
int operator()()
|
||||
{
|
||||
using namespace boost::intrusive;
|
||||
typedef testvalue<VoidPointer, false> value_type;
|
||||
|
||||
test::test_generic_set < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::splay_set_base_hook_t
|
||||
>::type
|
||||
, GetContainer
|
||||
>::test_all();
|
||||
|
||||
test::test_generic_set < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::splay_set_member_hook_t
|
||||
, &value_type::splay_set_node_
|
||||
>
|
||||
>::type
|
||||
, GetContainer
|
||||
>::test_all();
|
||||
|
||||
test::test_generic_set < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::splay_set_auto_base_hook_t
|
||||
>::type
|
||||
, GetContainer
|
||||
>::test_all();
|
||||
|
||||
test::test_generic_set < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::splay_set_auto_member_hook_t
|
||||
, &value_type::splay_set_auto_node_
|
||||
>
|
||||
>::type
|
||||
, GetContainer
|
||||
>::test_all();
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
int main( int, char* [] )
|
||||
{
|
||||
test_main_template<void*, false>()();
|
||||
test_main_template<boost::intrusive::smart_ptr<void>, false>()();
|
||||
test_main_template<void*, true>()();
|
||||
test_main_template<boost::intrusive::smart_ptr<void>, true>()();
|
||||
return boost::report_errors();
|
||||
}
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
@@ -0,0 +1,147 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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 containers
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,301 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTRUSIVE_TEST_CONTAINER_HPP
|
||||
#define BOOST_INTRUSIVE_TEST_CONTAINER_HPP
|
||||
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <boost/intrusive/detail/mpl.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
namespace test {
|
||||
|
||||
template<class T>
|
||||
struct has_const_overloads
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template< class Container >
|
||||
void test_container( Container & c )
|
||||
{
|
||||
typedef typename Container::value_type value_type;
|
||||
typedef typename Container::iterator iterator;
|
||||
typedef typename Container::const_iterator const_iterator;
|
||||
typedef typename Container::reference reference;
|
||||
typedef typename Container::const_reference const_reference;
|
||||
typedef typename Container::pointer pointer;
|
||||
typedef typename Container::const_pointer const_pointer;
|
||||
typedef typename Container::difference_type difference_type;
|
||||
typedef typename Container::size_type size_type;
|
||||
typedef typename Container::difference_type difference_type;
|
||||
typedef typename Container::size_type size_type;
|
||||
typedef typename Container::value_traits value_traits;
|
||||
|
||||
const size_type num_elem = c.size();
|
||||
BOOST_TEST( c.empty() == (num_elem == 0) );
|
||||
{
|
||||
iterator it(c.begin()), itend(c.end());
|
||||
size_type i;
|
||||
for(i = 0; i < num_elem; ++i){
|
||||
++it;
|
||||
}
|
||||
BOOST_TEST( it == c.end() );
|
||||
BOOST_TEST( c.size() == i );
|
||||
}
|
||||
|
||||
//Check iterator conversion
|
||||
BOOST_TEST( const_iterator(c.begin()) == c.cbegin() );
|
||||
{
|
||||
const_iterator it(c.cbegin()), itend(c.cend());
|
||||
size_type i;
|
||||
for(i = 0; i < num_elem; ++i){
|
||||
++it;
|
||||
}
|
||||
BOOST_TEST( it == c.cend() );
|
||||
BOOST_TEST( c.size() == i );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template< class Container, class Data >
|
||||
void test_sequence_container(Container & c, Data & d)
|
||||
{
|
||||
assert( d.size() > 2 );
|
||||
|
||||
c.clear();
|
||||
|
||||
BOOST_TEST( c.size() == 0 );
|
||||
BOOST_TEST( c.empty() );
|
||||
|
||||
{
|
||||
typename Data::iterator i = d.begin();
|
||||
c.insert( c.begin(), *i );
|
||||
c.insert( c.end(), *(++i) );
|
||||
}
|
||||
|
||||
BOOST_TEST( c.size() == 2 );
|
||||
BOOST_TEST( !c.empty() );
|
||||
|
||||
c.erase( c.begin() );
|
||||
|
||||
BOOST_TEST( c.size() == 1 );
|
||||
|
||||
{
|
||||
typename Data::iterator i = d.begin();
|
||||
++++i;
|
||||
c.insert( c.begin(), *(i) );
|
||||
}
|
||||
|
||||
c.erase( c.begin(), c.end() );
|
||||
|
||||
BOOST_TEST( c.empty() );
|
||||
|
||||
c.insert( c.begin(), *d.begin() );
|
||||
|
||||
BOOST_TEST( c.size() == 1 );
|
||||
|
||||
BOOST_TEST( c.begin() != c.end() );
|
||||
|
||||
c.erase( c.begin() );
|
||||
|
||||
c.assign(d.begin(), d.end());
|
||||
|
||||
BOOST_TEST( c.size() == d.size() );
|
||||
|
||||
c.clear();
|
||||
|
||||
BOOST_TEST( c.size() == 0 );
|
||||
BOOST_TEST( c.empty() );
|
||||
}
|
||||
|
||||
template< class Container, class Data >
|
||||
void test_common_unordered_and_associative_container(Container & c, Data & d)
|
||||
{
|
||||
typedef typename Container::size_type size_type;
|
||||
|
||||
assert( d.size() > 2 );
|
||||
|
||||
c.clear();
|
||||
c.insert(d.begin(), d.end());
|
||||
|
||||
for( typename Data::const_iterator di = d.begin(), de = d.end();
|
||||
di != de; ++di )
|
||||
{
|
||||
BOOST_TEST( c.find(*di) != c.end() );
|
||||
}
|
||||
|
||||
typename Data::const_iterator db = d.begin();
|
||||
typename Data::const_iterator da = db++;
|
||||
|
||||
size_type old_size = c.size();
|
||||
|
||||
c.erase(*da);
|
||||
|
||||
BOOST_TEST( c.size() == old_size-1 );
|
||||
|
||||
BOOST_TEST( c.count(*da) == 0 );
|
||||
BOOST_TEST( c.count(*db) != 0 );
|
||||
|
||||
BOOST_TEST( c.find(*da) == c.end() );
|
||||
BOOST_TEST( c.find(*db) != c.end() );
|
||||
|
||||
BOOST_TEST( c.equal_range(*db).first != c.end() );
|
||||
|
||||
c.clear();
|
||||
|
||||
BOOST_TEST( c.equal_range(*da).first == c.end() );
|
||||
}
|
||||
|
||||
template< class Container, class Data >
|
||||
void test_associative_container_invariants(Container & c, Data & d, boost::intrusive::detail::true_type)
|
||||
{
|
||||
typedef typename Container::const_iterator const_iterator;
|
||||
for( typename Data::const_iterator di = d.begin(), de = d.end();
|
||||
di != de; ++di)
|
||||
{
|
||||
const_iterator ci = c.find(*di);
|
||||
BOOST_TEST( ci != c.end() );
|
||||
BOOST_TEST( ! c.value_comp()(*ci, *di) );
|
||||
const_iterator cil = c.lower_bound(*di);
|
||||
const_iterator ciu = c.upper_bound(*di);
|
||||
std::pair<const_iterator, const_iterator> er = c.equal_range(*di);
|
||||
BOOST_TEST( cil == er.first );
|
||||
BOOST_TEST( ciu == er.second );
|
||||
if(ciu != c.end()){
|
||||
BOOST_TEST( c.value_comp()(*cil, *ciu) );
|
||||
}
|
||||
if(c.count(*di) > 1){
|
||||
const_iterator ci_next = cil; ++ci_next;
|
||||
for( ; ci_next != ciu; ++cil, ++ci_next){
|
||||
BOOST_TEST( !c.value_comp()(*ci_next, *cil) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template< class Container, class Data >
|
||||
void test_associative_container_invariants(Container &, Data &, boost::intrusive::detail::false_type)
|
||||
{}
|
||||
|
||||
template< class Container, class Data >
|
||||
void test_associative_container_invariants(Container & c, Data & d)
|
||||
{
|
||||
using namespace boost::intrusive;
|
||||
typedef typename detail::remove_const<Container>::type Type;
|
||||
typedef detail::bool_<has_const_overloads<Type>::value> enabler;
|
||||
test_associative_container_invariants(c, d, enabler());
|
||||
}
|
||||
|
||||
template< class Container, class Data >
|
||||
void test_associative_container(Container & c, Data & d)
|
||||
{
|
||||
typedef typename Container::const_iterator const_iterator;
|
||||
assert( d.size() > 2 );
|
||||
|
||||
c.clear();
|
||||
c.insert(d.begin(),d.end());
|
||||
|
||||
test_associative_container_invariants(c, d);
|
||||
|
||||
const Container & cr = c;
|
||||
|
||||
test_associative_container_invariants(cr, d);
|
||||
}
|
||||
|
||||
template< class Container, class Data >
|
||||
void test_unordered_associative_container_invariants(Container & c, Data & d, boost::intrusive::detail::true_type)
|
||||
{
|
||||
typedef typename Container::size_type size_type;
|
||||
typedef typename Container::const_iterator const_iterator;
|
||||
|
||||
for( typename Data::const_iterator di = d.begin(), de = d.end() ;
|
||||
di != de ; ++di ){
|
||||
const_iterator i = c.find(*di);
|
||||
size_type nb = c.bucket(*i);
|
||||
size_type bucket_elem = std::distance(c.begin(nb), c.end(nb));
|
||||
BOOST_TEST( bucket_elem == c.bucket_size(nb) );
|
||||
BOOST_TEST( &*c.local_iterator_to(*c.find(*di)) == &*i );
|
||||
std::pair<const_iterator, const_iterator> er = c.equal_range(*di);
|
||||
size_type cnt = std::distance(er.first, er.second);
|
||||
BOOST_TEST( cnt == c.count(*di));
|
||||
if(cnt > 1)
|
||||
for(const_iterator n = er.first, i = n++, e = er.second; n != e; ++i, ++n){
|
||||
BOOST_TEST( c.key_eq()(*i, *n) );
|
||||
BOOST_TEST( c.hash_function()(*i) == c.hash_function()(*n) );
|
||||
}
|
||||
}
|
||||
|
||||
size_type blen = c.bucket_count();
|
||||
size_type total_objects = 0;
|
||||
for(size_type i = 0; i < blen; ++i){
|
||||
total_objects += c.bucket_size(i);
|
||||
}
|
||||
BOOST_TEST( total_objects == c.size() );
|
||||
}
|
||||
|
||||
template< class Container, class Data >
|
||||
void test_unordered_associative_container_invariants(Container &, Data &, boost::intrusive::detail::false_type)
|
||||
{}
|
||||
|
||||
template< class Container, class Data >
|
||||
void test_unordered_associative_container_invariants(Container & c, Data & d)
|
||||
{
|
||||
using namespace boost::intrusive;
|
||||
typedef typename detail::remove_const<Container>::type Type;
|
||||
typedef detail::bool_<has_const_overloads<Type>::value> enabler;
|
||||
test_unordered_associative_container_invariants(c, d, enabler());
|
||||
}
|
||||
|
||||
template< class Container, class Data >
|
||||
void test_unordered_associative_container(Container & c, Data & d)
|
||||
{
|
||||
c.clear();
|
||||
c.insert( d.begin(), d.end() );
|
||||
|
||||
test_unordered_associative_container_invariants(c, d);
|
||||
|
||||
const Container & cr = c;
|
||||
|
||||
test_unordered_associative_container_invariants(cr, d);
|
||||
}
|
||||
|
||||
template< class Container, class Data >
|
||||
void test_unique_container(Container & c, Data & d)
|
||||
{
|
||||
typedef typename Container::value_type value_type;
|
||||
c.clear();
|
||||
c.insert(d.begin(),d.end());
|
||||
typename Container::size_type old_size = c.size();
|
||||
value_type v(*d.begin());
|
||||
c.insert(v);
|
||||
BOOST_TEST( c.size() == old_size );
|
||||
c.clear();
|
||||
}
|
||||
|
||||
template< class Container, class Data >
|
||||
void test_non_unique_container(Container & c, Data & d)
|
||||
{
|
||||
typedef typename Container::value_type value_type;
|
||||
c.clear();
|
||||
c.insert(d.begin(),d.end());
|
||||
typename Container::size_type old_size = c.size();
|
||||
value_type v(*d.begin());
|
||||
c.insert(v);
|
||||
BOOST_TEST( c.size() == (old_size+1) );
|
||||
c.clear();
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
#endif //#ifndef BOOST_INTRUSIVE_TEST_CONTAINER_HPP
|
||||
@@ -0,0 +1,29 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2006-2007
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/intrusive for documentation.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTRUSIVE_TEST_TEST_MACROS_HPP
|
||||
#define BOOST_INTRUSIVE_TEST_TEST_MACROS_HPP
|
||||
|
||||
#define TEST_INTRUSIVE_SEQUENCE( INTVALUES, ITERATOR )\
|
||||
{ \
|
||||
const int init_values_size = sizeof(INTVALUES)/sizeof(INTVALUES[0]); \
|
||||
std::vector<int> expected; \
|
||||
expected.assign(&INTVALUES[0], &INTVALUES[0] + init_values_size); \
|
||||
BOOST_TEST (std::equal(expected.begin(), expected.end(), ITERATOR) ); \
|
||||
}
|
||||
|
||||
#define TEST_INTRUSIVE_SEQUENCE_EXPECTED( EXPECTEDVECTOR, ITERATOR )\
|
||||
{ \
|
||||
BOOST_TEST (std::equal(EXPECTEDVECTOR.begin(), EXPECTEDVECTOR.end(), ITERATOR) ); \
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,65 @@
|
||||
#ifndef BOOST_INTRUSIVE_TEST_TEST_TEMPLATES_HPP
|
||||
#define BOOST_INTRUSIVE_TEST_TEST_TEMPLATES_HPP
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace boost {
|
||||
namespace intrusive {
|
||||
namespace test {
|
||||
|
||||
template<class Container>
|
||||
void test_shift()
|
||||
{
|
||||
typedef typename ValueTraits::value_type testvalue_t;
|
||||
boost::test_tools::output_test_stream test_seq;
|
||||
Container test_cont;
|
||||
const int NumElem = 6;
|
||||
|
||||
std::vector<typename Container::value_type> values(NumElem);
|
||||
for(int i = 0; i < NumElem; ++i){
|
||||
values[i] = i+1;
|
||||
}
|
||||
|
||||
const int num_values = (int)values.size();
|
||||
std::vector<int> expected_values(num_values);
|
||||
|
||||
//Shift forward all possible positions 3 times
|
||||
for(int i = 0; i < num_values*3; ++i){
|
||||
test_cont.assign(values.begin(), values.end());
|
||||
test_cont.shift_forward(i);
|
||||
for(int j = 0; j < num_values; ++j){
|
||||
expected_values[(j + num_values - i%num_values) % num_values] = (j + 1);
|
||||
}
|
||||
std::copy (test_cont.begin(), test_cont.end(),
|
||||
std::ostream_iterator<testvalue_t> (test_seq));
|
||||
std::stringstream stream;
|
||||
std::copy (expected_values.begin(), expected_values.end(),
|
||||
std::ostream_iterator<testvalue_t> (stream));
|
||||
stream << std::ends;
|
||||
BOOST_CHECK (test_seq.is_equal (stream.str().c_str()));
|
||||
test_cont.clear();
|
||||
}
|
||||
|
||||
//Shift backwards all possible positions
|
||||
for(int i = 0; i < num_values*2; ++i){
|
||||
test_cont.assign(values.begin(), values.end());
|
||||
test_cont.shift_backwards(i);
|
||||
for(int j = 0; j < num_values; ++j){
|
||||
expected_values[(j + i) % num_values] = (j + 1);
|
||||
}
|
||||
std::copy (test_cont.begin(), test_cont.end(),
|
||||
std::ostream_iterator<testvalue_t> (test_seq));
|
||||
std::stringstream stream;
|
||||
std::copy (expected_values.begin(), expected_values.end(),
|
||||
std::ostream_iterator<testvalue_t> (stream));
|
||||
stream << std::ends;
|
||||
BOOST_CHECK (test_seq.is_equal (stream.str().c_str()));
|
||||
test_cont.clear();
|
||||
}
|
||||
}
|
||||
|
||||
} //namespace test {
|
||||
} //namespace intrusive {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_INTRUSIVE_TEST_TEST_TEMPLATES_HPP
|
||||
@@ -0,0 +1,445 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Olaf Krzikalla 2004-2006.
|
||||
// (C) Copyright Ion Gaztanaga 2006-2007.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/intrusive for documentation.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/unordered_set.hpp>
|
||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||
#include "itestvalue.hpp"
|
||||
#include "smart_ptr.hpp"
|
||||
#include "common_functors.hpp"
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include "test_macros.hpp"
|
||||
#include "test_container.hpp"
|
||||
|
||||
using namespace boost::intrusive;
|
||||
|
||||
static const std::size_t BucketSize = 11;
|
||||
|
||||
template<class ValueTraits>
|
||||
struct test_unordered_multiset
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
static void test_all (std::vector<value_type>& values);
|
||||
static void test_sort(std::vector<value_type>& values);
|
||||
static void test_insert(std::vector<value_type>& values);
|
||||
static void test_swap(std::vector<value_type>& values);
|
||||
static void test_rehash(std::vector<value_type>& values);
|
||||
static void test_find(std::vector<value_type>& values);
|
||||
static void test_impl();
|
||||
static void test_clone(std::vector<value_type>& values);
|
||||
};
|
||||
|
||||
template<class ValueTraits>
|
||||
void test_unordered_multiset<ValueTraits>::test_all (std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef unordered_multiset
|
||||
<value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> unordered_multiset_type;
|
||||
{
|
||||
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
||||
typename unordered_multiset_type::bucket_type buckets [BucketSize];
|
||||
unordered_multiset_type testset(bucket_traits(buckets, BucketSize));
|
||||
testset.insert(values.begin(), values.end());
|
||||
test::test_container(testset);
|
||||
testset.clear();
|
||||
testset.insert(values.begin(), values.end());
|
||||
test::test_common_unordered_and_associative_container(testset, values);
|
||||
testset.clear();
|
||||
testset.insert(values.begin(), values.end());
|
||||
test::test_unordered_associative_container(testset, values);
|
||||
testset.clear();
|
||||
testset.insert(values.begin(), values.end());
|
||||
test::test_non_unique_container(testset, values);
|
||||
}
|
||||
test_sort(values);
|
||||
test_insert(values);
|
||||
test_swap(values);
|
||||
test_rehash(values);
|
||||
test_find(values);
|
||||
test_impl();
|
||||
test_clone(values);
|
||||
}
|
||||
|
||||
//test case due to an error in tree implementation:
|
||||
template<class ValueTraits>
|
||||
void test_unordered_multiset<ValueTraits>::test_impl()
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef unordered_multiset
|
||||
<value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> unordered_multiset_type;
|
||||
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
||||
|
||||
std::vector<value_type> values (5);
|
||||
for (int i = 0; i < 5; ++i)
|
||||
values[i].value_ = i;
|
||||
|
||||
typename unordered_multiset_type::bucket_type buckets [BucketSize];
|
||||
unordered_multiset_type testset(bucket_traits(buckets, BucketSize));
|
||||
|
||||
for (int i = 0; i < 5; ++i)
|
||||
testset.insert (values[i]);
|
||||
|
||||
testset.erase (testset.iterator_to (values[0]));
|
||||
testset.erase (testset.iterator_to (values[1]));
|
||||
testset.insert (values[1]);
|
||||
|
||||
testset.erase (testset.iterator_to (values[2]));
|
||||
testset.erase (testset.iterator_to (values[3]));
|
||||
}
|
||||
|
||||
//test: constructor, iterator, clear, reverse_iterator, front, back, size:
|
||||
template<class ValueTraits>
|
||||
void test_unordered_multiset<ValueTraits>::test_sort(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef unordered_multiset
|
||||
<value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> unordered_multiset_type;
|
||||
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
||||
|
||||
typename unordered_multiset_type::bucket_type buckets [BucketSize];
|
||||
unordered_multiset_type testset1(values.begin(), values.end(), bucket_traits(buckets, BucketSize));
|
||||
|
||||
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
testset1.clear();
|
||||
BOOST_TEST (testset1.empty());
|
||||
}
|
||||
|
||||
//test: insert, const_iterator, const_reverse_iterator, erase, iterator_to:
|
||||
template<class ValueTraits>
|
||||
void test_unordered_multiset<ValueTraits>::test_insert(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef unordered_multiset
|
||||
<value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> unordered_multiset_type;
|
||||
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
||||
|
||||
typename unordered_multiset_type::bucket_type buckets [BucketSize];
|
||||
unordered_multiset_type testset(bucket_traits(buckets, BucketSize));
|
||||
|
||||
testset.insert(&values[0] + 2, &values[0] + 5);
|
||||
|
||||
const unordered_multiset_type& const_testset = testset;
|
||||
{ int init_values [] = { 1, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); }
|
||||
|
||||
typename unordered_multiset_type::iterator i = testset.begin();
|
||||
BOOST_TEST (i->value_ == 1);
|
||||
|
||||
i = testset.insert (values[0]);
|
||||
BOOST_TEST (&*i == &values[0]);
|
||||
|
||||
i = testset.iterator_to (values[2]);
|
||||
BOOST_TEST (&*i == &values[2]);
|
||||
testset.erase(i);
|
||||
|
||||
{ int init_values [] = { 1, 3, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); }
|
||||
testset.clear();
|
||||
testset.insert(&values[0], &values[0] + values.size());
|
||||
|
||||
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); }
|
||||
|
||||
BOOST_TEST (testset.erase(1) == 1);
|
||||
BOOST_TEST (testset.erase(2) == 2);
|
||||
BOOST_TEST (testset.erase(3) == 1);
|
||||
BOOST_TEST (testset.erase(4) == 1);
|
||||
BOOST_TEST (testset.erase(5) == 1);
|
||||
BOOST_TEST (testset.empty() == true);
|
||||
|
||||
//Now with a single bucket
|
||||
typename unordered_multiset_type::bucket_type single_bucket[1];
|
||||
unordered_multiset_type testset2(bucket_traits(single_bucket, 1));
|
||||
testset2.insert(&values[0], &values[0] + values.size());
|
||||
BOOST_TEST (testset2.erase(5) == 1);
|
||||
BOOST_TEST (testset2.erase(2) == 2);
|
||||
BOOST_TEST (testset2.erase(1) == 1);
|
||||
BOOST_TEST (testset2.erase(4) == 1);
|
||||
BOOST_TEST (testset2.erase(3) == 1);
|
||||
BOOST_TEST (testset2.empty() == true);
|
||||
}
|
||||
|
||||
//test: insert (seq-version), swap, erase (seq-version), size:
|
||||
template<class ValueTraits>
|
||||
void test_unordered_multiset<ValueTraits>::test_swap(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef unordered_multiset
|
||||
<value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> unordered_multiset_type;
|
||||
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
||||
|
||||
typename unordered_multiset_type::bucket_type buckets [BucketSize];
|
||||
typename unordered_multiset_type::bucket_type buckets2 [BucketSize];
|
||||
unordered_multiset_type testset1(&values[0], &values[0] + 2, bucket_traits(buckets, BucketSize));
|
||||
unordered_multiset_type testset2(bucket_traits(buckets2, BucketSize));
|
||||
|
||||
testset2.insert (&values[0] + 2, &values[0] + 6);
|
||||
testset1.swap (testset2);
|
||||
|
||||
{ int init_values [] = { 1, 2, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
|
||||
{ int init_values [] = { 2, 3 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset2.begin() ); }
|
||||
|
||||
testset1.erase (testset1.iterator_to(values[5]), testset1.end());
|
||||
BOOST_TEST (testset1.size() == 1);
|
||||
// BOOST_TEST (&testset1.front() == &values[3]);
|
||||
BOOST_TEST (&*testset1.begin() == &values[3]);
|
||||
}
|
||||
|
||||
//test: rehash:
|
||||
template<class ValueTraits>
|
||||
void test_unordered_multiset<ValueTraits>::test_rehash(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef unordered_multiset
|
||||
<value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> unordered_multiset_type;
|
||||
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
||||
|
||||
typename unordered_multiset_type::bucket_type buckets1 [BucketSize];
|
||||
typename unordered_multiset_type::bucket_type buckets2 [2];
|
||||
typename unordered_multiset_type::bucket_type buckets3 [BucketSize*2];
|
||||
|
||||
unordered_multiset_type testset1(&values[0], &values[0] + 6, bucket_traits(buckets1, BucketSize));
|
||||
BOOST_TEST (testset1.size() == 6);
|
||||
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
|
||||
testset1.rehash(bucket_traits(buckets2, 2));
|
||||
BOOST_TEST (testset1.size() == 6);
|
||||
{ int init_values [] = { 4, 2, 2, 5, 3, 1 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
|
||||
testset1.rehash(bucket_traits(buckets3, BucketSize*2));
|
||||
BOOST_TEST (testset1.size() == 6);
|
||||
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
|
||||
//Now rehash reducing the buckets
|
||||
testset1.rehash(bucket_traits(buckets3, 2));
|
||||
BOOST_TEST (testset1.size() == 6);
|
||||
{ int init_values [] = { 4, 2, 2, 5, 3, 1 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
|
||||
//Now rehash increasing the buckets
|
||||
testset1.rehash(bucket_traits(buckets3, BucketSize*2));
|
||||
BOOST_TEST (testset1.size() == 6);
|
||||
{ int init_values [] = { 1, 2, 2, 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
}
|
||||
|
||||
//test: find, equal_range (lower_bound, upper_bound):
|
||||
template<class ValueTraits>
|
||||
void test_unordered_multiset<ValueTraits>::test_find(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef unordered_multiset
|
||||
<value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> unordered_multiset_type;
|
||||
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
||||
|
||||
typename unordered_multiset_type::bucket_type buckets[BucketSize];
|
||||
unordered_multiset_type testset(values.begin(), values.end(), bucket_traits(buckets, BucketSize));
|
||||
|
||||
typedef typename unordered_multiset_type::iterator iterator;
|
||||
|
||||
value_type cmp_val;
|
||||
cmp_val.value_ = 2;
|
||||
iterator i = testset.find (cmp_val);
|
||||
BOOST_TEST (i->value_ == 2);
|
||||
BOOST_TEST ((++i)->value_ == 2);
|
||||
std::pair<iterator,iterator> range = testset.equal_range (cmp_val);
|
||||
|
||||
BOOST_TEST (range.first->value_ == 2);
|
||||
BOOST_TEST (range.second->value_ == 3);
|
||||
BOOST_TEST (std::distance (range.first, range.second) == 2);
|
||||
|
||||
cmp_val.value_ = 7;
|
||||
BOOST_TEST (testset.find (cmp_val) == testset.end());
|
||||
}
|
||||
|
||||
|
||||
template<class ValueTraits>
|
||||
void test_unordered_multiset<ValueTraits>
|
||||
::test_clone(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef unordered_multiset
|
||||
<value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> unordered_multiset_type;
|
||||
typedef typename unordered_multiset_type::bucket_traits bucket_traits;
|
||||
{
|
||||
//Test with equal bucket arrays
|
||||
typename unordered_multiset_type::bucket_type buckets1 [BucketSize];
|
||||
typename unordered_multiset_type::bucket_type buckets2 [BucketSize];
|
||||
unordered_multiset_type testset1 (values.begin(), values.end(), bucket_traits(buckets1, BucketSize));
|
||||
unordered_multiset_type testset2 (bucket_traits(buckets2, BucketSize));
|
||||
|
||||
testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
|
||||
//Ordering is not guarantee in the cloning so insert data in a set and test
|
||||
std::multiset<typename ValueTraits::value_type>
|
||||
src(testset1.begin(), testset1.end());
|
||||
std::multiset<typename ValueTraits::value_type>
|
||||
dst(testset2.begin(), testset2.end());
|
||||
BOOST_TEST (src.size() == dst.size() && std::equal(src.begin(), src.end(), dst.begin()));
|
||||
testset2.clear_and_dispose(test::delete_disposer<value_type>());
|
||||
BOOST_TEST (testset2.empty());
|
||||
}
|
||||
{
|
||||
//Test with bigger source bucket arrays
|
||||
typename unordered_multiset_type::bucket_type buckets1 [BucketSize*2];
|
||||
typename unordered_multiset_type::bucket_type buckets2 [BucketSize];
|
||||
unordered_multiset_type testset1 (values.begin(), values.end(), bucket_traits(buckets1, BucketSize*2));
|
||||
unordered_multiset_type testset2 (bucket_traits(buckets2, BucketSize));
|
||||
|
||||
testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
|
||||
//Ordering is not guarantee in the cloning so insert data in a set and test
|
||||
std::multiset<typename ValueTraits::value_type>
|
||||
src(testset1.begin(), testset1.end());
|
||||
std::multiset<typename ValueTraits::value_type>
|
||||
dst(testset2.begin(), testset2.end());
|
||||
BOOST_TEST (src.size() == dst.size() && std::equal(src.begin(), src.end(), dst.begin()));
|
||||
testset2.clear_and_dispose(test::delete_disposer<value_type>());
|
||||
BOOST_TEST (testset2.empty());
|
||||
}
|
||||
{
|
||||
//Test with smaller source bucket arrays
|
||||
typename unordered_multiset_type::bucket_type buckets1 [BucketSize];
|
||||
typename unordered_multiset_type::bucket_type buckets2 [BucketSize*2];
|
||||
unordered_multiset_type testset1 (values.begin(), values.end(), bucket_traits(buckets1, BucketSize));
|
||||
unordered_multiset_type testset2 (bucket_traits(buckets2, BucketSize*2));
|
||||
|
||||
testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
|
||||
//Ordering is not guarantee in the cloning so insert data in a set and test
|
||||
std::multiset<typename ValueTraits::value_type>
|
||||
src(testset1.begin(), testset1.end());
|
||||
std::multiset<typename ValueTraits::value_type>
|
||||
dst(testset2.begin(), testset2.end());
|
||||
BOOST_TEST (src.size() == dst.size() && std::equal(src.begin(), src.end(), dst.begin()));
|
||||
testset2.clear_and_dispose(test::delete_disposer<value_type>());
|
||||
BOOST_TEST (testset2.empty());
|
||||
}
|
||||
}
|
||||
|
||||
template<class VoidPointer, bool constant_time_size>
|
||||
class test_main_template
|
||||
{
|
||||
public:
|
||||
int operator()()
|
||||
{
|
||||
typedef testvalue<VoidPointer, constant_time_size> value_type;
|
||||
static const int random_init[6] = { 3, 2, 4, 1, 5, 2 };
|
||||
std::vector<testvalue<VoidPointer, constant_time_size> > data (6);
|
||||
for (int i = 0; i < 6; ++i)
|
||||
data[i].value_ = random_init[i];
|
||||
|
||||
test_unordered_multiset < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::unordered_set_base_hook_t
|
||||
>::type
|
||||
>::test_all(data);
|
||||
|
||||
test_unordered_multiset < typename 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;
|
||||
}
|
||||
};
|
||||
|
||||
template<class VoidPointer>
|
||||
class test_main_template<VoidPointer, false>
|
||||
{
|
||||
public:
|
||||
int operator()()
|
||||
{
|
||||
typedef testvalue<VoidPointer, false> value_type;
|
||||
static const int random_init[6] = { 3, 2, 4, 1, 5, 2 };
|
||||
std::vector<testvalue<VoidPointer, false> > data (6);
|
||||
for (int i = 0; i < 6; ++i)
|
||||
data[i].value_ = random_init[i];
|
||||
|
||||
test_unordered_multiset < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::unordered_set_base_hook_t
|
||||
>::type
|
||||
>::test_all(data);
|
||||
|
||||
test_unordered_multiset < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::unordered_set_member_hook_t
|
||||
, &value_type::unordered_set_node_
|
||||
>
|
||||
>::type
|
||||
>::test_all(data);
|
||||
|
||||
test_unordered_multiset < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::unordered_set_auto_base_hook_t
|
||||
>::type
|
||||
>::test_all(data);
|
||||
|
||||
test_unordered_multiset < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::unordered_set_auto_member_hook_t
|
||||
, &value_type::unordered_set_auto_node_
|
||||
>
|
||||
>::type
|
||||
>::test_all(data);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
int main( int, char* [] )
|
||||
{
|
||||
test_main_template<void*, false>()();
|
||||
test_main_template<smart_ptr<void>, false>()();
|
||||
test_main_template<void*, true>()();
|
||||
test_main_template<smart_ptr<void>, true>()();
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
@@ -0,0 +1,417 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Olaf Krzikalla 2004-2006.
|
||||
// (C) Copyright Ion Gaztanaga 2006-2007.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/intrusive for documentation.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#include <boost/intrusive/detail/config_begin.hpp>
|
||||
#include <boost/intrusive/unordered_set.hpp>
|
||||
#include <boost/intrusive/detail/pointer_to_other.hpp>
|
||||
#include "itestvalue.hpp"
|
||||
#include "smart_ptr.hpp"
|
||||
#include "common_functors.hpp"
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include "test_macros.hpp"
|
||||
#include "test_container.hpp"
|
||||
|
||||
using namespace boost::intrusive;
|
||||
|
||||
static const std::size_t BucketSize = 11;
|
||||
|
||||
template<class ValueTraits>
|
||||
struct test_unordered_set
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
static void test_all(std::vector<value_type>& values);
|
||||
static void test_sort(std::vector<value_type>& values);
|
||||
static void test_insert(std::vector<value_type>& values);
|
||||
static void test_swap(std::vector<value_type>& values);
|
||||
static void test_rehash(std::vector<value_type>& values);
|
||||
static void test_find(std::vector<value_type>& values);
|
||||
static void test_impl();
|
||||
static void test_clone(std::vector<value_type>& values);
|
||||
};
|
||||
|
||||
template<class ValueTraits>
|
||||
void test_unordered_set<ValueTraits>::test_all(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef unordered_set
|
||||
<value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> unordered_set_type;
|
||||
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
||||
{
|
||||
typename unordered_set_type::bucket_type buckets [BucketSize];
|
||||
unordered_set_type testset(bucket_traits(buckets, BucketSize));
|
||||
testset.insert(values.begin(), values.end());
|
||||
test::test_container(testset);
|
||||
testset.clear();
|
||||
testset.insert(values.begin(), values.end());
|
||||
test::test_common_unordered_and_associative_container(testset, values);
|
||||
testset.clear();
|
||||
testset.insert(values.begin(), values.end());
|
||||
test::test_unordered_associative_container(testset, values);
|
||||
testset.clear();
|
||||
testset.insert(values.begin(), values.end());
|
||||
test::test_unique_container(testset, values);
|
||||
}
|
||||
test_sort(values);
|
||||
test_insert(values);
|
||||
test_swap(values);
|
||||
test_rehash(values);
|
||||
test_find(values);
|
||||
test_impl();
|
||||
test_clone(values);
|
||||
}
|
||||
|
||||
//test case due to an error in tree implementation:
|
||||
template<class ValueTraits>
|
||||
void test_unordered_set<ValueTraits>::test_impl()
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef unordered_set
|
||||
<value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> unordered_set_type;
|
||||
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
||||
|
||||
std::vector<value_type> values (5);
|
||||
for (int i = 0; i < 5; ++i)
|
||||
values[i].value_ = i;
|
||||
|
||||
typename unordered_set_type::bucket_type buckets [BucketSize];
|
||||
unordered_set_type testset(bucket_traits(buckets, BucketSize));
|
||||
for (int i = 0; i < 5; ++i)
|
||||
testset.insert (values[i]);
|
||||
|
||||
testset.erase (testset.iterator_to (values[0]));
|
||||
testset.erase (testset.iterator_to (values[1]));
|
||||
testset.insert (values[1]);
|
||||
testset.erase (testset.iterator_to (values[2]));
|
||||
testset.erase (testset.iterator_to (values[3]));
|
||||
}
|
||||
|
||||
//test: constructor, iterator, clear, reverse_iterator, front, back, size:
|
||||
template<class ValueTraits>
|
||||
void test_unordered_set<ValueTraits>::test_sort(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef unordered_set
|
||||
<value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> unordered_set_type;
|
||||
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
||||
|
||||
typename unordered_set_type::bucket_type buckets [BucketSize];
|
||||
unordered_set_type testset1(values.begin(), values.end(), bucket_traits(buckets, BucketSize));
|
||||
|
||||
BOOST_TEST (5 == std::distance(testset1.begin(), testset1.end()));
|
||||
{ int init_values [] = { 1, 2, 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
|
||||
testset1.clear();
|
||||
BOOST_TEST (testset1.empty());
|
||||
}
|
||||
|
||||
//test: insert, const_iterator, const_reverse_iterator, erase, iterator_to:
|
||||
template<class ValueTraits>
|
||||
void test_unordered_set<ValueTraits>::test_insert(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef unordered_set
|
||||
<value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> unordered_set_type;
|
||||
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
||||
|
||||
typename unordered_set_type::bucket_type buckets [BucketSize];
|
||||
unordered_set_type testset(bucket_traits(buckets, BucketSize));
|
||||
testset.insert(&values[0] + 2, &values[0] + 5);
|
||||
|
||||
const unordered_set_type& const_testset = testset;
|
||||
{ int init_values [] = { 1, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); }
|
||||
|
||||
typename unordered_set_type::iterator i = testset.begin();
|
||||
BOOST_TEST (i->value_ == 1);
|
||||
|
||||
i = testset.insert(values[0]).first;
|
||||
BOOST_TEST (&*i == &values[0]);
|
||||
|
||||
i = testset.iterator_to (values[2]);
|
||||
BOOST_TEST (&*i == &values[2]);
|
||||
|
||||
testset.erase (i);
|
||||
|
||||
{ int init_values [] = { 1, 3, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); }
|
||||
}
|
||||
|
||||
//test: insert (seq-version), swap, erase (seq-version), size:
|
||||
template<class ValueTraits>
|
||||
void test_unordered_set<ValueTraits>::test_swap(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef unordered_set
|
||||
<value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> unordered_set_type;
|
||||
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
||||
|
||||
typename unordered_set_type::bucket_type buckets1 [BucketSize];
|
||||
typename unordered_set_type::bucket_type buckets2 [BucketSize];
|
||||
unordered_set_type testset1(&values[0], &values[0] + 2, bucket_traits(buckets1, BucketSize));
|
||||
unordered_set_type testset2(bucket_traits(buckets2, BucketSize));
|
||||
|
||||
testset2.insert (&values[0] + 2, &values[0] + 6);
|
||||
testset1.swap (testset2);
|
||||
|
||||
{ int init_values [] = { 1, 2, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
{ int init_values [] = { 2, 3 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset2.begin() ); }
|
||||
|
||||
testset1.erase (testset1.iterator_to(values[5]), testset1.end());
|
||||
BOOST_TEST (testset1.size() == 1);
|
||||
// BOOST_TEST (&testset1.front() == &values[3]);
|
||||
BOOST_TEST (&*testset1.begin() == &values[3]);
|
||||
}
|
||||
|
||||
//test: rehash:
|
||||
template<class ValueTraits>
|
||||
void test_unordered_set<ValueTraits>::test_rehash(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef unordered_set
|
||||
<value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> unordered_set_type;
|
||||
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
||||
|
||||
typename unordered_set_type::bucket_type buckets1 [BucketSize];
|
||||
typename unordered_set_type::bucket_type buckets2 [2];
|
||||
typename unordered_set_type::bucket_type buckets3 [BucketSize*2];
|
||||
|
||||
unordered_set_type testset1(&values[0], &values[0] + 6, bucket_traits(buckets1, BucketSize));
|
||||
BOOST_TEST (testset1.size() == 5);
|
||||
{ int init_values [] = { 1, 2, 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
|
||||
testset1.rehash(bucket_traits(buckets2, 2));
|
||||
BOOST_TEST (testset1.size() == 5);
|
||||
{ int init_values [] = { 4, 2, 5, 3, 1 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
|
||||
testset1.rehash(bucket_traits(buckets3, BucketSize*2));
|
||||
BOOST_TEST (testset1.size() == 5);
|
||||
{ int init_values [] = { 1, 2, 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
|
||||
//Now rehash reducing the buckets
|
||||
testset1.rehash(bucket_traits(buckets3, 2));
|
||||
BOOST_TEST (testset1.size() == 5);
|
||||
{ int init_values [] = { 4, 2, 5, 3, 1 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
|
||||
//Now rehash increasing the buckets
|
||||
testset1.rehash(bucket_traits(buckets3, BucketSize*2));
|
||||
BOOST_TEST (testset1.size() == 5);
|
||||
{ int init_values [] = { 1, 2, 3, 4, 5 };
|
||||
TEST_INTRUSIVE_SEQUENCE( init_values, testset1.begin() ); }
|
||||
}
|
||||
|
||||
|
||||
//test: find, equal_range (lower_bound, upper_bound):
|
||||
template<class ValueTraits>
|
||||
void test_unordered_set<ValueTraits>::test_find(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef unordered_set
|
||||
<value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> unordered_set_type;
|
||||
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
||||
|
||||
typename unordered_set_type::bucket_type buckets [BucketSize];
|
||||
unordered_set_type testset (values.begin(), values.end(), bucket_traits(buckets, BucketSize));
|
||||
typedef typename unordered_set_type::iterator iterator;
|
||||
|
||||
value_type cmp_val;
|
||||
cmp_val.value_ = 2;
|
||||
iterator i = testset.find (cmp_val);
|
||||
BOOST_TEST (i->value_ == 2);
|
||||
BOOST_TEST ((++i)->value_ != 2);
|
||||
std::pair<iterator,iterator> range = testset.equal_range (cmp_val);
|
||||
|
||||
BOOST_TEST (range.first->value_ == 2);
|
||||
BOOST_TEST (range.second->value_ == 3);
|
||||
BOOST_TEST (std::distance (range.first, range.second) == 1);
|
||||
|
||||
cmp_val.value_ = 7;
|
||||
BOOST_TEST (testset.find (cmp_val) == testset.end());
|
||||
}
|
||||
|
||||
template<class ValueTraits>
|
||||
void test_unordered_set<ValueTraits>
|
||||
::test_clone(std::vector<typename ValueTraits::value_type>& values)
|
||||
{
|
||||
typedef typename ValueTraits::value_type value_type;
|
||||
typedef unordered_set
|
||||
<value_type
|
||||
, value_traits<ValueTraits>
|
||||
, constant_time_size<value_type::constant_time_size>
|
||||
> unordered_set_type;
|
||||
typedef typename unordered_set_type::bucket_traits bucket_traits;
|
||||
{
|
||||
//Test with equal bucket arrays
|
||||
typename unordered_set_type::bucket_type buckets1 [BucketSize];
|
||||
typename unordered_set_type::bucket_type buckets2 [BucketSize];
|
||||
unordered_set_type testset1 (values.begin(), values.end(), bucket_traits(buckets1, BucketSize));
|
||||
unordered_set_type testset2 (bucket_traits(buckets2, BucketSize));
|
||||
|
||||
testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
|
||||
//Ordering is not guarantee in the cloning so insert data in a set and test
|
||||
std::set<typename ValueTraits::value_type>
|
||||
src(testset1.begin(), testset1.end());
|
||||
std::set<typename ValueTraits::value_type>
|
||||
dst(testset2.begin(), testset2.end());
|
||||
BOOST_TEST (src.size() == dst.size() && std::equal(src.begin(), src.end(), dst.begin()));
|
||||
testset2.clear_and_dispose(test::delete_disposer<value_type>());
|
||||
BOOST_TEST (testset2.empty());
|
||||
}
|
||||
{
|
||||
//Test with bigger source bucket arrays
|
||||
typename unordered_set_type::bucket_type buckets1 [BucketSize*2];
|
||||
typename unordered_set_type::bucket_type buckets2 [BucketSize];
|
||||
unordered_set_type testset1 (values.begin(), values.end(), bucket_traits(buckets1, BucketSize*2));
|
||||
unordered_set_type testset2 (bucket_traits(buckets2, BucketSize));
|
||||
|
||||
testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
|
||||
//Ordering is not guarantee in the cloning so insert data in a set and test
|
||||
std::set<typename ValueTraits::value_type>
|
||||
src(testset1.begin(), testset1.end());
|
||||
std::set<typename ValueTraits::value_type>
|
||||
dst(testset2.begin(), testset2.end());
|
||||
BOOST_TEST (src.size() == dst.size() && std::equal(src.begin(), src.end(), dst.begin()));
|
||||
testset2.clear_and_dispose(test::delete_disposer<value_type>());
|
||||
BOOST_TEST (testset2.empty());
|
||||
}
|
||||
{
|
||||
//Test with smaller source bucket arrays
|
||||
typename unordered_set_type::bucket_type buckets1 [BucketSize];
|
||||
typename unordered_set_type::bucket_type buckets2 [BucketSize*2];
|
||||
unordered_set_type testset1 (values.begin(), values.end(), bucket_traits(buckets1, BucketSize));
|
||||
unordered_set_type testset2 (bucket_traits(buckets2, BucketSize*2));
|
||||
|
||||
testset2.clone_from(testset1, test::new_cloner<value_type>(), test::delete_disposer<value_type>());
|
||||
//Ordering is not guarantee in the cloning so insert data in a set and test
|
||||
std::set<typename ValueTraits::value_type>
|
||||
src(testset1.begin(), testset1.end());
|
||||
std::set<typename ValueTraits::value_type>
|
||||
dst(testset2.begin(), testset2.end());
|
||||
BOOST_TEST (src.size() == dst.size() && std::equal(src.begin(), src.end(), dst.begin()));
|
||||
testset2.clear_and_dispose(test::delete_disposer<value_type>());
|
||||
BOOST_TEST (testset2.empty());
|
||||
}
|
||||
}
|
||||
|
||||
template<class VoidPointer, bool constant_time_size>
|
||||
class test_main_template
|
||||
{
|
||||
public:
|
||||
int operator()()
|
||||
{
|
||||
typedef testvalue<VoidPointer, constant_time_size> value_type;
|
||||
static const int random_init[6] = { 3, 2, 4, 1, 5, 2 };
|
||||
std::vector<testvalue<VoidPointer, constant_time_size> > data (6);
|
||||
for (int i = 0; i < 6; ++i)
|
||||
data[i].value_ = random_init[i];
|
||||
|
||||
test_unordered_set < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::unordered_set_base_hook_t
|
||||
>::type
|
||||
>::test_all(data);
|
||||
test_unordered_set < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::unordered_set_member_hook_t
|
||||
, &value_type::unordered_set_node_
|
||||
>
|
||||
>::type
|
||||
>::test_all(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
template<class VoidPointer>
|
||||
class test_main_template<VoidPointer, false>
|
||||
{
|
||||
public:
|
||||
int operator()()
|
||||
{
|
||||
typedef testvalue<VoidPointer, false> value_type;
|
||||
static const int random_init[6] = { 3, 2, 4, 1, 5, 2 };
|
||||
std::vector<testvalue<VoidPointer, false> > data (6);
|
||||
for (int i = 0; i < 6; ++i)
|
||||
data[i].value_ = random_init[i];
|
||||
|
||||
test_unordered_set < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::unordered_set_base_hook_t
|
||||
>::type
|
||||
>::test_all(data);
|
||||
|
||||
test_unordered_set < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::unordered_set_member_hook_t
|
||||
, &value_type::unordered_set_node_
|
||||
>
|
||||
>::type
|
||||
>::test_all(data);
|
||||
|
||||
test_unordered_set < typename detail::get_base_value_traits
|
||||
< value_type
|
||||
, typename value_type::unordered_set_auto_base_hook_t
|
||||
>::type
|
||||
>::test_all(data);
|
||||
|
||||
test_unordered_set < typename detail::get_member_value_traits
|
||||
< value_type
|
||||
, member_hook< value_type
|
||||
, typename value_type::unordered_set_auto_member_hook_t
|
||||
, &value_type::unordered_set_auto_node_
|
||||
>
|
||||
>::type
|
||||
>::test_all(data);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
int main( int, char* [] )
|
||||
{
|
||||
test_main_template<void*, false>()();
|
||||
test_main_template<smart_ptr<void>, false>()();
|
||||
test_main_template<void*, true>()();
|
||||
test_main_template<smart_ptr<void>, true>()();
|
||||
return boost::report_errors();
|
||||
}
|
||||
#include <boost/intrusive/detail/config_end.hpp>
|
||||
@@ -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