iterator_tests.hpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  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 <assert.h>
  22. # include <boost/type_traits.hpp>
  23. # include <boost/static_assert.hpp>
  24. # include <boost/concept_archetype.hpp> // for detail::dummy_constructor
  25. # include <boost/implicit_cast.hpp>
  26. namespace boost {
  27. // use this for the value type
  28. struct dummyT {
  29. dummyT() { }
  30. dummyT(detail::dummy_constructor) { }
  31. dummyT(int x) : m_x(x) { }
  32. int foo() const { return m_x; }
  33. bool operator==(const dummyT& d) const { return m_x == d.m_x; }
  34. int m_x;
  35. };
  36. }
  37. namespace boost {
  38. namespace iterators {
  39. // Tests whether type Iterator satisfies the requirements for a
  40. // TrivialIterator.
  41. // Preconditions: i != j, *i == val
  42. template <class Iterator, class T>
  43. void trivial_iterator_test(const Iterator i, const Iterator j, T val)
  44. {
  45. Iterator k;
  46. assert(i == i);
  47. assert(j == j);
  48. assert(i != j);
  49. #ifdef BOOST_NO_STD_ITERATOR_TRAITS
  50. T v = *i;
  51. #else
  52. typename std::iterator_traits<Iterator>::value_type v = *i;
  53. #endif
  54. assert(v == val);
  55. #if 0
  56. // hmm, this will give a warning for transform_iterator... perhaps
  57. // this should be separated out into a stand-alone test since there
  58. // are several situations where it can't be used, like for
  59. // integer_range::iterator.
  60. assert(v == i->foo());
  61. #endif
  62. k = i;
  63. assert(k == k);
  64. assert(k == i);
  65. assert(k != j);
  66. assert(*k == val);
  67. }
  68. // Preconditions: i != j
  69. template <class Iterator, class T>
  70. void mutable_trivial_iterator_test(const Iterator i, const Iterator j, T val)
  71. {
  72. *i = val;
  73. trivial_iterator_test(i, j, val);
  74. }
  75. // Preconditions: *i == v1, *++i == v2
  76. template <class Iterator, class T>
  77. void input_iterator_test(Iterator i, T v1, T v2)
  78. {
  79. Iterator i1(i);
  80. assert(i == i1);
  81. assert(!(i != i1));
  82. // I can see no generic way to create an input iterator
  83. // that is in the domain of== of i and != i.
  84. // The following works for istream_iterator but is not
  85. // guaranteed to work for arbitrary input iterators.
  86. //
  87. // Iterator i2;
  88. //
  89. // assert(i != i2);
  90. // assert(!(i == i2));
  91. assert(*i1 == v1);
  92. assert(*i == v1);
  93. // we cannot test for equivalence of (void)++i & (void)i++
  94. // as i is only guaranteed to be single pass.
  95. assert(*i++ == v1);
  96. i1 = i;
  97. assert(i == i1);
  98. assert(!(i != i1));
  99. assert(*i1 == v2);
  100. assert(*i == v2);
  101. // i is dereferencable, so it must be incrementable.
  102. ++i;
  103. // how to test for operator-> ?
  104. }
  105. // how to test output iterator?
  106. template <bool is_pointer> struct lvalue_test
  107. {
  108. template <class Iterator> static void check(Iterator)
  109. {
  110. # ifndef BOOST_NO_STD_ITERATOR_TRAITS
  111. typedef typename std::iterator_traits<Iterator>::reference reference;
  112. typedef typename std::iterator_traits<Iterator>::value_type value_type;
  113. # else
  114. typedef typename Iterator::reference reference;
  115. typedef typename Iterator::value_type value_type;
  116. # endif
  117. BOOST_STATIC_ASSERT(boost::is_reference<reference>::value);
  118. BOOST_STATIC_ASSERT((boost::is_same<reference,value_type&>::value
  119. || boost::is_same<reference,const value_type&>::value
  120. ));
  121. }
  122. };
  123. # ifdef BOOST_NO_STD_ITERATOR_TRAITS
  124. template <> struct lvalue_test<true> {
  125. template <class T> static void check(T) {}
  126. };
  127. #endif
  128. template <class Iterator, class T>
  129. void forward_iterator_test(Iterator i, T v1, T v2)
  130. {
  131. input_iterator_test(i, v1, v2);
  132. Iterator i1 = i, i2 = i;
  133. assert(i == i1++);
  134. assert(i != ++i2);
  135. trivial_iterator_test(i, i1, v1);
  136. trivial_iterator_test(i, i2, v1);
  137. ++i;
  138. assert(i == i1);
  139. assert(i == i2);
  140. ++i1;
  141. ++i2;
  142. trivial_iterator_test(i, i1, v2);
  143. trivial_iterator_test(i, i2, v2);
  144. // borland doesn't allow non-type template parameters
  145. # if !defined(__BORLANDC__) || (__BORLANDC__ > 0x551)
  146. lvalue_test<(boost::is_pointer<Iterator>::value)>::check(i);
  147. #endif
  148. }
  149. // Preconditions: *i == v1, *++i == v2
  150. template <class Iterator, class T>
  151. void bidirectional_iterator_test(Iterator i, T v1, T v2)
  152. {
  153. forward_iterator_test(i, v1, v2);
  154. ++i;
  155. Iterator i1 = i, i2 = i;
  156. assert(i == i1--);
  157. assert(i != --i2);
  158. trivial_iterator_test(i, i1, v2);
  159. trivial_iterator_test(i, i2, v2);
  160. --i;
  161. assert(i == i1);
  162. assert(i == i2);
  163. ++i1;
  164. ++i2;
  165. trivial_iterator_test(i, i1, v1);
  166. trivial_iterator_test(i, i2, v1);
  167. }
  168. // mutable_bidirectional_iterator_test
  169. template <class U> struct undefined;
  170. // Preconditions: [i,i+N) is a valid range
  171. template <class Iterator, class TrueVals>
  172. void random_access_iterator_test(Iterator i, int N, TrueVals vals)
  173. {
  174. bidirectional_iterator_test(i, vals[0], vals[1]);
  175. const Iterator j = i;
  176. int c;
  177. typedef typename boost::detail::iterator_traits<Iterator>::value_type value_type;
  178. for (c = 0; c < N-1; ++c) {
  179. assert(i == j + c);
  180. assert(*i == vals[c]);
  181. assert(*i == boost::implicit_cast<value_type>(j[c]));
  182. assert(*i == *(j + c));
  183. assert(*i == *(c + j));
  184. ++i;
  185. assert(i > j);
  186. assert(i >= j);
  187. assert(j <= i);
  188. assert(j < i);
  189. }
  190. Iterator k = j + N - 1;
  191. for (c = 0; c < N-1; ++c) {
  192. assert(i == k - c);
  193. assert(*i == vals[N - 1 - c]);
  194. assert(*i == boost::implicit_cast<value_type>(j[N - 1 - c]));
  195. Iterator q = k - c;
  196. assert(*i == *q);
  197. assert(i > j);
  198. assert(i >= j);
  199. assert(j <= i);
  200. assert(j < i);
  201. --i;
  202. }
  203. }
  204. // Precondition: i != j
  205. template <class Iterator, class ConstIterator>
  206. void const_nonconst_iterator_test(Iterator i, ConstIterator j)
  207. {
  208. assert(i != j);
  209. assert(j != i);
  210. ConstIterator k(i);
  211. assert(k == i);
  212. assert(i == k);
  213. k = i;
  214. assert(k == i);
  215. assert(i == k);
  216. }
  217. } // namespace iterators
  218. using iterators::undefined;
  219. using iterators::trivial_iterator_test;
  220. using iterators::mutable_trivial_iterator_test;
  221. using iterators::input_iterator_test;
  222. using iterators::lvalue_test;
  223. using iterators::forward_iterator_test;
  224. using iterators::bidirectional_iterator_test;
  225. using iterators::random_access_iterator_test;
  226. using iterators::const_nonconst_iterator_test;
  227. } // namespace boost
  228. #endif // BOOST_ITERATOR_TESTS_HPP