iterator_test.hpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  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)
  6. //
  7. // See http://www.boost.org/libs/intrusive for documentation.
  8. //
  9. //////////////////////////////////////////////////////////////////////////////
  10. #include <boost/intrusive/detail/iterator.hpp>
  11. #include <boost/intrusive/detail/mpl.hpp>
  12. #include <boost/static_assert.hpp>
  13. namespace boost{ namespace intrusive { namespace test{
  14. //////////////////////////////////////////////
  15. //
  16. // Some traits to avoid special cases with
  17. // containers without bidirectional iterators
  18. //
  19. //////////////////////////////////////////////
  20. template<class C>
  21. struct has_member_reverse_iterator
  22. {
  23. typedef char yes_type;
  24. struct no_type{ char _[2]; };
  25. template<typename D> static no_type test(...);
  26. template<typename D> static yes_type test(typename D::reverse_iterator const*);
  27. static const bool value = sizeof(test<C>(0)) == sizeof(yes_type);
  28. };
  29. template<class C>
  30. struct has_member_const_reverse_iterator
  31. {
  32. typedef char yes_type;
  33. struct no_type{ char _[2]; };
  34. template<typename D> static no_type test(...);
  35. template<typename D> static yes_type test(typename D::const_reverse_iterator const*);
  36. static const bool value = sizeof(test<C>(0)) == sizeof(yes_type);
  37. };
  38. template<class C, bool = has_member_reverse_iterator<C>::value>
  39. struct get_reverse_iterator
  40. {
  41. typedef typename C::reverse_iterator type;
  42. static type begin(C &c) { return c.rbegin(); }
  43. static type end(C &c) { return c.rend(); }
  44. };
  45. template<class C>
  46. struct get_reverse_iterator<C, false>
  47. {
  48. typedef typename C::iterator type;
  49. static type begin(C &c) { return c.begin(); }
  50. static type end(C &c) { return c.end(); }
  51. };
  52. template<class C, bool = has_member_const_reverse_iterator<C>::value>
  53. struct get_const_reverse_iterator
  54. {
  55. typedef typename C::const_reverse_iterator type;
  56. static type begin(C &c) { return c.crbegin(); }
  57. static type end(C &c) { return c.crend(); }
  58. };
  59. template<class C>
  60. struct get_const_reverse_iterator<C, false>
  61. {
  62. typedef typename C::const_iterator type;
  63. static type begin(C &c) { return c.cbegin(); }
  64. static type end(C &c) { return c.cend(); }
  65. };
  66. //////////////////////////////////////////////
  67. //
  68. // Iterator tests
  69. //
  70. //////////////////////////////////////////////
  71. template<class I>
  72. void test_iterator_operations(I b, I e)
  73. {
  74. //Test the range is not empty
  75. BOOST_TEST(b != e);
  76. BOOST_TEST(!(b == e));
  77. {
  78. I i;
  79. I i2(b); //CopyConstructible
  80. i = i2; //Assignable
  81. //Destructible
  82. (void)i;
  83. (void)i2;
  84. }
  85. typedef typename iterator_traits<I>::reference reference;
  86. reference r = *b;
  87. (void)r;
  88. typedef typename iterator_traits<I>::pointer pointer;
  89. pointer p = (iterator_arrow_result)(b);
  90. (void)p;
  91. I &ri= ++b;
  92. (void)ri;
  93. const I &cri= b++;
  94. (void)cri;
  95. }
  96. template<class C>
  97. void test_iterator_compatible(C &c)
  98. {
  99. typedef typename C::iterator iterator;
  100. typedef typename C::const_iterator const_iterator;
  101. typedef typename get_reverse_iterator<C>::type reverse_iterator;
  102. typedef typename get_const_reverse_iterator<C>::type const_reverse_iterator;
  103. //Basic operations
  104. test_iterator_operations(c. begin(), c. end());
  105. test_iterator_operations(c.cbegin(), c.cend());
  106. test_iterator_operations(get_reverse_iterator<C>::begin(c), get_reverse_iterator<C>::end(c));
  107. test_iterator_operations(get_const_reverse_iterator<C>::begin(c), get_const_reverse_iterator<C>::end(c));
  108. //Make sure dangeous conversions are not possible
  109. BOOST_STATIC_ASSERT((!boost::intrusive::detail::is_convertible<const_iterator, iterator>::value));
  110. BOOST_STATIC_ASSERT((!boost::intrusive::detail::is_convertible<const_reverse_iterator, reverse_iterator>::value));
  111. //Test iterator conversions
  112. {
  113. const_iterator ci;
  114. iterator i(c.begin());
  115. ci = i;
  116. (void)ci;
  117. BOOST_ASSERT(ci == i);
  118. BOOST_ASSERT(*ci == *i);
  119. const_iterator ci2(i);
  120. BOOST_ASSERT(ci2 == i);
  121. BOOST_ASSERT(*ci2 == *i);
  122. (void)ci2;
  123. }
  124. //Test reverse_iterator conversions
  125. {
  126. const_reverse_iterator cr;
  127. reverse_iterator r(get_reverse_iterator<C>::begin(c));
  128. cr = r;
  129. BOOST_ASSERT(cr == r);
  130. BOOST_ASSERT(*cr == *r);
  131. const_reverse_iterator cr2(r);
  132. BOOST_ASSERT(cr2 == r);
  133. BOOST_ASSERT(*cr2 == *r);
  134. (void)cr2;
  135. }
  136. }
  137. template<class C>
  138. void test_iterator_input_and_compatible(C &c)
  139. {
  140. typedef typename C::iterator iterator;
  141. typedef typename C::const_iterator const_iterator;
  142. typedef typename get_reverse_iterator<C>::type reverse_iterator;
  143. typedef typename get_const_reverse_iterator<C>::type const_reverse_iterator;
  144. typedef iterator_traits<iterator> nit_traits;
  145. typedef iterator_traits<const_iterator> cit_traits;
  146. typedef iterator_traits<reverse_iterator> rnit_traits;
  147. typedef iterator_traits<const_reverse_iterator> crit_traits;
  148. using boost::move_detail::is_same;
  149. //Trivial typedefs
  150. BOOST_STATIC_ASSERT((!is_same<iterator, const_iterator>::value));
  151. BOOST_STATIC_ASSERT((!is_same<reverse_iterator, const_reverse_iterator>::value));
  152. //difference_type
  153. typedef typename C::difference_type difference_type;
  154. BOOST_STATIC_ASSERT((is_same<difference_type, typename nit_traits::difference_type>::value));
  155. BOOST_STATIC_ASSERT((is_same<difference_type, typename cit_traits::difference_type>::value));
  156. BOOST_STATIC_ASSERT((is_same<difference_type, typename rnit_traits::difference_type>::value));
  157. BOOST_STATIC_ASSERT((is_same<difference_type, typename crit_traits::difference_type>::value));
  158. //value_type
  159. typedef typename C::value_type value_type;
  160. BOOST_STATIC_ASSERT((is_same<value_type, typename nit_traits::value_type>::value));
  161. BOOST_STATIC_ASSERT((is_same<value_type, typename cit_traits::value_type>::value));
  162. BOOST_STATIC_ASSERT((is_same<value_type, typename rnit_traits::value_type>::value));
  163. BOOST_STATIC_ASSERT((is_same<value_type, typename crit_traits::value_type>::value));
  164. //pointer
  165. typedef typename C::pointer pointer;
  166. typedef typename C::const_pointer const_pointer;
  167. BOOST_STATIC_ASSERT((is_same<pointer, typename nit_traits::pointer>::value));
  168. BOOST_STATIC_ASSERT((is_same<const_pointer, typename cit_traits::pointer>::value));
  169. BOOST_STATIC_ASSERT((is_same<pointer, typename rnit_traits::pointer>::value));
  170. BOOST_STATIC_ASSERT((is_same<const_pointer, typename crit_traits::pointer>::value));
  171. //reference
  172. typedef typename C::reference reference;
  173. typedef typename C::const_reference const_reference;
  174. BOOST_STATIC_ASSERT((is_same<reference, typename nit_traits::reference>::value));
  175. BOOST_STATIC_ASSERT((is_same<const_reference, typename cit_traits::reference>::value));
  176. BOOST_STATIC_ASSERT((is_same<reference, typename rnit_traits::reference>::value));
  177. BOOST_STATIC_ASSERT((is_same<const_reference, typename crit_traits::reference>::value));
  178. //Dynamic tests
  179. test_iterator_compatible(c);
  180. }
  181. template<class C, class I>
  182. void test_iterator_forward_functions(C const &c, I const b, I const e)
  183. {
  184. typedef typename C::size_type size_type;
  185. {
  186. size_type i = 0;
  187. I it = b;
  188. for(I it2 = b; i != c.size(); ++it, ++i){
  189. BOOST_TEST(it == it2++);
  190. I ittmp(it);
  191. I *iaddr = &ittmp;
  192. BOOST_TEST(&(++ittmp) == iaddr);
  193. BOOST_TEST(ittmp == it2);
  194. }
  195. BOOST_TEST(i == c.size());
  196. BOOST_TEST(it == e);
  197. }
  198. }
  199. template<class C>
  200. void test_iterator_forward_and_compatible(C &c)
  201. {
  202. test_iterator_input_and_compatible(c);
  203. test_iterator_forward_functions(c, c.begin(), c.end());
  204. test_iterator_forward_functions(c, c.cbegin(), c.cend());
  205. test_iterator_forward_functions(c, get_reverse_iterator<C>::begin(c), get_reverse_iterator<C>::end(c));
  206. test_iterator_forward_functions(c, get_const_reverse_iterator<C>::begin(c), get_const_reverse_iterator<C>::end(c));
  207. }
  208. template<class C, class I>
  209. void test_iterator_bidirectional_functions(C const &c, I const b, I const e)
  210. {
  211. typedef typename C::size_type size_type;
  212. {
  213. size_type i = 0;
  214. I it = e;
  215. for(I it2 = e; i != c.size(); --it, ++i){
  216. BOOST_TEST(it == it2--);
  217. I ittmp(it);
  218. I*iaddr = &ittmp;
  219. BOOST_TEST(&(--ittmp) == iaddr);
  220. BOOST_TEST(ittmp == it2);
  221. BOOST_TEST((++ittmp) == it);
  222. }
  223. BOOST_TEST(i == c.size());
  224. BOOST_TEST(it == b);
  225. }
  226. }
  227. template<class C>
  228. void test_iterator_bidirectional_and_compatible(C &c)
  229. {
  230. test_iterator_forward_and_compatible(c);
  231. test_iterator_bidirectional_functions(c, c.begin(), c.end());
  232. test_iterator_bidirectional_functions(c, c.cbegin(), c.cend());
  233. test_iterator_bidirectional_functions(c, c.rbegin(), c.rend());
  234. test_iterator_bidirectional_functions(c, c.crbegin(), c.crend());
  235. }
  236. template<class C, class I>
  237. void test_iterator_random_functions(C const &c, I const b, I const e)
  238. {
  239. typedef typename C::size_type size_type;
  240. {
  241. I it = b;
  242. for(size_type i = 0, m = c.size(); i != m; ++i, ++it){
  243. BOOST_TEST(i == size_type(it - b));
  244. BOOST_TEST(b[i] == *it);
  245. BOOST_TEST(&b[i] == &*it);
  246. BOOST_TEST((b + i) == it);
  247. BOOST_TEST((i + b) == it);
  248. BOOST_TEST(b == (it - i));
  249. I tmp(b);
  250. BOOST_TEST((tmp+=i) == it);
  251. tmp = it;
  252. BOOST_TEST(b == (tmp-=i));
  253. }
  254. BOOST_TEST(c.size() == size_type(e - b));
  255. }
  256. {
  257. I it(b), itb(b);
  258. if(b != e){
  259. for(++it; it != e; ++it){
  260. BOOST_TEST(itb < it);
  261. BOOST_TEST(itb <= it);
  262. BOOST_TEST(!(itb > it));
  263. BOOST_TEST(!(itb >= it));
  264. BOOST_TEST(it > itb);
  265. BOOST_TEST(it >= itb);
  266. BOOST_TEST(!(it < itb));
  267. BOOST_TEST(!(it <= itb));
  268. BOOST_TEST(it >= it);
  269. BOOST_TEST(it <= it);
  270. itb = it;
  271. }
  272. }
  273. }
  274. }
  275. template<class C>
  276. void test_iterator_random_and_compatible(C &c)
  277. {
  278. test_iterator_bidirectional_and_compatible(c);
  279. test_iterator_random_functions(c, c.begin(), c.end());
  280. test_iterator_random_functions(c, c.cbegin(), c.cend());
  281. test_iterator_random_functions(c, c.rbegin(), c.rend());
  282. test_iterator_random_functions(c, c.crbegin(), c.crend());
  283. }
  284. ////////////////////////
  285. template<class C>
  286. void test_iterator_forward(C &c)
  287. {
  288. typedef typename C::iterator iterator;
  289. typedef typename C::const_iterator const_iterator;
  290. typedef typename get_reverse_iterator<C>::type reverse_iterator;
  291. typedef typename get_const_reverse_iterator<C>::type const_reverse_iterator;
  292. typedef iterator_traits<iterator> nit_traits;
  293. typedef iterator_traits<const_iterator> cit_traits;
  294. typedef iterator_traits<reverse_iterator> rnit_traits;
  295. typedef iterator_traits<const_reverse_iterator> crit_traits;
  296. using boost::intrusive::detail::is_same;
  297. //iterator_category
  298. BOOST_STATIC_ASSERT((is_same<std::forward_iterator_tag, typename nit_traits::iterator_category>::value));
  299. BOOST_STATIC_ASSERT((is_same<std::forward_iterator_tag, typename cit_traits::iterator_category>::value));
  300. BOOST_STATIC_ASSERT((is_same<std::forward_iterator_tag, typename rnit_traits::iterator_category>::value));
  301. BOOST_STATIC_ASSERT((is_same<std::forward_iterator_tag, typename crit_traits::iterator_category>::value));
  302. //Test dynamic
  303. test_iterator_forward_and_compatible(c);
  304. }
  305. template<class C>
  306. void test_iterator_bidirectional(C &c)
  307. {
  308. typedef typename C::iterator iterator;
  309. typedef typename C::const_iterator const_iterator;
  310. typedef typename C::reverse_iterator reverse_iterator;
  311. typedef typename C::const_reverse_iterator const_reverse_iterator;
  312. typedef iterator_traits<iterator> nit_traits;
  313. typedef iterator_traits<const_iterator> cit_traits;
  314. typedef iterator_traits<reverse_iterator> rnit_traits;
  315. typedef iterator_traits<const_reverse_iterator> crit_traits;
  316. using boost::intrusive::detail::is_same;
  317. //iterator_category
  318. BOOST_STATIC_ASSERT((is_same<std::bidirectional_iterator_tag, typename nit_traits::iterator_category>::value));
  319. BOOST_STATIC_ASSERT((is_same<std::bidirectional_iterator_tag, typename cit_traits::iterator_category>::value));
  320. BOOST_STATIC_ASSERT((is_same<std::bidirectional_iterator_tag, typename rnit_traits::iterator_category>::value));
  321. BOOST_STATIC_ASSERT((is_same<std::bidirectional_iterator_tag, typename crit_traits::iterator_category>::value));
  322. //Test dynamic
  323. test_iterator_bidirectional_and_compatible(c);
  324. }
  325. template<class C>
  326. void test_iterator_random(C &c)
  327. {
  328. typedef typename C::iterator iterator;
  329. typedef typename C::const_iterator const_iterator;
  330. typedef typename C::reverse_iterator reverse_iterator;
  331. typedef typename C::const_reverse_iterator const_reverse_iterator;
  332. typedef iterator_traits<iterator> nit_traits;
  333. typedef iterator_traits<const_iterator> cit_traits;
  334. typedef iterator_traits<reverse_iterator> rnit_traits;
  335. typedef iterator_traits<const_reverse_iterator> crit_traits;
  336. using boost::intrusive::detail::is_same;
  337. //iterator_category
  338. BOOST_STATIC_ASSERT((is_same<std::random_access_iterator_tag, typename nit_traits::iterator_category>::value));
  339. BOOST_STATIC_ASSERT((is_same<std::random_access_iterator_tag, typename cit_traits::iterator_category>::value));
  340. BOOST_STATIC_ASSERT((is_same<std::random_access_iterator_tag, typename rnit_traits::iterator_category>::value));
  341. BOOST_STATIC_ASSERT((is_same<std::random_access_iterator_tag, typename crit_traits::iterator_category>::value));
  342. //Test dynamic
  343. test_iterator_random_and_compatible(c);
  344. }
  345. }}} //boost::container::test