1 //////////////////////////////////////////////////////////////////////////////
3 // (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
4 // Software License, Version 1.0. (See accompanying file
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 // See http://www.boost.org/libs/intrusive for documentation.
9 //////////////////////////////////////////////////////////////////////////////
11 #include <boost/intrusive/detail/iterator.hpp>
12 #include <boost/intrusive/detail/mpl.hpp>
13 #include <boost/static_assert.hpp>
15 namespace boost{ namespace intrusive { namespace test{
17 //////////////////////////////////////////////
19 // Some traits to avoid special cases with
20 // containers without bidirectional iterators
22 //////////////////////////////////////////////
24 struct has_member_reverse_iterator
26 typedef char yes_type;
27 struct no_type{ char _[2]; };
29 template<typename D> static no_type test(...);
30 template<typename D> static yes_type test(typename D::reverse_iterator const*);
31 static const bool value = sizeof(test<C>(0)) == sizeof(yes_type);
35 struct has_member_const_reverse_iterator
37 typedef char yes_type;
38 struct no_type{ char _[2]; };
40 template<typename D> static no_type test(...);
41 template<typename D> static yes_type test(typename D::const_reverse_iterator const*);
42 static const bool value = sizeof(test<C>(0)) == sizeof(yes_type);
45 template<class C, bool = has_member_reverse_iterator<C>::value>
46 struct get_reverse_iterator
48 typedef typename C::reverse_iterator type;
49 static type begin(C &c) { return c.rbegin(); }
50 static type end(C &c) { return c.rend(); }
54 struct get_reverse_iterator<C, false>
56 typedef typename C::iterator type;
57 static type begin(C &c) { return c.begin(); }
58 static type end(C &c) { return c.end(); }
61 template<class C, bool = has_member_const_reverse_iterator<C>::value>
62 struct get_const_reverse_iterator
64 typedef typename C::const_reverse_iterator type;
65 static type begin(C &c) { return c.crbegin(); }
66 static type end(C &c) { return c.crend(); }
70 struct get_const_reverse_iterator<C, false>
72 typedef typename C::const_iterator type;
73 static type begin(C &c) { return c.cbegin(); }
74 static type end(C &c) { return c.cend(); }
77 //////////////////////////////////////////////
81 //////////////////////////////////////////////
84 void test_iterator_operations(I b, I e)
86 //Test the range is not empty
88 BOOST_TEST(!(b == e));
91 I i2(b); //CopyConstructible
98 typedef typename iterator_traits<I>::reference reference;
101 typedef typename iterator_traits<I>::pointer pointer;
102 pointer p = (iterator_arrow_result)(b);
111 void test_iterator_compatible(C &c)
113 typedef typename C::iterator iterator;
114 typedef typename C::const_iterator const_iterator;
115 typedef typename get_reverse_iterator<C>::type reverse_iterator;
116 typedef typename get_const_reverse_iterator<C>::type const_reverse_iterator;
118 test_iterator_operations(c. begin(), c. end());
119 test_iterator_operations(c.cbegin(), c.cend());
120 test_iterator_operations(get_reverse_iterator<C>::begin(c), get_reverse_iterator<C>::end(c));
121 test_iterator_operations(get_const_reverse_iterator<C>::begin(c), get_const_reverse_iterator<C>::end(c));
122 //Make sure dangeous conversions are not possible
123 BOOST_STATIC_ASSERT((!boost::intrusive::detail::is_convertible<const_iterator, iterator>::value));
124 BOOST_STATIC_ASSERT((!boost::intrusive::detail::is_convertible<const_reverse_iterator, reverse_iterator>::value));
125 //Test iterator conversions
128 iterator i(c.begin());
131 BOOST_ASSERT(ci == i);
132 BOOST_ASSERT(*ci == *i);
133 const_iterator ci2(i);
134 BOOST_ASSERT(ci2 == i);
135 BOOST_ASSERT(*ci2 == *i);
138 //Test reverse_iterator conversions
140 const_reverse_iterator cr;
141 reverse_iterator r(get_reverse_iterator<C>::begin(c));
143 BOOST_ASSERT(cr == r);
144 BOOST_ASSERT(*cr == *r);
145 const_reverse_iterator cr2(r);
146 BOOST_ASSERT(cr2 == r);
147 BOOST_ASSERT(*cr2 == *r);
153 void test_iterator_input_and_compatible(C &c)
155 typedef typename C::iterator iterator;
156 typedef typename C::const_iterator const_iterator;
157 typedef typename get_reverse_iterator<C>::type reverse_iterator;
158 typedef typename get_const_reverse_iterator<C>::type const_reverse_iterator;
159 typedef iterator_traits<iterator> nit_traits;
160 typedef iterator_traits<const_iterator> cit_traits;
161 typedef iterator_traits<reverse_iterator> rnit_traits;
162 typedef iterator_traits<const_reverse_iterator> crit_traits;
164 using boost::move_detail::is_same;
166 BOOST_STATIC_ASSERT((!is_same<iterator, const_iterator>::value));
167 BOOST_STATIC_ASSERT((!is_same<reverse_iterator, const_reverse_iterator>::value));
169 typedef typename C::difference_type difference_type;
170 BOOST_STATIC_ASSERT((is_same<difference_type, typename nit_traits::difference_type>::value));
171 BOOST_STATIC_ASSERT((is_same<difference_type, typename cit_traits::difference_type>::value));
172 BOOST_STATIC_ASSERT((is_same<difference_type, typename rnit_traits::difference_type>::value));
173 BOOST_STATIC_ASSERT((is_same<difference_type, typename crit_traits::difference_type>::value));
175 typedef typename C::value_type value_type;
176 BOOST_STATIC_ASSERT((is_same<value_type, typename nit_traits::value_type>::value));
177 BOOST_STATIC_ASSERT((is_same<value_type, typename cit_traits::value_type>::value));
178 BOOST_STATIC_ASSERT((is_same<value_type, typename rnit_traits::value_type>::value));
179 BOOST_STATIC_ASSERT((is_same<value_type, typename crit_traits::value_type>::value));
181 typedef typename C::pointer pointer;
182 typedef typename C::const_pointer const_pointer;
183 BOOST_STATIC_ASSERT((is_same<pointer, typename nit_traits::pointer>::value));
184 BOOST_STATIC_ASSERT((is_same<const_pointer, typename cit_traits::pointer>::value));
185 BOOST_STATIC_ASSERT((is_same<pointer, typename rnit_traits::pointer>::value));
186 BOOST_STATIC_ASSERT((is_same<const_pointer, typename crit_traits::pointer>::value));
188 typedef typename C::reference reference;
189 typedef typename C::const_reference const_reference;
190 BOOST_STATIC_ASSERT((is_same<reference, typename nit_traits::reference>::value));
191 BOOST_STATIC_ASSERT((is_same<const_reference, typename cit_traits::reference>::value));
192 BOOST_STATIC_ASSERT((is_same<reference, typename rnit_traits::reference>::value));
193 BOOST_STATIC_ASSERT((is_same<const_reference, typename crit_traits::reference>::value));
195 test_iterator_compatible(c);
198 template<class C, class I>
199 void test_iterator_forward_functions(C const &c, I const b, I const e)
201 typedef typename C::size_type size_type;
205 for(I it2 = b; i != c.size(); ++it, ++i){
206 BOOST_TEST(it == it2++);
209 BOOST_TEST(&(++ittmp) == iaddr);
210 BOOST_TEST(ittmp == it2);
212 BOOST_TEST(i == c.size());
218 void test_iterator_forward_and_compatible(C &c)
220 test_iterator_input_and_compatible(c);
221 test_iterator_forward_functions(c, c.begin(), c.end());
222 test_iterator_forward_functions(c, c.cbegin(), c.cend());
223 test_iterator_forward_functions(c, get_reverse_iterator<C>::begin(c), get_reverse_iterator<C>::end(c));
224 test_iterator_forward_functions(c, get_const_reverse_iterator<C>::begin(c), get_const_reverse_iterator<C>::end(c));
227 template<class C, class I>
228 void test_iterator_bidirectional_functions(C const &c, I const b, I const e)
230 typedef typename C::size_type size_type;
234 for(I it2 = e; i != c.size(); --it, ++i){
235 BOOST_TEST(it == it2--);
238 BOOST_TEST(&(--ittmp) == iaddr);
239 BOOST_TEST(ittmp == it2);
240 BOOST_TEST((++ittmp) == it);
242 BOOST_TEST(i == c.size());
248 void test_iterator_bidirectional_and_compatible(C &c)
250 test_iterator_forward_and_compatible(c);
251 test_iterator_bidirectional_functions(c, c.begin(), c.end());
252 test_iterator_bidirectional_functions(c, c.cbegin(), c.cend());
253 test_iterator_bidirectional_functions(c, c.rbegin(), c.rend());
254 test_iterator_bidirectional_functions(c, c.crbegin(), c.crend());
257 template<class C, class I>
258 void test_iterator_random_functions(C const &c, I const b, I const e)
260 typedef typename C::size_type size_type;
263 for(size_type i = 0, m = c.size(); i != m; ++i, ++it){
264 BOOST_TEST(i == size_type(it - b));
265 BOOST_TEST(b[i] == *it);
266 BOOST_TEST(&b[i] == &*it);
267 BOOST_TEST((b + i) == it);
268 BOOST_TEST((i + b) == it);
269 BOOST_TEST(b == (it - i));
271 BOOST_TEST((tmp+=i) == it);
273 BOOST_TEST(b == (tmp-=i));
275 BOOST_TEST(c.size() == size_type(e - b));
280 for(++it; it != e; ++it){
281 BOOST_TEST(itb < it);
282 BOOST_TEST(itb <= it);
283 BOOST_TEST(!(itb > it));
284 BOOST_TEST(!(itb >= it));
285 BOOST_TEST(it > itb);
286 BOOST_TEST(it >= itb);
287 BOOST_TEST(!(it < itb));
288 BOOST_TEST(!(it <= itb));
289 BOOST_TEST(it >= it);
290 BOOST_TEST(it <= it);
298 void test_iterator_random_and_compatible(C &c)
300 test_iterator_bidirectional_and_compatible(c);
301 test_iterator_random_functions(c, c.begin(), c.end());
302 test_iterator_random_functions(c, c.cbegin(), c.cend());
303 test_iterator_random_functions(c, c.rbegin(), c.rend());
304 test_iterator_random_functions(c, c.crbegin(), c.crend());
307 ////////////////////////
310 void test_iterator_forward(C &c)
312 typedef typename C::iterator iterator;
313 typedef typename C::const_iterator const_iterator;
314 typedef typename get_reverse_iterator<C>::type reverse_iterator;
315 typedef typename get_const_reverse_iterator<C>::type const_reverse_iterator;
316 typedef iterator_traits<iterator> nit_traits;
317 typedef iterator_traits<const_iterator> cit_traits;
318 typedef iterator_traits<reverse_iterator> rnit_traits;
319 typedef iterator_traits<const_reverse_iterator> crit_traits;
321 using boost::intrusive::detail::is_same;
323 BOOST_STATIC_ASSERT((is_same<std::forward_iterator_tag, typename nit_traits::iterator_category>::value));
324 BOOST_STATIC_ASSERT((is_same<std::forward_iterator_tag, typename cit_traits::iterator_category>::value));
325 BOOST_STATIC_ASSERT((is_same<std::forward_iterator_tag, typename rnit_traits::iterator_category>::value));
326 BOOST_STATIC_ASSERT((is_same<std::forward_iterator_tag, typename crit_traits::iterator_category>::value));
328 test_iterator_forward_and_compatible(c);
332 void test_iterator_bidirectional(C &c)
334 typedef typename C::iterator iterator;
335 typedef typename C::const_iterator const_iterator;
336 typedef typename C::reverse_iterator reverse_iterator;
337 typedef typename C::const_reverse_iterator const_reverse_iterator;
338 typedef iterator_traits<iterator> nit_traits;
339 typedef iterator_traits<const_iterator> cit_traits;
340 typedef iterator_traits<reverse_iterator> rnit_traits;
341 typedef iterator_traits<const_reverse_iterator> crit_traits;
343 using boost::intrusive::detail::is_same;
345 BOOST_STATIC_ASSERT((is_same<std::bidirectional_iterator_tag, typename nit_traits::iterator_category>::value));
346 BOOST_STATIC_ASSERT((is_same<std::bidirectional_iterator_tag, typename cit_traits::iterator_category>::value));
347 BOOST_STATIC_ASSERT((is_same<std::bidirectional_iterator_tag, typename rnit_traits::iterator_category>::value));
348 BOOST_STATIC_ASSERT((is_same<std::bidirectional_iterator_tag, typename crit_traits::iterator_category>::value));
350 test_iterator_bidirectional_and_compatible(c);
354 void test_iterator_random(C &c)
356 typedef typename C::iterator iterator;
357 typedef typename C::const_iterator const_iterator;
358 typedef typename C::reverse_iterator reverse_iterator;
359 typedef typename C::const_reverse_iterator const_reverse_iterator;
360 typedef iterator_traits<iterator> nit_traits;
361 typedef iterator_traits<const_iterator> cit_traits;
362 typedef iterator_traits<reverse_iterator> rnit_traits;
363 typedef iterator_traits<const_reverse_iterator> crit_traits;
365 using boost::intrusive::detail::is_same;
367 BOOST_STATIC_ASSERT((is_same<std::random_access_iterator_tag, typename nit_traits::iterator_category>::value));
368 BOOST_STATIC_ASSERT((is_same<std::random_access_iterator_tag, typename cit_traits::iterator_category>::value));
369 BOOST_STATIC_ASSERT((is_same<std::random_access_iterator_tag, typename rnit_traits::iterator_category>::value));
370 BOOST_STATIC_ASSERT((is_same<std::random_access_iterator_tag, typename crit_traits::iterator_category>::value));
372 test_iterator_random_and_compatible(c);
375 }}} //boost::container::test