source: NonGTP/Boost/boost/pending/iterator_tests.hpp @ 857

Revision 857, 6.7 KB checked in by igarcia, 18 years ago (diff)
Line 
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
30namespace boost {
31
32  // use this for the value type
33struct 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
44BOOST_TT_BROKEN_COMPILER_SPEC(boost::dummyT)
45   
46namespace boost {
47
48// Tests whether type Iterator satisfies the requirements for a
49// TrivialIterator.
50// Preconditions: i != j, *i == val
51template <class Iterator, class T>
52void 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
80template <class Iterator, class T>
81void 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
89template <class Iterator, class T>
90void 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
131template <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
150template <> struct lvalue_test<true> {
151    template <class T> static void check(T) {}
152};
153#endif
154
155template <class Iterator, class T>
156void 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
184template <class Iterator, class T>
185void 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
210template <class U> struct undefined;
211
212// Preconditions: [i,i+N) is a valid range
213template <class Iterator, class TrueVals>
214void 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
251template <class Iterator, class ConstIterator>
252void 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
Note: See TracBrowser for help on using the repository browser.