utility_iterator.hpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. // Copyright 2003 David Abrahams and Jeremy Siek
  2. // Copyright 2019 Hans Dembinski
  3. //
  4. // Distributed under the Boost Software License, Version 1.0.
  5. // (See accompanying file LICENSE_1_0.txt
  6. // or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. #ifndef BOOST_HISTOGRAM_TEST_ITERATOR_TESTS_HPP
  8. #define BOOST_HISTOGRAM_TEST_ITERATOR_TESTS_HPP
  9. // This file contains adapted code from
  10. // - boost::core::iterator; boost/pending/iterator_tests.hpp
  11. // - boost::core::conversion; boost/implicit_cast.hpp
  12. #include <boost/core/ignore_unused.hpp>
  13. #include <boost/core/lightweight_test.hpp>
  14. #include <iterator>
  15. #include <type_traits>
  16. namespace boost {
  17. namespace histogram {
  18. namespace detail {
  19. template <class T>
  20. struct icast_identity {
  21. typedef T type;
  22. };
  23. } // namespace detail
  24. template <typename T>
  25. inline T implicit_cast(typename detail::icast_identity<T>::type x) {
  26. return x;
  27. }
  28. // use this for the value type
  29. struct dummyT {
  30. dummyT() {}
  31. dummyT(char) {}
  32. dummyT(int x) : m_x(x) {}
  33. int foo() const { return m_x; }
  34. bool operator==(const dummyT& d) const { return m_x == d.m_x; }
  35. int m_x;
  36. };
  37. // Tests whether type Iterator satisfies the requirements for a
  38. // TrivialIterator.
  39. // Preconditions: i != j, *i == val
  40. template <class Iterator, class T>
  41. void trivial_iterator_test(const Iterator i, const Iterator j, T val) {
  42. Iterator k;
  43. BOOST_TEST(i == i);
  44. BOOST_TEST(j == j);
  45. BOOST_TEST(i != j);
  46. typename std::iterator_traits<Iterator>::value_type v = *i;
  47. BOOST_TEST(v == val);
  48. ignore_unused(v);
  49. BOOST_TEST(v == i->foo());
  50. k = i;
  51. BOOST_TEST(k == k);
  52. BOOST_TEST(k == i);
  53. BOOST_TEST(k != j);
  54. BOOST_TEST(*k == val);
  55. ignore_unused(k);
  56. }
  57. // Preconditions: i != j
  58. template <class Iterator, class T>
  59. void mutable_trivial_iterator_test(const Iterator i, const Iterator j, T val) {
  60. *i = val;
  61. trivial_iterator_test(i, j, val);
  62. }
  63. // Preconditions: *i == v1, *++i == v2
  64. template <class Iterator, class T>
  65. void input_iterator_test(Iterator i, T v1, T v2) {
  66. Iterator i1(i);
  67. BOOST_TEST(i == i1);
  68. BOOST_TEST(!(i != i1));
  69. // I can see no generic way to create an input iterator
  70. // that is in the domain of== of i and != i.
  71. // The following works for istream_iterator but is not
  72. // guaranteed to work for arbitrary input iterators.
  73. //
  74. // Iterator i2;
  75. //
  76. // BOOST_TEST(i != i2);
  77. // BOOST_TEST(!(i == i2));
  78. BOOST_TEST(*i1 == v1);
  79. BOOST_TEST(*i == v1);
  80. // we cannot test for equivalence of (void)++i & (void)i++
  81. // as i is only guaranteed to be single pass.
  82. BOOST_TEST(*i++ == v1);
  83. ignore_unused(i1);
  84. i1 = i;
  85. BOOST_TEST(i == i1);
  86. BOOST_TEST(!(i != i1));
  87. BOOST_TEST(*i1 == v2);
  88. BOOST_TEST(*i == v2);
  89. ignore_unused(i1);
  90. // i is dereferencable, so it must be incrementable.
  91. ++i;
  92. // how to test for operator-> ?
  93. }
  94. template <class Iterator, class T>
  95. void forward_iterator_test(Iterator i, T v1, T v2) {
  96. input_iterator_test(i, v1, v2);
  97. Iterator i1 = i, i2 = i;
  98. BOOST_TEST(i == i1++);
  99. BOOST_TEST(i != ++i2);
  100. trivial_iterator_test(i, i1, v1);
  101. trivial_iterator_test(i, i2, v1);
  102. ++i;
  103. BOOST_TEST(i == i1);
  104. BOOST_TEST(i == i2);
  105. ++i1;
  106. ++i2;
  107. trivial_iterator_test(i, i1, v2);
  108. trivial_iterator_test(i, i2, v2);
  109. typedef typename std::iterator_traits<Iterator>::reference reference;
  110. typedef typename std::iterator_traits<Iterator>::value_type value_type;
  111. BOOST_TEST(std::is_reference<reference>::value);
  112. BOOST_TEST((std::is_same<reference, value_type&>::value ||
  113. std::is_same<reference, const value_type&>::value));
  114. }
  115. // Preconditions: *i == v1, *++i == v2
  116. template <class Iterator, class T>
  117. void bidirectional_iterator_test(Iterator i, T v1, T v2) {
  118. forward_iterator_test(i, v1, v2);
  119. ++i;
  120. Iterator i1 = i, i2 = i;
  121. BOOST_TEST(i == i1--);
  122. BOOST_TEST(i != --i2);
  123. trivial_iterator_test(i, i1, v2);
  124. trivial_iterator_test(i, i2, v2);
  125. --i;
  126. BOOST_TEST(i == i1);
  127. BOOST_TEST(i == i2);
  128. ++i1;
  129. ++i2;
  130. trivial_iterator_test(i, i1, v1);
  131. trivial_iterator_test(i, i2, v1);
  132. }
  133. // mutable_bidirectional_iterator_test
  134. template <class U>
  135. struct undefined;
  136. // Preconditions: [i,i+N) is a valid range
  137. template <class Iterator, class TrueVals>
  138. void random_access_iterator_test(Iterator i, int N, TrueVals vals) {
  139. bidirectional_iterator_test(i, vals[0], vals[1]);
  140. const Iterator j = i;
  141. int c;
  142. typedef typename std::iterator_traits<Iterator>::value_type value_type;
  143. ignore_unused<value_type>();
  144. for (c = 0; c < N - 1; ++c) {
  145. BOOST_TEST(i == j + c);
  146. BOOST_TEST(*i == vals[c]);
  147. BOOST_TEST(*i == implicit_cast<value_type>(j[c]));
  148. BOOST_TEST(*i == *(j + c));
  149. BOOST_TEST(*i == *(c + j));
  150. ++i;
  151. BOOST_TEST(i > j);
  152. BOOST_TEST(i >= j);
  153. BOOST_TEST(j <= i);
  154. BOOST_TEST(j < i);
  155. }
  156. Iterator k = j + N - 1;
  157. for (c = 0; c < N - 1; ++c) {
  158. BOOST_TEST(i == k - c);
  159. BOOST_TEST(*i == vals[N - 1 - c]);
  160. BOOST_TEST(*i == implicit_cast<value_type>(j[N - 1 - c]));
  161. Iterator q = k - c;
  162. ignore_unused(q);
  163. BOOST_TEST(*i == *q);
  164. BOOST_TEST(i > j);
  165. BOOST_TEST(i >= j);
  166. BOOST_TEST(j <= i);
  167. BOOST_TEST(j < i);
  168. --i;
  169. }
  170. }
  171. // Precondition: i != j
  172. template <class Iterator, class ConstIterator>
  173. void const_nonconst_iterator_test(Iterator i, ConstIterator j) {
  174. BOOST_TEST(i != j);
  175. BOOST_TEST(j != i);
  176. ConstIterator k(i);
  177. BOOST_TEST(k == i);
  178. BOOST_TEST(i == k);
  179. k = i;
  180. BOOST_TEST(k == i);
  181. BOOST_TEST(i == k);
  182. ignore_unused(k);
  183. }
  184. } // namespace histogram
  185. } // namespace boost
  186. #endif // BOOST_HISTOGRAM_TEST_ITERATOR_TESTS_HPP