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