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