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
8 // This is meant to be the beginnings of a comprehensive, generic
9 // test suite for STL concepts such as iterators and containers.
12 // 28 Apr 2002 Fixed input iterator requirements.
13 // For a == b a++ == b++ is no longer required.
14 // See 24.1.1/3 for details.
16 // 08 Feb 2001 Fixed bidirectional iterator test so that
17 // --i is no longer a precondition.
19 // 04 Feb 2001 Added lvalue test, corrected preconditions
24 # include <boost/type_traits.hpp>
25 # include <boost/static_assert.hpp>
26 # include <boost/concept_archetype.hpp> // for detail::dummy_constructor
27 # include <boost/implicit_cast.hpp>
31 // use this for the value type
34 dummyT(detail::dummy_constructor) { }
35 dummyT(int x) : m_x(x) { }
36 int foo() const { return m_x; }
37 bool operator==(const dummyT& d) const { return m_x == d.m_x; }
46 // Tests whether type Iterator satisfies the requirements for a
48 // Preconditions: i != j, *i == val
49 template <class Iterator, class T>
50 void trivial_iterator_test(const Iterator i, const Iterator j, T val)
56 #ifdef BOOST_NO_STD_ITERATOR_TRAITS
59 typename std::iterator_traits<Iterator>::value_type v = *i;
63 // hmm, this will give a warning for transform_iterator... perhaps
64 // this should be separated out into a stand-alone test since there
65 // are several situations where it can't be used, like for
66 // integer_range::iterator.
67 assert(v == i->foo());
77 // Preconditions: i != j
78 template <class Iterator, class T>
79 void mutable_trivial_iterator_test(const Iterator i, const Iterator j, T val)
82 trivial_iterator_test(i, j, val);
86 // Preconditions: *i == v1, *++i == v2
87 template <class Iterator, class T>
88 void input_iterator_test(Iterator i, T v1, T v2)
95 // I can see no generic way to create an input iterator
96 // that is in the domain of== of i and != i.
97 // The following works for istream_iterator but is not
98 // guaranteed to work for arbitrary input iterators.
103 // assert(!(i == i2));
108 // we cannot test for equivalence of (void)++i & (void)i++
109 // as i is only guaranteed to be single pass.
120 // i is dereferencable, so it must be incrementable.
123 // how to test for operator-> ?
126 // how to test output iterator?
129 template <bool is_pointer> struct lvalue_test
131 template <class Iterator> static void check(Iterator)
133 # ifndef BOOST_NO_STD_ITERATOR_TRAITS
134 typedef typename std::iterator_traits<Iterator>::reference reference;
135 typedef typename std::iterator_traits<Iterator>::value_type value_type;
137 typedef typename Iterator::reference reference;
138 typedef typename Iterator::value_type value_type;
140 BOOST_STATIC_ASSERT(boost::is_reference<reference>::value);
141 BOOST_STATIC_ASSERT((boost::is_same<reference,value_type&>::value
142 || boost::is_same<reference,const value_type&>::value
147 # ifdef BOOST_NO_STD_ITERATOR_TRAITS
148 template <> struct lvalue_test<true> {
149 template <class T> static void check(T) {}
153 template <class Iterator, class T>
154 void forward_iterator_test(Iterator i, T v1, T v2)
156 input_iterator_test(i, v1, v2);
158 Iterator i1 = i, i2 = i;
163 trivial_iterator_test(i, i1, v1);
164 trivial_iterator_test(i, i2, v1);
172 trivial_iterator_test(i, i1, v2);
173 trivial_iterator_test(i, i2, v2);
175 // borland doesn't allow non-type template parameters
176 # if !defined(__BORLANDC__) || (__BORLANDC__ > 0x551)
177 lvalue_test<(boost::is_pointer<Iterator>::value)>::check(i);
181 // Preconditions: *i == v1, *++i == v2
182 template <class Iterator, class T>
183 void bidirectional_iterator_test(Iterator i, T v1, T v2)
185 forward_iterator_test(i, v1, v2);
188 Iterator i1 = i, i2 = i;
193 trivial_iterator_test(i, i1, v2);
194 trivial_iterator_test(i, i2, v2);
202 trivial_iterator_test(i, i1, v1);
203 trivial_iterator_test(i, i2, v1);
206 // mutable_bidirectional_iterator_test
208 template <class U> struct undefined;
210 // Preconditions: [i,i+N) is a valid range
211 template <class Iterator, class TrueVals>
212 void random_access_iterator_test(Iterator i, int N, TrueVals vals)
214 bidirectional_iterator_test(i, vals[0], vals[1]);
215 const Iterator j = i;
218 typedef typename boost::detail::iterator_traits<Iterator>::value_type value_type;
220 for (c = 0; c < N-1; ++c) {
222 assert(*i == vals[c]);
223 assert(*i == boost::implicit_cast<value_type>(j[c]));
224 assert(*i == *(j + c));
225 assert(*i == *(c + j));
233 Iterator k = j + N - 1;
234 for (c = 0; c < N-1; ++c) {
236 assert(*i == vals[N - 1 - c]);
237 assert(*i == boost::implicit_cast<value_type>(j[N - 1 - c]));
248 // Precondition: i != j
249 template <class Iterator, class ConstIterator>
250 void const_nonconst_iterator_test(Iterator i, ConstIterator j)
264 } // namespace iterators
266 using iterators::undefined;
267 using iterators::trivial_iterator_test;
268 using iterators::mutable_trivial_iterator_test;
269 using iterators::input_iterator_test;
270 using iterators::lvalue_test;
271 using iterators::forward_iterator_test;
272 using iterators::bidirectional_iterator_test;
273 using iterators::random_access_iterator_test;
274 using iterators::const_nonconst_iterator_test;
278 #endif // BOOST_ITERATOR_TESTS_HPP