]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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) | |
5 | ||
6 | // See http://www.boost.org for most recent version including documentation. | |
7 | ||
8 | #include <boost/config.hpp> | |
9 | #include <iostream> | |
10 | ||
11 | #include <algorithm> | |
12 | #include <functional> | |
13 | #include <numeric> | |
14 | ||
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> | |
19 | #endif | |
20 | #include <boost/pending/iterator_tests.hpp> | |
21 | ||
22 | # include <boost/detail/lightweight_test.hpp> | |
23 | ||
24 | #include <stdlib.h> | |
25 | #include <vector> | |
26 | #include <deque> | |
27 | #include <set> | |
28 | #include <list> | |
29 | ||
30 | #include "static_assert_same.hpp" | |
31 | ||
32 | #include <boost/iterator/detail/config_def.hpp> | |
33 | ||
34 | using boost::dummyT; | |
35 | ||
7c673cae FG |
36 | typedef std::deque<int> storage; |
37 | typedef std::deque<int*> pointer_deque; | |
38 | typedef std::set<storage::iterator> iterator_set; | |
39 | ||
40 | template <class T> struct foo; | |
41 | ||
42 | void blah(int) { } | |
43 | ||
44 | struct my_gen | |
45 | { | |
46 | typedef int result_type; | |
47 | my_gen() : n(0) { } | |
48 | int operator()() { return ++n; } | |
49 | int n; | |
50 | }; | |
51 | ||
52 | template <class V> | |
53 | struct ptr_iterator | |
54 | : boost::iterator_adaptor< | |
55 | ptr_iterator<V> | |
56 | , V* | |
57 | , V | |
58 | , boost::random_access_traversal_tag | |
59 | #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) | |
60 | , V& | |
61 | #endif | |
62 | > | |
63 | { | |
64 | private: | |
65 | typedef boost::iterator_adaptor< | |
66 | ptr_iterator<V> | |
67 | , V* | |
68 | , V | |
69 | , boost::random_access_traversal_tag | |
70 | #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) | |
71 | , V& | |
72 | #endif | |
73 | > super_t; | |
74 | ||
75 | public: | |
76 | ptr_iterator() { } | |
77 | ptr_iterator(V* d) : super_t(d) { } | |
78 | ||
79 | template <class V2> | |
80 | ptr_iterator( | |
81 | const ptr_iterator<V2>& x | |
82 | , typename boost::enable_if_convertible<V2*, V*>::type* = 0 | |
83 | ) | |
84 | : super_t(x.base()) | |
85 | {} | |
86 | }; | |
87 | ||
88 | // Non-functional iterator for category modification checking | |
89 | template <class Iter, class Traversal> | |
90 | struct modify_traversal | |
91 | : boost::iterator_adaptor< | |
92 | modify_traversal<Iter, Traversal> | |
93 | , Iter | |
94 | , boost::use_default | |
95 | , Traversal | |
96 | > | |
97 | {}; | |
98 | ||
99 | template <class T> | |
100 | struct fwd_iterator | |
101 | : boost::iterator_adaptor< | |
102 | fwd_iterator<T> | |
103 | , boost::forward_iterator_archetype<T> | |
104 | > | |
105 | { | |
106 | private: | |
107 | typedef boost::iterator_adaptor< | |
108 | fwd_iterator<T> | |
109 | , boost::forward_iterator_archetype<T> | |
110 | > super_t; | |
111 | ||
112 | public: | |
113 | fwd_iterator() { } | |
114 | fwd_iterator(boost::forward_iterator_archetype<T> d) : super_t(d) { } | |
115 | }; | |
116 | ||
117 | template <class T> | |
118 | struct in_iterator | |
119 | : boost::iterator_adaptor< | |
120 | in_iterator<T> | |
121 | , boost::input_iterator_archetype_no_proxy<T> | |
122 | > | |
123 | { | |
124 | private: | |
125 | typedef boost::iterator_adaptor< | |
126 | in_iterator<T> | |
127 | , boost::input_iterator_archetype_no_proxy<T> | |
128 | > super_t; | |
129 | ||
130 | public: | |
131 | in_iterator() { } | |
132 | in_iterator(boost::input_iterator_archetype_no_proxy<T> d) : super_t(d) { } | |
133 | }; | |
134 | ||
135 | template <class Iter> | |
136 | struct constant_iterator | |
137 | : boost::iterator_adaptor< | |
138 | constant_iterator<Iter> | |
139 | , Iter | |
140 | , typename std::iterator_traits<Iter>::value_type const | |
141 | > | |
142 | { | |
143 | typedef boost::iterator_adaptor< | |
144 | constant_iterator<Iter> | |
145 | , Iter | |
146 | , typename std::iterator_traits<Iter>::value_type const | |
147 | > base_t; | |
148 | ||
149 | constant_iterator() {} | |
150 | constant_iterator(Iter it) | |
151 | : base_t(it) {} | |
152 | }; | |
153 | ||
154 | char (& traversal2(boost::incrementable_traversal_tag) )[1]; | |
155 | char (& traversal2(boost::single_pass_traversal_tag ) )[2]; | |
156 | char (& traversal2(boost::forward_traversal_tag ) )[3]; | |
157 | char (& traversal2(boost::bidirectional_traversal_tag) )[4]; | |
158 | char (& traversal2(boost::random_access_traversal_tag) )[5]; | |
159 | ||
160 | template <class Cat> | |
161 | struct traversal3 | |
162 | { | |
163 | static typename boost::iterator_category_to_traversal<Cat>::type x; | |
164 | BOOST_STATIC_CONSTANT(std::size_t, value = sizeof(traversal2(x))); | |
165 | typedef char (&type)[value]; | |
166 | }; | |
167 | ||
168 | template <class Cat> | |
169 | typename traversal3<Cat>::type traversal(Cat); | |
170 | ||
171 | template <class Iter, class Trav> | |
172 | int static_assert_traversal(Iter* = 0, Trav* = 0) | |
173 | { | |
174 | typedef typename boost::iterator_category_to_traversal< | |
175 | BOOST_DEDUCED_TYPENAME Iter::iterator_category | |
176 | >::type t2; | |
177 | ||
178 | return static_assert_same<Trav,t2>::value; | |
179 | } | |
180 | ||
181 | int | |
182 | main() | |
183 | { | |
184 | dummyT array[] = { dummyT(0), dummyT(1), dummyT(2), | |
185 | dummyT(3), dummyT(4), dummyT(5) }; | |
186 | const int N = sizeof(array)/sizeof(dummyT); | |
187 | ||
188 | // sanity check, if this doesn't pass the test is buggy | |
189 | boost::random_access_iterator_test(array, N, array); | |
190 | ||
191 | // Test the iterator_adaptor | |
192 | { | |
193 | ptr_iterator<dummyT> i(array); | |
194 | boost::random_access_iterator_test(i, N, array); | |
195 | ||
196 | ptr_iterator<const dummyT> j(array); | |
197 | boost::random_access_iterator_test(j, N, array); | |
198 | boost::const_nonconst_iterator_test(i, ++j); | |
199 | } | |
200 | ||
201 | int test; | |
202 | // Test the iterator_traits | |
203 | { | |
204 | // Test computation of defaults | |
205 | typedef ptr_iterator<int> Iter1; | |
206 | // don't use std::iterator_traits here to avoid VC++ problems | |
207 | test = static_assert_same<Iter1::value_type, int>::value; | |
208 | test = static_assert_same<Iter1::reference, int&>::value; | |
209 | test = static_assert_same<Iter1::pointer, int*>::value; | |
210 | test = static_assert_same<Iter1::difference_type, std::ptrdiff_t>::value; | |
211 | #if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407) | |
212 | BOOST_STATIC_ASSERT((boost::is_convertible<Iter1::iterator_category, std::random_access_iterator_tag>::value)); | |
213 | #endif | |
214 | } | |
215 | ||
216 | { | |
217 | // Test computation of default when the Value is const | |
218 | typedef ptr_iterator<int const> Iter1; | |
219 | test = static_assert_same<Iter1::value_type, int>::value; | |
220 | test = static_assert_same<Iter1::reference, const int&>::value; | |
221 | ||
222 | #if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407) | |
223 | BOOST_STATIC_ASSERT(boost::is_readable_iterator<Iter1>::value); | |
224 | # ifndef BOOST_NO_LVALUE_RETURN_DETECTION | |
225 | BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<Iter1>::value); | |
226 | # endif | |
227 | #endif | |
228 | ||
229 | #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) // borland drops constness | |
230 | test = static_assert_same<Iter1::pointer, int const*>::value; | |
231 | #endif | |
232 | } | |
233 | ||
234 | { | |
235 | // Test constant iterator idiom | |
236 | typedef ptr_iterator<int> BaseIter; | |
237 | typedef constant_iterator<BaseIter> Iter; | |
238 | ||
239 | test = static_assert_same<Iter::value_type, int>::value; | |
240 | test = static_assert_same<Iter::reference, int const&>::value; | |
241 | #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) // borland drops constness | |
242 | test = static_assert_same<Iter::pointer, int const*>::value; | |
243 | #endif | |
244 | ||
245 | #ifndef BOOST_NO_LVALUE_RETURN_DETECTION | |
246 | BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator<BaseIter>::value); | |
247 | BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<Iter>::value); | |
248 | #endif | |
249 | ||
250 | typedef modify_traversal<BaseIter, boost::incrementable_traversal_tag> IncrementableIter; | |
251 | ||
252 | static_assert_traversal<BaseIter,boost::random_access_traversal_tag>(); | |
253 | static_assert_traversal<IncrementableIter,boost::incrementable_traversal_tag>(); | |
254 | } | |
255 | ||
256 | // Test the iterator_adaptor | |
257 | { | |
258 | ptr_iterator<dummyT> i(array); | |
259 | boost::random_access_iterator_test(i, N, array); | |
260 | ||
261 | ptr_iterator<const dummyT> j(array); | |
262 | boost::random_access_iterator_test(j, N, array); | |
263 | boost::const_nonconst_iterator_test(i, ++j); | |
264 | } | |
265 | ||
266 | // check operator-> with a forward iterator | |
267 | { | |
268 | boost::forward_iterator_archetype<dummyT> forward_iter; | |
269 | ||
270 | typedef fwd_iterator<dummyT> adaptor_type; | |
271 | ||
272 | adaptor_type i(forward_iter); | |
273 | int zero = 0; | |
274 | if (zero) // don't do this, just make sure it compiles | |
275 | BOOST_TEST((*i).m_x == i->foo()); | |
276 | } | |
277 | ||
278 | // check operator-> with an input iterator | |
279 | { | |
280 | boost::input_iterator_archetype_no_proxy<dummyT> input_iter; | |
281 | typedef in_iterator<dummyT> adaptor_type; | |
282 | adaptor_type i(input_iter); | |
283 | int zero = 0; | |
284 | if (zero) // don't do this, just make sure it compiles | |
285 | BOOST_TEST((*i).m_x == i->foo()); | |
286 | } | |
287 | ||
288 | // check that base_type is correct | |
289 | { | |
290 | // Test constant iterator idiom | |
291 | typedef ptr_iterator<int> BaseIter; | |
292 | ||
293 | test = static_assert_same<BaseIter::base_type,int*>::value; | |
294 | test = static_assert_same<constant_iterator<BaseIter>::base_type,BaseIter>::value; | |
295 | ||
296 | typedef modify_traversal<BaseIter, boost::incrementable_traversal_tag> IncrementableIter; | |
297 | ||
298 | test = static_assert_same<IncrementableIter::base_type,BaseIter>::value; | |
299 | } | |
300 | ||
301 | std::cout << "test successful " << std::endl; | |
302 | (void)test; | |
303 | return boost::report_errors(); | |
304 | } |