1 // (C) Copyright Thomas Witt 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)
6 // See http://www.boost.org for most recent version including documentation.
8 #include <boost/config.hpp>
15 #include <boost/iterator/iterator_adaptor.hpp>
16 #if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
17 # include <boost/iterator/is_readable_iterator.hpp>
18 # include <boost/iterator/is_lvalue_iterator.hpp>
20 #include <boost/pending/iterator_tests.hpp>
22 # include <boost/detail/lightweight_test.hpp>
30 #include "static_assert_same.hpp"
32 #include <boost/iterator/detail/config_def.hpp>
37 typedef int result_type
;
38 typedef int argument_type
;
39 // Functors used with transform_iterator must be
40 // DefaultConstructible, as the transform_iterator must be
41 // DefaultConstructible to satisfy the requirements for
44 mult_functor(int aa
) : a(aa
) { }
45 int operator()(int b
) const { return a
* b
; }
51 : public std::unary_function
<Pair
, typename
Pair::first_type
>
53 const typename
Pair::first_type
& operator()(const Pair
& x
) const {
56 typename
Pair::first_type
& operator()(Pair
& x
) const {
62 bool operator()(dummyT x
) const {
63 return x
.foo() == 1 || x
.foo() == 4;
67 typedef std::deque
<int> storage
;
68 typedef std::deque
<int*> pointer_deque
;
69 typedef std::set
<storage::iterator
> iterator_set
;
71 template <class T
> struct foo
;
77 typedef int result_type
;
79 int operator()() { return ++n
; }
85 : boost::iterator_adaptor
<
89 , boost::random_access_traversal_tag
90 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
96 typedef boost::iterator_adaptor
<
100 , boost::random_access_traversal_tag
101 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
108 ptr_iterator(V
* d
) : super_t(d
) { }
112 const ptr_iterator
<V2
>& x
113 , typename
boost::enable_if_convertible
<V2
*, V
*>::type
* = 0
119 // Non-functional iterator for category modification checking
120 template <class Iter
, class Traversal
>
121 struct modify_traversal
122 : boost::iterator_adaptor
<
123 modify_traversal
<Iter
, Traversal
>
132 : boost::iterator_adaptor
<
134 , boost::forward_iterator_archetype
<T
>
138 typedef boost::iterator_adaptor
<
140 , boost::forward_iterator_archetype
<T
>
145 fwd_iterator(boost::forward_iterator_archetype
<T
> d
) : super_t(d
) { }
150 : boost::iterator_adaptor
<
152 , boost::input_iterator_archetype_no_proxy
<T
>
156 typedef boost::iterator_adaptor
<
158 , boost::input_iterator_archetype_no_proxy
<T
>
163 in_iterator(boost::input_iterator_archetype_no_proxy
<T
> d
) : super_t(d
) { }
166 template <class Iter
>
167 struct constant_iterator
168 : boost::iterator_adaptor
<
169 constant_iterator
<Iter
>
171 , typename
std::iterator_traits
<Iter
>::value_type
const
174 typedef boost::iterator_adaptor
<
175 constant_iterator
<Iter
>
177 , typename
std::iterator_traits
<Iter
>::value_type
const
180 constant_iterator() {}
181 constant_iterator(Iter it
)
185 char (& traversal2(boost::incrementable_traversal_tag
) )[1];
186 char (& traversal2(boost::single_pass_traversal_tag
) )[2];
187 char (& traversal2(boost::forward_traversal_tag
) )[3];
188 char (& traversal2(boost::bidirectional_traversal_tag
) )[4];
189 char (& traversal2(boost::random_access_traversal_tag
) )[5];
194 static typename
boost::iterator_category_to_traversal
<Cat
>::type x
;
195 BOOST_STATIC_CONSTANT(std::size_t, value
= sizeof(traversal2(x
)));
196 typedef char (&type
)[value
];
200 typename traversal3
<Cat
>::type
traversal(Cat
);
202 template <class Iter
, class Trav
>
203 int static_assert_traversal(Iter
* = 0, Trav
* = 0)
205 typedef typename
boost::iterator_category_to_traversal
<
206 BOOST_DEDUCED_TYPENAME
Iter::iterator_category
209 return static_assert_same
<Trav
,t2
>::value
;
215 dummyT array
[] = { dummyT(0), dummyT(1), dummyT(2),
216 dummyT(3), dummyT(4), dummyT(5) };
217 const int N
= sizeof(array
)/sizeof(dummyT
);
219 // sanity check, if this doesn't pass the test is buggy
220 boost::random_access_iterator_test(array
, N
, array
);
222 // Test the iterator_adaptor
224 ptr_iterator
<dummyT
> i(array
);
225 boost::random_access_iterator_test(i
, N
, array
);
227 ptr_iterator
<const dummyT
> j(array
);
228 boost::random_access_iterator_test(j
, N
, array
);
229 boost::const_nonconst_iterator_test(i
, ++j
);
233 // Test the iterator_traits
235 // Test computation of defaults
236 typedef ptr_iterator
<int> Iter1
;
237 // don't use std::iterator_traits here to avoid VC++ problems
238 test
= static_assert_same
<Iter1::value_type
, int>::value
;
239 test
= static_assert_same
<Iter1::reference
, int&>::value
;
240 test
= static_assert_same
<Iter1::pointer
, int*>::value
;
241 test
= static_assert_same
<Iter1::difference_type
, std::ptrdiff_t>::value
;
242 #if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
243 BOOST_STATIC_ASSERT((boost::is_convertible
<Iter1::iterator_category
, std::random_access_iterator_tag
>::value
));
248 // Test computation of default when the Value is const
249 typedef ptr_iterator
<int const> Iter1
;
250 test
= static_assert_same
<Iter1::value_type
, int>::value
;
251 test
= static_assert_same
<Iter1::reference
, const int&>::value
;
253 #if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
254 BOOST_STATIC_ASSERT(boost::is_readable_iterator
<Iter1
>::value
);
255 # ifndef BOOST_NO_LVALUE_RETURN_DETECTION
256 BOOST_STATIC_ASSERT(boost::is_lvalue_iterator
<Iter1
>::value
);
260 #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) // borland drops constness
261 test
= static_assert_same
<Iter1::pointer
, int const*>::value
;
266 // Test constant iterator idiom
267 typedef ptr_iterator
<int> BaseIter
;
268 typedef constant_iterator
<BaseIter
> Iter
;
270 test
= static_assert_same
<Iter::value_type
, int>::value
;
271 test
= static_assert_same
<Iter::reference
, int const&>::value
;
272 #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) // borland drops constness
273 test
= static_assert_same
<Iter::pointer
, int const*>::value
;
276 #ifndef BOOST_NO_LVALUE_RETURN_DETECTION
277 BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator
<BaseIter
>::value
);
278 BOOST_STATIC_ASSERT(boost::is_lvalue_iterator
<Iter
>::value
);
281 typedef modify_traversal
<BaseIter
, boost::incrementable_traversal_tag
> IncrementableIter
;
283 static_assert_traversal
<BaseIter
,boost::random_access_traversal_tag
>();
284 static_assert_traversal
<IncrementableIter
,boost::incrementable_traversal_tag
>();
287 // Test the iterator_adaptor
289 ptr_iterator
<dummyT
> i(array
);
290 boost::random_access_iterator_test(i
, N
, array
);
292 ptr_iterator
<const dummyT
> j(array
);
293 boost::random_access_iterator_test(j
, N
, array
);
294 boost::const_nonconst_iterator_test(i
, ++j
);
297 // check operator-> with a forward iterator
299 boost::forward_iterator_archetype
<dummyT
> forward_iter
;
301 typedef fwd_iterator
<dummyT
> adaptor_type
;
303 adaptor_type
i(forward_iter
);
305 if (zero
) // don't do this, just make sure it compiles
306 BOOST_TEST((*i
).m_x
== i
->foo());
309 // check operator-> with an input iterator
311 boost::input_iterator_archetype_no_proxy
<dummyT
> input_iter
;
312 typedef in_iterator
<dummyT
> adaptor_type
;
313 adaptor_type
i(input_iter
);
315 if (zero
) // don't do this, just make sure it compiles
316 BOOST_TEST((*i
).m_x
== i
->foo());
319 // check that base_type is correct
321 // Test constant iterator idiom
322 typedef ptr_iterator
<int> BaseIter
;
324 test
= static_assert_same
<BaseIter::base_type
,int*>::value
;
325 test
= static_assert_same
<constant_iterator
<BaseIter
>::base_type
,BaseIter
>::value
;
327 typedef modify_traversal
<BaseIter
, boost::incrementable_traversal_tag
> IncrementableIter
;
329 test
= static_assert_same
<IncrementableIter::base_type
,BaseIter
>::value
;
332 std::cout
<< "test successful " << std::endl
;
334 return boost::report_errors();