]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ||
29 | namespace boost { | |
30 | ||
31 | // use this for the value type | |
32 | struct dummyT { | |
33 | dummyT() { } | |
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; } | |
38 | int m_x; | |
39 | }; | |
40 | ||
41 | } | |
42 | ||
43 | namespace boost { | |
44 | namespace iterators { | |
45 | ||
46 | // Tests whether type Iterator satisfies the requirements for a | |
47 | // TrivialIterator. | |
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) | |
51 | { | |
52 | Iterator k; | |
53 | assert(i == i); | |
54 | assert(j == j); | |
55 | assert(i != j); | |
56 | #ifdef BOOST_NO_STD_ITERATOR_TRAITS | |
57 | T v = *i; | |
58 | #else | |
59 | typename std::iterator_traits<Iterator>::value_type v = *i; | |
60 | #endif | |
61 | assert(v == val); | |
62 | #if 0 | |
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()); | |
68 | #endif | |
69 | k = i; | |
70 | assert(k == k); | |
71 | assert(k == i); | |
72 | assert(k != j); | |
73 | assert(*k == val); | |
74 | } | |
75 | ||
76 | ||
77 | // Preconditions: i != j | |
78 | template <class Iterator, class T> | |
79 | void mutable_trivial_iterator_test(const Iterator i, const Iterator j, T val) | |
80 | { | |
81 | *i = val; | |
82 | trivial_iterator_test(i, j, val); | |
83 | } | |
84 | ||
85 | ||
86 | // Preconditions: *i == v1, *++i == v2 | |
87 | template <class Iterator, class T> | |
88 | void input_iterator_test(Iterator i, T v1, T v2) | |
89 | { | |
90 | Iterator i1(i); | |
91 | ||
92 | assert(i == i1); | |
93 | assert(!(i != i1)); | |
94 | ||
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. | |
99 | // | |
100 | // Iterator i2; | |
101 | // | |
102 | // assert(i != i2); | |
103 | // assert(!(i == i2)); | |
104 | ||
105 | assert(*i1 == v1); | |
106 | assert(*i == v1); | |
107 | ||
108 | // we cannot test for equivalence of (void)++i & (void)i++ | |
109 | // as i is only guaranteed to be single pass. | |
110 | assert(*i++ == v1); | |
111 | ||
112 | i1 = i; | |
113 | ||
114 | assert(i == i1); | |
115 | assert(!(i != i1)); | |
116 | ||
117 | assert(*i1 == v2); | |
118 | assert(*i == v2); | |
119 | ||
120 | // i is dereferencable, so it must be incrementable. | |
121 | ++i; | |
122 | ||
123 | // how to test for operator-> ? | |
124 | } | |
125 | ||
126 | // how to test output iterator? | |
127 | ||
128 | ||
129 | template <bool is_pointer> struct lvalue_test | |
130 | { | |
131 | template <class Iterator> static void check(Iterator) | |
132 | { | |
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; | |
136 | # else | |
137 | typedef typename Iterator::reference reference; | |
138 | typedef typename Iterator::value_type value_type; | |
139 | # endif | |
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 | |
143 | )); | |
144 | } | |
145 | }; | |
146 | ||
147 | # ifdef BOOST_NO_STD_ITERATOR_TRAITS | |
148 | template <> struct lvalue_test<true> { | |
149 | template <class T> static void check(T) {} | |
150 | }; | |
151 | #endif | |
152 | ||
153 | template <class Iterator, class T> | |
154 | void forward_iterator_test(Iterator i, T v1, T v2) | |
155 | { | |
156 | input_iterator_test(i, v1, v2); | |
157 | ||
158 | Iterator i1 = i, i2 = i; | |
159 | ||
160 | assert(i == i1++); | |
161 | assert(i != ++i2); | |
162 | ||
163 | trivial_iterator_test(i, i1, v1); | |
164 | trivial_iterator_test(i, i2, v1); | |
165 | ||
166 | ++i; | |
167 | assert(i == i1); | |
168 | assert(i == i2); | |
169 | ++i1; | |
170 | ++i2; | |
171 | ||
172 | trivial_iterator_test(i, i1, v2); | |
173 | trivial_iterator_test(i, i2, v2); | |
174 | ||
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); | |
178 | #endif | |
179 | } | |
180 | ||
181 | // Preconditions: *i == v1, *++i == v2 | |
182 | template <class Iterator, class T> | |
183 | void bidirectional_iterator_test(Iterator i, T v1, T v2) | |
184 | { | |
185 | forward_iterator_test(i, v1, v2); | |
186 | ++i; | |
187 | ||
188 | Iterator i1 = i, i2 = i; | |
189 | ||
190 | assert(i == i1--); | |
191 | assert(i != --i2); | |
192 | ||
193 | trivial_iterator_test(i, i1, v2); | |
194 | trivial_iterator_test(i, i2, v2); | |
195 | ||
196 | --i; | |
197 | assert(i == i1); | |
198 | assert(i == i2); | |
199 | ++i1; | |
200 | ++i2; | |
201 | ||
202 | trivial_iterator_test(i, i1, v1); | |
203 | trivial_iterator_test(i, i2, v1); | |
204 | } | |
205 | ||
206 | // mutable_bidirectional_iterator_test | |
207 | ||
208 | template <class U> struct undefined; | |
209 | ||
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) | |
213 | { | |
214 | bidirectional_iterator_test(i, vals[0], vals[1]); | |
215 | const Iterator j = i; | |
216 | int c; | |
217 | ||
218 | typedef typename boost::detail::iterator_traits<Iterator>::value_type value_type; | |
219 | ||
220 | for (c = 0; c < N-1; ++c) { | |
221 | assert(i == j + 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)); | |
226 | ++i; | |
227 | assert(i > j); | |
228 | assert(i >= j); | |
229 | assert(j <= i); | |
230 | assert(j < i); | |
231 | } | |
232 | ||
233 | Iterator k = j + N - 1; | |
234 | for (c = 0; c < N-1; ++c) { | |
235 | assert(i == k - c); | |
236 | assert(*i == vals[N - 1 - c]); | |
237 | assert(*i == boost::implicit_cast<value_type>(j[N - 1 - c])); | |
238 | Iterator q = k - c; | |
239 | assert(*i == *q); | |
240 | assert(i > j); | |
241 | assert(i >= j); | |
242 | assert(j <= i); | |
243 | assert(j < i); | |
244 | --i; | |
245 | } | |
246 | } | |
247 | ||
248 | // Precondition: i != j | |
249 | template <class Iterator, class ConstIterator> | |
250 | void const_nonconst_iterator_test(Iterator i, ConstIterator j) | |
251 | { | |
252 | assert(i != j); | |
253 | assert(j != i); | |
254 | ||
255 | ConstIterator k(i); | |
256 | assert(k == i); | |
257 | assert(i == k); | |
258 | ||
259 | k = i; | |
260 | assert(k == i); | |
261 | assert(i == k); | |
262 | } | |
263 | ||
264 | } // namespace iterators | |
265 | ||
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; | |
275 | ||
276 | } // namespace boost | |
277 | ||
278 | #endif // BOOST_ITERATOR_TESTS_HPP |