1 // (C) Copyright David Abrahams 2001.
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)
6 // See http://www.boost.org for most recent version including documentation.
9 // 16 Feb 2001 Added a missing const. Made the tests run (somewhat) with
10 // plain MSVC again. (David Abrahams)
11 // 11 Feb 2001 #if 0'd out use of counting_iterator on non-numeric types in
12 // MSVC without STLport, so that the other tests may proceed
14 // 04 Feb 2001 Added use of iterator_tests.hpp (David Abrahams)
15 // 28 Jan 2001 Removed not_an_iterator detritus (David Abrahams)
16 // 24 Jan 2001 Initial revision (David Abrahams)
18 #include <boost/config.hpp>
20 #ifdef BOOST_BORLANDC // Borland mis-detects our custom iterators
21 # pragma warn -8091 // template argument ForwardIterator passed to '...' is a output iterator
22 # pragma warn -8071 // Conversion may lose significant digits (due to counting_iterator<char> += n).
26 # pragma warning(disable:4786) // identifier truncated in debug info
29 #include <boost/iterator/counting_iterator.hpp>
30 #include <boost/iterator/new_iterator_tests.hpp>
32 #include <boost/next_prior.hpp>
33 #include <boost/mpl/if.hpp>
34 #include <boost/detail/workaround.hpp>
35 #include <boost/limits.hpp>
41 #ifndef BOOST_BORLANDC
42 # include <boost/tuple/tuple.hpp>
46 #include <boost/core/lightweight_test.hpp>
47 #ifndef BOOST_NO_SLIST
48 # ifdef BOOST_SLIST_HEADER
49 # include BOOST_SLIST_HEADER
56 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
58 struct signed_assert_nonnegative
60 static void test(T x
) { BOOST_TEST(x
>= 0); }
64 struct unsigned_assert_nonnegative
66 static void test(T x
) {}
70 struct assert_nonnegative
72 std::numeric_limits
<T
>::is_signed
73 , signed_assert_nonnegative
<T
>
74 , unsigned_assert_nonnegative
<T
>
80 // Special tests for RandomAccess CountingIterators.
81 template <class CountingIterator
, class Value
>
83 CountingIterator start
,
84 CountingIterator finish
,
86 std::random_access_iterator_tag
)
89 std::iterator_traits
<CountingIterator
>::difference_type
91 difference_type distance
= std::distance(start
, finish
);
93 // Pick a random position internal to the range
94 difference_type offset
= (unsigned)rand() % distance
;
96 #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
97 BOOST_TEST(offset
>= 0);
99 assert_nonnegative
<difference_type
>::test(offset
);
102 CountingIterator internal
= start
;
103 std::advance(internal
, offset
);
105 // Try some binary searches on the range to show that it's ordered
106 BOOST_TEST(std::binary_search(start
, finish
, *internal
));
108 // #including tuple crashed borland, so I had to give up on tie().
109 std::pair
<CountingIterator
,CountingIterator
> xy(
110 std::equal_range(start
, finish
, *internal
));
111 CountingIterator x
= xy
.first
, y
= xy
.second
;
113 BOOST_TEST(std::distance(x
, y
) == 1);
115 // Show that values outside the range can't be found
116 BOOST_TEST(!std::binary_search(start
, boost::prior(finish
), *finish
));
118 // Do the generic random_access_iterator_test
119 typedef typename
CountingIterator::value_type value_type
;
120 std::vector
<value_type
> v
;
121 for (value_type z
= *start
; !(z
== *finish
); ++z
)
124 // Note that this test requires a that the first argument is
125 // dereferenceable /and/ a valid iterator prior to the first argument
126 boost::random_access_iterator_test(start
, v
.size(), v
.begin());
129 // Special tests for bidirectional CountingIterators
130 template <class CountingIterator
, class Value
>
131 void category_test(CountingIterator start
, Value v1
, std::bidirectional_iterator_tag
)
136 // Note that this test requires a that the first argument is
137 // dereferenceable /and/ a valid iterator prior to the first argument
138 boost::bidirectional_iterator_test(start
, v1
, v2
);
141 template <class CountingIterator
, class Value
>
142 void category_test(CountingIterator start
, CountingIterator finish
, Value v1
, std::forward_iterator_tag
)
146 if (finish
!= start
&& finish
!= boost::next(start
))
147 boost::forward_readable_iterator_test(start
, finish
, v1
, v2
);
150 template <class CountingIterator
, class Value
>
151 void test_aux(CountingIterator start
, CountingIterator finish
, Value v1
)
153 typedef typename
CountingIterator::iterator_category category
;
155 // If it's a RandomAccessIterator we can do a few delicate tests
156 category_test(start
, finish
, v1
, category());
158 // Okay, brute force...
159 for (CountingIterator p
= start
160 ; p
!= finish
&& boost::next(p
) != finish
163 BOOST_TEST(boost::next(*p
) == *boost::next(p
));
166 // prove that a reference can be formed to these values
167 typedef typename
CountingIterator::value_type value
;
168 const value
* q
= &*start
;
169 (void)q
; // suppress unused variable warning
172 template <class Incrementable
>
173 void test(Incrementable start
, Incrementable finish
)
175 test_aux(boost::make_counting_iterator(start
), boost::make_counting_iterator(finish
), start
);
178 template <class Integer
>
179 void test_integer(Integer
* = 0) // default arg works around MSVC bug
182 Integer finish
= 120;
186 template <class Integer
, class Category
, class Difference
>
187 void test_integer3(Integer
* = 0, Category
* = 0, Difference
* = 0) // default arg works around MSVC bug
190 Integer finish
= 120;
191 typedef boost::counting_iterator
<Integer
,Category
,Difference
> iterator
;
192 test_aux(iterator(start
), iterator(finish
), start
);
195 template <class Container
>
196 void test_container(Container
* = 0) // default arg works around MSVC bug
198 Container
c(1 + (unsigned)rand() % 1673);
200 const typename
Container::iterator start
= c
.begin();
202 // back off by 1 to leave room for dereferenceable value at the end
203 typename
Container::iterator finish
= start
;
204 std::advance(finish
, c
.size() - 1);
208 typedef typename
Container::const_iterator const_iterator
;
209 test(const_iterator(start
), const_iterator(finish
));
215 my_int1(int x
) : m_int(x
) { }
216 my_int1
& operator++() { ++m_int
; return *this; }
217 bool operator==(const my_int1
& x
) const { return m_int
== x
.m_int
; }
224 typedef void value_type
;
225 typedef void pointer
;
226 typedef void reference
;
227 typedef std::ptrdiff_t difference_type
;
228 typedef std::bidirectional_iterator_tag iterator_category
;
231 my_int2(int x
) : m_int(x
) { }
232 my_int2
& operator++() { ++m_int
; return *this; }
233 my_int2
& operator--() { --m_int
; return *this; }
234 bool operator==(const my_int2
& x
) const { return m_int
== x
.m_int
; }
241 typedef void value_type
;
242 typedef void pointer
;
243 typedef void reference
;
244 typedef std::ptrdiff_t difference_type
;
245 typedef std::random_access_iterator_tag iterator_category
;
248 my_int3(int x
) : m_int(x
) { }
249 my_int3
& operator++() { ++m_int
; return *this; }
250 my_int3
& operator+=(std::ptrdiff_t n
) { m_int
+= n
; return *this; }
251 std::ptrdiff_t operator-(const my_int3
& x
) const { return m_int
- x
.m_int
; }
252 my_int3
& operator--() { --m_int
; return *this; }
253 bool operator==(const my_int3
& x
) const { return m_int
== x
.m_int
; }
254 bool operator!=(const my_int3
& x
) const { return m_int
!= x
.m_int
; }
255 bool operator<(const my_int3
& x
) const { return m_int
< x
.m_int
; }
262 // Test the built-in integer types.
263 test_integer
<char>();
264 test_integer
<unsigned char>();
265 test_integer
<signed char>();
266 test_integer
<wchar_t>();
267 test_integer
<short>();
268 test_integer
<unsigned short>();
270 test_integer
<unsigned int>();
271 test_integer
<long>();
272 test_integer
<unsigned long>();
273 #if defined(BOOST_HAS_LONG_LONG)
274 test_integer
< ::boost::long_long_type
>();
275 test_integer
< ::boost::ulong_long_type
>();
278 // Test user-defined type.
280 test_integer3
<my_int1
, std::forward_iterator_tag
, int>();
281 test_integer3
<long, std::random_access_iterator_tag
, int>();
282 test_integer
<my_int2
>();
283 test_integer
<my_int3
>();
285 // Some tests on container iterators, to prove we handle a few different categories
286 test_container
<std::vector
<int> >();
287 test_container
<std::list
<int> >();
288 # ifndef BOOST_NO_SLIST
289 test_container
<BOOST_STD_EXTENSION_NAMESPACE::slist
<int> >();
292 // Also prove that we can handle raw pointers.
294 test(boost::make_counting_iterator(array
), boost::make_counting_iterator(array
+2000-1));
296 return boost::report_errors();