new_iterator_tests.hpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. #ifndef BOOST_NEW_ITERATOR_TESTS_HPP
  2. #define BOOST_NEW_ITERATOR_TESTS_HPP
  3. //
  4. // Copyright (c) David Abrahams 2001.
  5. // Copyright (c) Jeremy Siek 2001-2003.
  6. // Copyright (c) Thomas Witt 2002.
  7. //
  8. // Use, modification and distribution is subject to the
  9. // Boost Software License, Version 1.0.
  10. // (See accompanying file LICENSE_1_0.txt or copy at
  11. // http://www.boost.org/LICENSE_1_0.txt)
  12. //
  13. // This is meant to be the beginnings of a comprehensive, generic
  14. // test suite for STL concepts such as iterators and containers.
  15. //
  16. // Revision History:
  17. // 28 Oct 2002 Started update for new iterator categories
  18. // (Jeremy Siek)
  19. // 28 Apr 2002 Fixed input iterator requirements.
  20. // For a == b a++ == b++ is no longer required.
  21. // See 24.1.1/3 for details.
  22. // (Thomas Witt)
  23. // 08 Feb 2001 Fixed bidirectional iterator test so that
  24. // --i is no longer a precondition.
  25. // (Jeremy Siek)
  26. // 04 Feb 2001 Added lvalue test, corrected preconditions
  27. // (David Abrahams)
  28. #include <boost/concept_archetype.hpp> // for detail::dummy_constructor
  29. #include <boost/iterator/is_lvalue_iterator.hpp>
  30. #include <boost/iterator/is_readable_iterator.hpp>
  31. #include <boost/pending/iterator_tests.hpp>
  32. #include <boost/core/lightweight_test.hpp>
  33. #include <boost/detail/is_incrementable.hpp>
  34. #include <boost/iterator/detail/type_traits/conjunction.hpp>
  35. #include <iterator>
  36. #include <type_traits>
  37. namespace boost {
  38. // Do separate tests for *i++ so we can treat, e.g., smart pointers,
  39. // as readable and/or writable iterators.
  40. template <class Iterator, class T>
  41. void readable_iterator_traversal_test(Iterator i1, T v, std::true_type)
  42. {
  43. T v2(*i1++);
  44. BOOST_TEST(v == v2);
  45. }
  46. template <class Iterator, class T>
  47. void readable_iterator_traversal_test(const Iterator i1, T v, std::false_type)
  48. {}
  49. template <class Iterator, class T>
  50. void writable_iterator_traversal_test(Iterator i1, T v, std::true_type)
  51. {
  52. ++i1; // we just wrote into that position
  53. *i1++ = v;
  54. Iterator x(i1++);
  55. (void)x;
  56. }
  57. template <class Iterator, class T>
  58. void writable_iterator_traversal_test(const Iterator i1, T v, std::false_type)
  59. {}
  60. // Preconditions: *i == v
  61. template <class Iterator, class T>
  62. void readable_iterator_test(const Iterator i1, T v)
  63. {
  64. Iterator i2(i1); // Copy Constructible
  65. typedef typename std::iterator_traits<Iterator>::reference ref_t;
  66. ref_t r1 = *i1;
  67. ref_t r2 = *i2;
  68. T v1 = r1;
  69. T v2 = r2;
  70. BOOST_TEST(v1 == v);
  71. BOOST_TEST(v2 == v);
  72. readable_iterator_traversal_test(
  73. i1, v,
  74. std::integral_constant<
  75. bool, detail::is_postfix_incrementable<Iterator>::value>{});
  76. // I think we don't really need this as it checks the same things as
  77. // the above code.
  78. static_assert(is_readable_iterator<Iterator>::value,
  79. "Iterator must be readable.");
  80. }
  81. template <class Iterator, class T>
  82. void writable_iterator_test(Iterator i, T v, T v2)
  83. {
  84. Iterator i2(i); // Copy Constructible
  85. *i2 = v;
  86. writable_iterator_traversal_test(
  87. i, v2,
  88. iterators::detail::conjunction<
  89. std::integral_constant<bool, detail::is_incrementable<Iterator>::value>,
  90. std::integral_constant<bool, detail::is_postfix_incrementable<Iterator>::value>
  91. >());
  92. }
  93. template <class Iterator>
  94. void swappable_iterator_test(Iterator i, Iterator j)
  95. {
  96. Iterator i2(i), j2(j);
  97. typename std::iterator_traits<Iterator>::value_type bi = *i, bj = *j;
  98. iter_swap(i2, j2);
  99. typename std::iterator_traits<Iterator>::value_type ai = *i, aj = *j;
  100. BOOST_TEST(bi == aj && bj == ai);
  101. }
  102. template <class Iterator, class T>
  103. void constant_lvalue_iterator_test(Iterator i, T v1)
  104. {
  105. Iterator i2(i);
  106. typedef typename std::iterator_traits<Iterator>::value_type value_type;
  107. typedef typename std::iterator_traits<Iterator>::reference reference;
  108. static_assert(std::is_same<const value_type&, reference>::value,
  109. "reference type must be the same as const value_type& for "
  110. "constant lvalue iterator.");
  111. const T& v2 = *i2;
  112. BOOST_TEST(v1 == v2);
  113. #ifndef BOOST_NO_LVALUE_RETURN_DETECTION
  114. static_assert(is_lvalue_iterator<Iterator>::value
  115. && !is_non_const_lvalue_iterator<Iterator>::value,
  116. "Iterator must be a const lvalue iterator.");
  117. #endif
  118. }
  119. template <class Iterator, class T>
  120. void non_const_lvalue_iterator_test(Iterator i, T v1, T v2)
  121. {
  122. Iterator i2(i);
  123. typedef typename std::iterator_traits<Iterator>::value_type value_type;
  124. typedef typename std::iterator_traits<Iterator>::reference reference;
  125. static_assert(std::is_same<value_type&, reference>::value,
  126. "reference type must be the same as value_type& for "
  127. "non-constant lvalue iterator.");
  128. T& v3 = *i2;
  129. BOOST_TEST(v1 == v3);
  130. // A non-const lvalue iterator is not necessarily writable, but we
  131. // are assuming the value_type is assignable here
  132. *i = v2;
  133. T& v4 = *i2;
  134. BOOST_TEST(v2 == v4);
  135. static_assert(is_lvalue_iterator<Iterator>::value,
  136. "Iterator must be an lvalue iterator.");
  137. static_assert(is_non_const_lvalue_iterator<Iterator>::value,
  138. "Iterator must be non-const.");
  139. }
  140. template <class Iterator, class T>
  141. void forward_readable_iterator_test(Iterator i, Iterator j, T val1, T val2)
  142. {
  143. Iterator i2;
  144. Iterator i3(i);
  145. i2 = i;
  146. BOOST_TEST(i2 == i3);
  147. BOOST_TEST(i != j);
  148. BOOST_TEST(i2 != j);
  149. readable_iterator_test(i, val1);
  150. readable_iterator_test(i2, val1);
  151. readable_iterator_test(i3, val1);
  152. BOOST_TEST(i == i2++);
  153. BOOST_TEST(i != ++i3);
  154. readable_iterator_test(i2, val2);
  155. readable_iterator_test(i3, val2);
  156. readable_iterator_test(i, val1);
  157. }
  158. template <class Iterator, class T>
  159. void forward_swappable_iterator_test(Iterator i, Iterator j, T val1, T val2)
  160. {
  161. forward_readable_iterator_test(i, j, val1, val2);
  162. Iterator i2 = i;
  163. ++i2;
  164. swappable_iterator_test(i, i2);
  165. }
  166. // bidirectional
  167. // Preconditions: *i == v1, *++i == v2
  168. template <class Iterator, class T>
  169. void bidirectional_readable_iterator_test(Iterator i, T v1, T v2)
  170. {
  171. Iterator j(i);
  172. ++j;
  173. forward_readable_iterator_test(i, j, v1, v2);
  174. ++i;
  175. Iterator i1 = i, i2 = i;
  176. BOOST_TEST(i == i1--);
  177. BOOST_TEST(i != --i2);
  178. readable_iterator_test(i, v2);
  179. readable_iterator_test(i1, v1);
  180. readable_iterator_test(i2, v1);
  181. --i;
  182. BOOST_TEST(i == i1);
  183. BOOST_TEST(i == i2);
  184. ++i1;
  185. ++i2;
  186. readable_iterator_test(i, v1);
  187. readable_iterator_test(i1, v2);
  188. readable_iterator_test(i2, v2);
  189. }
  190. // random access
  191. // Preconditions: [i,i+N) is a valid range
  192. template <class Iterator, class TrueVals>
  193. void random_access_readable_iterator_test(Iterator i, int N, TrueVals vals)
  194. {
  195. bidirectional_readable_iterator_test(i, vals[0], vals[1]);
  196. const Iterator j = i;
  197. int c;
  198. for (c = 0; c < N - 1; ++c)
  199. {
  200. BOOST_TEST(i == j + c);
  201. BOOST_TEST(*i == vals[c]);
  202. typename std::iterator_traits<Iterator>::value_type x = j[c];
  203. BOOST_TEST(*i == x);
  204. BOOST_TEST(*i == *(j + c));
  205. BOOST_TEST(*i == *(c + j));
  206. ++i;
  207. BOOST_TEST(i > j);
  208. BOOST_TEST(i >= j);
  209. BOOST_TEST(j <= i);
  210. BOOST_TEST(j < i);
  211. }
  212. Iterator k = j + N - 1;
  213. for (c = 0; c < N - 1; ++c)
  214. {
  215. BOOST_TEST(i == k - c);
  216. BOOST_TEST(*i == vals[N - 1 - c]);
  217. typename std::iterator_traits<Iterator>::value_type x = j[N - 1 - c];
  218. BOOST_TEST(*i == x);
  219. Iterator q = k - c;
  220. BOOST_TEST(*i == *q);
  221. BOOST_TEST(i > j);
  222. BOOST_TEST(i >= j);
  223. BOOST_TEST(j <= i);
  224. BOOST_TEST(j < i);
  225. --i;
  226. }
  227. }
  228. } // namespace boost
  229. #endif // BOOST_NEW_ITERATOR_TESTS_HPP