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,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;
|
||||
}
|
||||
Reference in New Issue
Block a user