1 /////////////////////////////////////////////////////////////////////////////
3 // (C) Copyright Ion Gaztanaga 2007-2013
5 // Distributed under the Boost Software License, Version 1.0.
6 // (See accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
9 // See http://www.boost.org/libs/intrusive for documentation.
11 /////////////////////////////////////////////////////////////////////////////
12 #include <boost/intrusive/list.hpp>
13 #include <boost/intrusive/slist.hpp>
14 #include <boost/intrusive/set.hpp>
15 #include <boost/intrusive/unordered_set.hpp>
16 #include <boost/container_hash/hash.hpp>
17 #include <boost/intrusive/pointer_traits.hpp>
20 using namespace boost::intrusive
;
31 friend bool operator<(const MyClass
&l
, const MyClass
&r
)
32 { return l
.int_
< r
.int_
; }
34 friend bool operator==(const MyClass
&l
, const MyClass
&r
)
35 { return l
.int_
== r
.int_
; }
37 friend std::size_t hash_value(const MyClass
&v
)
38 { return boost::hash_value(v
.int_
); }
41 template<class T
, class NodeTraits
>
42 struct stateful_value_traits
44 typedef NodeTraits node_traits
;
45 typedef typename
node_traits::node node
;
46 typedef typename
node_traits::node_ptr node_ptr
;
47 typedef typename
node_traits::const_node_ptr const_node_ptr
;
49 typedef typename pointer_traits
<node_ptr
>::
50 template rebind_pointer
<T
>::type pointer
;
51 typedef typename pointer_traits
<node_ptr
>::
52 template rebind_pointer
<const T
>::type const_pointer
;
54 static const link_mode_type link_mode
= normal_link
;
56 stateful_value_traits(pointer vals
, node_ptr node_array
)
57 : values_(vals
), node_array_(node_array
)
60 node_ptr
to_node_ptr (value_type
&value
) const
61 { return node_array_
+ (&value
- values_
); }
63 const_node_ptr
to_node_ptr (const value_type
&value
) const
64 { return node_array_
+ (&value
- values_
); }
66 pointer
to_value_ptr(node_ptr n
) const
67 { return values_
+ (n
- node_array_
); }
69 const_pointer
to_value_ptr(const_node_ptr n
) const
70 { return values_
+ (n
- node_array_
); }
76 //Define a list that will store MyClass using the external hook
77 typedef stateful_value_traits
< MyClass
, list_node_traits
<void*> > list_traits
;
78 typedef list
<MyClass
, value_traits
<list_traits
> > List
;
80 //Define a slist that will store MyClass using the external hook
81 typedef stateful_value_traits
< MyClass
, slist_node_traits
<void*> > slist_traits
;
82 typedef slist
<MyClass
, value_traits
<slist_traits
> > Slist
;
84 //Define a set that will store MyClass using the external hook
85 typedef stateful_value_traits
< MyClass
, rbtree_node_traits
<void*> > rbtree_traits
;
86 typedef set
<MyClass
, value_traits
<rbtree_traits
> > Set
;
88 //uset uses the same traits as slist
89 typedef unordered_set
<MyClass
, value_traits
<slist_traits
> > Uset
;
92 typedef list_traits::node list_node_t
;
93 typedef slist_traits::node slist_node_t
;
94 typedef rbtree_traits::node rbtree_node_t
;
96 const int NumElements
= 100;
98 MyClass values
[NumElements
];
99 list_node_t list_hook_array
[NumElements
];
100 slist_node_t slist_hook_array
[NumElements
];
101 rbtree_node_t rbtree_hook_array
[NumElements
];
102 slist_node_t uset_hook_array
[NumElements
];
106 //Create several MyClass objects, each one with a different value
107 for(int i
= 0; i
< NumElements
; ++i
)
110 Uset::bucket_type buckets
[NumElements
];
112 List
my_list (list_traits (values
, list_hook_array
));
113 Slist
my_slist(slist_traits(values
, slist_hook_array
));
114 Set
my_set (std::less
<MyClass
>(), rbtree_traits(values
, rbtree_hook_array
));
115 Uset
my_uset ( Uset::bucket_traits(buckets
, NumElements
)
116 , boost::hash
<MyClass
>()
117 , std::equal_to
<MyClass
>()
118 , slist_traits(values
, uset_hook_array
)
121 //Now insert them in containers
122 for(MyClass
* it(&values
[0]), *itend(&values
[NumElements
])
125 my_list
.push_front(*it
);
126 if(&*my_list
.iterator_to(*it
) != &my_list
.front())
128 my_slist
.push_front(*it
);
129 if(&*my_slist
.iterator_to(*it
) != &my_slist
.front())
131 Set::iterator sit
= my_set
.insert(*it
).first
;
132 if(&*my_set
.iterator_to(*it
) != &*sit
)
134 Uset::iterator uit
= my_uset
.insert(*it
).first
;
136 if(&*my_uset
.iterator_to(*it
) != &*uit
)
142 List::const_iterator
list_it (my_list
.cbegin());
143 Slist::const_iterator
slist_it(my_slist
.cbegin());
144 Set::const_reverse_iterator
set_rit(my_set
.crbegin());
145 MyClass
*it_val(&values
[NumElements
]), *it_rbeg_val(&values
[0]);
147 //Test the objects inserted in the base hook list
148 for(; it_val
!= it_rbeg_val
; --it_val
, ++list_it
, ++slist_it
, ++set_rit
){
149 if(&*list_it
!= &it_val
[-1]) return 1;
150 if(&*slist_it
!= &it_val
[-1]) return 1;
151 if(&*set_rit
!= &it_val
[-1]) return 1;
152 if(my_uset
.find(it_val
[-1]) == my_uset
.cend()) return 1;