iterator_tests.hpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. // Copyright David Abrahams and Jeremy Siek 2003.
  2. // Distributed under the Boost Software License, Version 1.0. (See
  3. // accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. #ifndef BOOST_ITERATOR_TESTS_HPP
  6. # define BOOST_ITERATOR_TESTS_HPP
  7. // This is meant to be the beginnings of a comprehensive, generic
  8. // test suite for STL concepts such as iterators and containers.
  9. //
  10. // Revision History:
  11. // 28 Apr 2002 Fixed input iterator requirements.
  12. // For a == b a++ == b++ is no longer required.
  13. // See 24.1.1/3 for details.
  14. // (Thomas Witt)
  15. // 08 Feb 2001 Fixed bidirectional iterator test so that
  16. // --i is no longer a precondition.
  17. // (Jeremy Siek)
  18. // 04 Feb 2001 Added lvalue test, corrected preconditions
  19. // (David Abrahams)
  20. # include <iterator>
  21. # include <boost/static_assert.hpp>
  22. # include <boost/concept_archetype.hpp> // for detail::dummy_constructor
  23. # include <boost/core/ignore_unused.hpp>
  24. # include <boost/core/lightweight_test.hpp>
  25. # include <boost/type_traits/is_same.hpp>
  26. # include <boost/type_traits/is_pointer.hpp>
  27. # include <boost/type_traits/is_reference.hpp>
  28. namespace boost {
  29. // use this for the value type
  30. struct dummyT {
  31. dummyT() { }
  32. dummyT(detail::dummy_constructor) { }
  33. dummyT(int x) : m_x(x) { }
  34. int foo() const { return m_x; }
  35. bool operator==(const dummyT& d) const { return m_x == d.m_x; }
  36. int m_x;
  37. };
  38. }
  39. namespace boost {
  40. namespace iterators {
  41. // Tests whether type Iterator satisfies the requirements for a
  42. // TrivialIterator.
  43. // Preconditions: i != j, *i == val
  44. template <class Iterator, class T>
  45. void trivial_iterator_test(const Iterator i, const Iterator j, T val)
  46. {
  47. Iterator k;
  48. BOOST_TEST(i == i);
  49. BOOST_TEST(j == j);
  50. BOOST_TEST(i != j);
  51. #ifdef BOOST_NO_STD_ITERATOR_TRAITS
  52. T v = *i;
  53. #else
  54. typename std::iterator_traits<Iterator>::value_type v = *i;
  55. #endif
  56. BOOST_TEST(v == val);
  57. boost::ignore_unused(v);
  58. #if 0
  59. // hmm, this will give a warning for transform_iterator... perhaps
  60. // this should be separated out into a stand-alone test since there
  61. // are several situations where it can't be used, like for
  62. // integer_range::iterator.
  63. BOOST_TEST(v == i->foo());
  64. #endif
  65. k = i;
  66. BOOST_TEST(k == k);
  67. BOOST_TEST(k == i);
  68. BOOST_TEST(k != j);
  69. BOOST_TEST(*k == val);
  70. boost::ignore_unused(k);
  71. }
  72. // Preconditions: i != j
  73. template <class Iterator, class T>
  74. void mutable_trivial_iterator_test(const Iterator i, const Iterator j, T val)
  75. {
  76. *i = val;
  77. trivial_iterator_test(i, j, val);
  78. }
  79. // Preconditions: *i == v1, *++i == v2
  80. template <class Iterator, class T>
  81. void input_iterator_test(Iterator i, T v1, T v2)
  82. {
  83. Iterator i1(i);
  84. BOOST_TEST(i == i1);
  85. BOOST_TEST(!(i != i1));
  86. // I can see no generic way to create an input iterator
  87. // that is in the domain of== of i and != i.
  88. // The following works for istream_iterator but is not
  89. // guaranteed to work for arbitrary input iterators.
  90. //
  91. // Iterator i2;
  92. //
  93. // BOOST_TEST(i != i2);
  94. // BOOST_TEST(!(i == i2));
  95. BOOST_TEST(*i1 == v1);
  96. BOOST_TEST(*i == v1);
  97. // we cannot test for equivalence of (void)++i & (void)i++
  98. // as i is only guaranteed to be single pass.
  99. BOOST_TEST(*i++ == v1);
  100. boost::ignore_unused(i1);
  101. i1 = i;
  102. BOOST_TEST(i == i1);
  103. BOOST_TEST(!(i != i1));
  104. BOOST_TEST(*i1 == v2);
  105. BOOST_TEST(*i == v2);
  106. boost::ignore_unused(i1);
  107. // i is dereferencable, so it must be incrementable.
  108. ++i;
  109. // how to test for operator-> ?
  110. }
  111. // how to test output iterator?
  112. template <bool is_pointer> struct lvalue_test
  113. {
  114. template <class Iterator> static void check(Iterator)
  115. {
  116. # ifndef BOOST_NO_STD_ITERATOR_TRAITS
  117. typedef typename std::iterator_traits<Iterator>::reference reference;
  118. typedef typename std::iterator_traits<Iterator>::value_type value_type;
  119. # else
  120. typedef typename Iterator::reference reference;
  121. typedef typename Iterator::value_type value_type;
  122. # endif
  123. BOOST_STATIC_ASSERT(boost::is_reference<reference>::value);
  124. BOOST_STATIC_ASSERT((boost::is_same<reference,value_type&>::value
  125. || boost::is_same<reference,const value_type&>::value
  126. ));
  127. }
  128. };
  129. # ifdef BOOST_NO_STD_ITERATOR_TRAITS
  130. template <> struct lvalue_test<true> {
  131. template <class T> static void check(T) {}
  132. };
  133. #endif
  134. template <class Iterator, class T>
  135. void forward_iterator_test(Iterator i, T v1, T v2)
  136. {
  137. input_iterator_test(i, v1, v2);
  138. Iterator i1 = i, i2 = i;
  139. BOOST_TEST(i == i1++);
  140. BOOST_TEST(i != ++i2);
  141. trivial_iterator_test(i, i1, v1);
  142. trivial_iterator_test(i, i2, v1);
  143. ++i;
  144. BOOST_TEST(i == i1);
  145. BOOST_TEST(i == i2);
  146. ++i1;
  147. ++i2;
  148. trivial_iterator_test(i, i1, v2);
  149. trivial_iterator_test(i, i2, v2);
  150. // borland doesn't allow non-type template parameters
  151. # if !defined(BOOST_BORLANDC) || (BOOST_BORLANDC > 0x551)
  152. lvalue_test<(boost::is_pointer<Iterator>::value)>::check(i);
  153. #endif
  154. }
  155. // Preconditions: *i == v1, *++i == v2
  156. template <class Iterator, class T>
  157. void bidirectional_iterator_test(Iterator i, T v1, T v2)
  158. {
  159. forward_iterator_test(i, v1, v2);
  160. ++i;
  161. Iterator i1 = i, i2 = i;
  162. BOOST_TEST(i == i1--);
  163. BOOST_TEST(i != --i2);
  164. trivial_iterator_test(i, i1, v2);
  165. trivial_iterator_test(i, i2, v2);
  166. --i;
  167. BOOST_TEST(i == i1);
  168. BOOST_TEST(i == i2);
  169. ++i1;
  170. ++i2;
  171. trivial_iterator_test(i, i1, v1);
  172. trivial_iterator_test(i, i2, v1);
  173. }
  174. // mutable_bidirectional_iterator_test
  175. template <class U> struct undefined;
  176. // Preconditions: [i,i+N) is a valid range
  177. template <class Iterator, class TrueVals>
  178. void random_access_iterator_test(Iterator i, int N, TrueVals vals)
  179. {
  180. bidirectional_iterator_test(i, vals[0], vals[1]);
  181. const Iterator j = i;
  182. int c;
  183. typedef typename std::iterator_traits<Iterator>::value_type value_type;
  184. struct local
  185. {
  186. static value_type to_value_type(value_type v) { return v; }
  187. };
  188. for (c = 0; c < N-1; ++c) {
  189. BOOST_TEST(i == j + c);
  190. BOOST_TEST(*i == vals[c]);
  191. BOOST_TEST(*i == local::to_value_type(j[c]));
  192. BOOST_TEST(*i == *(j + c));
  193. BOOST_TEST(*i == *(c + j));
  194. ++i;
  195. BOOST_TEST(i > j);
  196. BOOST_TEST(i >= j);
  197. BOOST_TEST(j <= i);
  198. BOOST_TEST(j < i);
  199. }
  200. Iterator k = j + N - 1;
  201. for (c = 0; c < N-1; ++c) {
  202. BOOST_TEST(i == k - c);
  203. BOOST_TEST(*i == vals[N - 1 - c]);
  204. BOOST_TEST(*i == local::to_value_type(j[N - 1 - c]));
  205. Iterator q = k - c;
  206. boost::ignore_unused(q);
  207. BOOST_TEST(*i == *q);
  208. BOOST_TEST(i > j);
  209. BOOST_TEST(i >= j);
  210. BOOST_TEST(j <= i);
  211. BOOST_TEST(j < i);
  212. --i;
  213. }
  214. }
  215. // Precondition: i != j
  216. template <class Iterator, class ConstIterator>
  217. void const_nonconst_iterator_test(Iterator i, ConstIterator j)
  218. {
  219. BOOST_TEST(i != j);
  220. BOOST_TEST(j != i);
  221. ConstIterator k(i);
  222. BOOST_TEST(k == i);
  223. BOOST_TEST(i == k);
  224. k = i;
  225. BOOST_TEST(k == i);
  226. BOOST_TEST(i == k);
  227. boost::ignore_unused(k);
  228. }
  229. } // namespace iterators
  230. using iterators::undefined;
  231. using iterators::trivial_iterator_test;
  232. using iterators::mutable_trivial_iterator_test;
  233. using iterators::input_iterator_test;
  234. using iterators::lvalue_test;
  235. using iterators::forward_iterator_test;
  236. using iterators::bidirectional_iterator_test;
  237. using iterators::random_access_iterator_test;
  238. using iterators::const_nonconst_iterator_test;
  239. } // namespace boost
  240. #endif // BOOST_ITERATOR_TESTS_HPP