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