1 | // (C) Copyright Jeremy Siek 2002. |
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 | #ifndef BOOST_ITERATOR_ARCHETYPES_HPP |
7 | #define BOOST_ITERATOR_ARCHETYPES_HPP |
8 | |
9 | #include <boost/iterator/iterator_categories.hpp> |
10 | #include <boost/operators.hpp> |
11 | #include <boost/static_assert.hpp> |
12 | #include <boost/iterator.hpp> |
13 | |
14 | #include <boost/iterator/detail/facade_iterator_category.hpp> |
15 | |
16 | #include <boost/type_traits/is_const.hpp> |
17 | #include <boost/type_traits/add_const.hpp> |
18 | #include <boost/type_traits/remove_const.hpp> |
19 | #include <boost/type_traits/remove_cv.hpp> |
20 | |
21 | #include <boost/concept_archetype.hpp> |
22 | |
23 | #include <boost/mpl/bitand.hpp> |
24 | #include <boost/mpl/int.hpp> |
25 | #include <boost/mpl/equal_to.hpp> |
26 | #include <boost/mpl/if.hpp> |
27 | #include <boost/mpl/eval_if.hpp> |
28 | #include <boost/mpl/and.hpp> |
29 | #include <boost/mpl/identity.hpp> |
30 | |
31 | #include <cstddef> |
32 | |
33 | namespace boost { |
34 | namespace iterators { |
35 | |
36 | template <class Value, class AccessCategory> |
37 | struct access_archetype; |
38 | |
39 | template <class Derived, class Value, class AccessCategory, class TraversalCategory> |
40 | struct traversal_archetype; |
41 | |
42 | namespace archetypes |
43 | { |
44 | enum { |
45 | readable_iterator_bit = 1 |
46 | , writable_iterator_bit = 2 |
47 | , swappable_iterator_bit = 4 |
48 | , lvalue_iterator_bit = 8 |
49 | }; |
50 | |
51 | // Not quite tags, since dispatching wouldn't work. |
52 | typedef mpl::int_<readable_iterator_bit>::type readable_iterator_t; |
53 | typedef mpl::int_<writable_iterator_bit>::type writable_iterator_t; |
54 | |
55 | typedef mpl::int_< |
56 | (readable_iterator_bit|writable_iterator_bit) |
57 | >::type readable_writable_iterator_t; |
58 | |
59 | typedef mpl::int_< |
60 | (readable_iterator_bit|lvalue_iterator_bit) |
61 | >::type readable_lvalue_iterator_t; |
62 | |
63 | typedef mpl::int_< |
64 | (lvalue_iterator_bit|writable_iterator_bit) |
65 | >::type writable_lvalue_iterator_t; |
66 | |
67 | typedef mpl::int_<swappable_iterator_bit>::type swappable_iterator_t; |
68 | typedef mpl::int_<lvalue_iterator_bit>::type lvalue_iterator_t; |
69 | |
70 | template <class Derived, class Base> |
71 | struct has_access |
72 | : mpl::equal_to< |
73 | mpl::bitand_<Derived,Base> |
74 | , Base |
75 | > |
76 | {}; |
77 | } |
78 | |
79 | namespace detail |
80 | { |
81 | template <class T> |
82 | struct assign_proxy |
83 | { |
84 | assign_proxy& operator=(T) { return *this; } |
85 | }; |
86 | |
87 | template <class T> |
88 | struct read_proxy |
89 | { |
90 | operator T() { return static_object<T>::get(); } |
91 | }; |
92 | |
93 | template <class T> |
94 | struct read_write_proxy |
95 | : read_proxy<T> // Use to inherit from assign_proxy, but that doesn't work. -JGS |
96 | { |
97 | read_write_proxy& operator=(T) { return *this; } |
98 | }; |
99 | |
100 | template <class T> |
101 | struct arrow_proxy |
102 | { |
103 | T const* operator->() const { return 0; } |
104 | }; |
105 | |
106 | struct no_operator_brackets {}; |
107 | |
108 | template <class ValueType> |
109 | struct readable_operator_brackets |
110 | { |
111 | read_proxy<ValueType> operator[](std::ptrdiff_t n) const { return read_proxy<ValueType>(); } |
112 | }; |
113 | |
114 | template <class ValueType> |
115 | struct writable_operator_brackets |
116 | { |
117 | read_write_proxy<ValueType> operator[](std::ptrdiff_t n) const { return read_write_proxy<ValueType>(); } |
118 | }; |
119 | |
120 | template <class Value, class AccessCategory, class TraversalCategory> |
121 | struct operator_brackets |
122 | : mpl::eval_if< |
123 | is_convertible<TraversalCategory, random_access_traversal_tag> |
124 | , mpl::eval_if< |
125 | archetypes::has_access< |
126 | AccessCategory |
127 | , archetypes::writable_iterator_t |
128 | > |
129 | , mpl::identity<writable_operator_brackets<Value> > |
130 | , mpl::if_< |
131 | archetypes::has_access< |
132 | AccessCategory |
133 | , archetypes::readable_iterator_t |
134 | > |
135 | , readable_operator_brackets<Value> |
136 | , no_operator_brackets |
137 | > |
138 | > |
139 | , mpl::identity<no_operator_brackets> |
140 | >::type |
141 | {}; |
142 | |
143 | template <class TraversalCategory> |
144 | struct traversal_archetype_impl |
145 | { |
146 | template <class Derived,class Value> struct archetype; |
147 | }; |
148 | |
149 | // Constructor argument for those iterators that |
150 | // are not default constructible |
151 | struct ctor_arg {}; |
152 | |
153 | template <class Derived, class Value, class TraversalCategory> |
154 | struct traversal_archetype_ |
155 | : traversal_archetype_impl<TraversalCategory>::template archetype<Derived,Value> |
156 | { |
157 | typedef typename |
158 | traversal_archetype_impl<TraversalCategory>::template archetype<Derived,Value> |
159 | base; |
160 | |
161 | traversal_archetype_() {} |
162 | |
163 | traversal_archetype_(ctor_arg arg) |
164 | : base(arg) |
165 | {} |
166 | }; |
167 | |
168 | template <> |
169 | struct traversal_archetype_impl<incrementable_traversal_tag> |
170 | { |
171 | template<class Derived, class Value> |
172 | struct archetype |
173 | { |
174 | explicit archetype(ctor_arg) {} |
175 | |
176 | struct bogus { }; // This use to be void, but that causes trouble for iterator_facade. Need more research. -JGS |
177 | typedef bogus difference_type; |
178 | |
179 | Derived& operator++() { return (Derived&)static_object<Derived>::get(); } |
180 | Derived operator++(int) const { return (Derived&)static_object<Derived>::get(); } |
181 | }; |
182 | }; |
183 | |
184 | template <> |
185 | struct traversal_archetype_impl<single_pass_traversal_tag> |
186 | { |
187 | template<class Derived, class Value> |
188 | struct archetype |
189 | : public equality_comparable< traversal_archetype_<Derived, Value, single_pass_traversal_tag> >, |
190 | public traversal_archetype_<Derived, Value, incrementable_traversal_tag> |
191 | { |
192 | explicit archetype(ctor_arg arg) |
193 | : traversal_archetype_<Derived, Value, incrementable_traversal_tag>(arg) |
194 | {} |
195 | |
196 | typedef std::ptrdiff_t difference_type; |
197 | }; |
198 | }; |
199 | |
200 | template <class Derived, class Value> |
201 | bool operator==(traversal_archetype_<Derived, Value, single_pass_traversal_tag> const&, |
202 | traversal_archetype_<Derived, Value, single_pass_traversal_tag> const&) { return true; } |
203 | |
204 | template <> |
205 | struct traversal_archetype_impl<forward_traversal_tag> |
206 | { |
207 | template<class Derived, class Value> |
208 | struct archetype |
209 | : public traversal_archetype_<Derived, Value, single_pass_traversal_tag> |
210 | { |
211 | archetype() |
212 | : traversal_archetype_<Derived, Value, single_pass_traversal_tag>(ctor_arg()) |
213 | {} |
214 | }; |
215 | }; |
216 | |
217 | template <> |
218 | struct traversal_archetype_impl<bidirectional_traversal_tag> |
219 | { |
220 | template<class Derived, class Value> |
221 | struct archetype |
222 | : public traversal_archetype_<Derived, Value, forward_traversal_tag> |
223 | { |
224 | Derived& operator--() { return static_object<Derived>::get(); } |
225 | Derived operator--(int) const { return static_object<Derived>::get(); } |
226 | }; |
227 | }; |
228 | |
229 | template <> |
230 | struct traversal_archetype_impl<random_access_traversal_tag> |
231 | { |
232 | template<class Derived, class Value> |
233 | struct archetype |
234 | : public traversal_archetype_<Derived, Value, bidirectional_traversal_tag> |
235 | { |
236 | Derived& operator+=(std::ptrdiff_t) { return static_object<Derived>::get(); } |
237 | Derived& operator-=(std::ptrdiff_t) { return static_object<Derived>::get(); } |
238 | }; |
239 | }; |
240 | |
241 | template <class Derived, class Value> |
242 | Derived& operator+(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&, |
243 | std::ptrdiff_t) { return static_object<Derived>::get(); } |
244 | |
245 | template <class Derived, class Value> |
246 | Derived& operator+(std::ptrdiff_t, |
247 | traversal_archetype_<Derived, Value, random_access_traversal_tag> const&) |
248 | { return static_object<Derived>::get(); } |
249 | |
250 | template <class Derived, class Value> |
251 | Derived& operator-(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&, |
252 | std::ptrdiff_t) |
253 | { return static_object<Derived>::get(); } |
254 | |
255 | template <class Derived, class Value> |
256 | std::ptrdiff_t operator-(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&, |
257 | traversal_archetype_<Derived, Value, random_access_traversal_tag> const&) |
258 | { return 0; } |
259 | |
260 | template <class Derived, class Value> |
261 | bool operator<(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&, |
262 | traversal_archetype_<Derived, Value, random_access_traversal_tag> const&) |
263 | { return true; } |
264 | |
265 | template <class Derived, class Value> |
266 | bool operator>(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&, |
267 | traversal_archetype_<Derived, Value, random_access_traversal_tag> const&) |
268 | { return true; } |
269 | |
270 | template <class Derived, class Value> |
271 | bool operator<=(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&, |
272 | traversal_archetype_<Derived, Value, random_access_traversal_tag> const&) |
273 | { return true; } |
274 | |
275 | template <class Derived, class Value> |
276 | bool operator>=(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&, |
277 | traversal_archetype_<Derived, Value, random_access_traversal_tag> const&) |
278 | { return true; } |
279 | |
280 | struct bogus_type; |
281 | |
282 | template <class Value> |
283 | struct convertible_type |
284 | : mpl::if_< is_const<Value>, |
285 | typename remove_const<Value>::type, |
286 | bogus_type > |
287 | {}; |
288 | |
289 | } // namespace detail |
290 | |
291 | |
292 | template <class> struct undefined; |
293 | |
294 | template <class AccessCategory> |
295 | struct iterator_access_archetype_impl |
296 | { |
297 | template <class Value> struct archetype; |
298 | }; |
299 | |
300 | template <class Value, class AccessCategory> |
301 | struct iterator_access_archetype |
302 | : iterator_access_archetype_impl< |
303 | AccessCategory |
304 | >::template archetype<Value> |
305 | { |
306 | }; |
307 | |
308 | template <> |
309 | struct iterator_access_archetype_impl< |
310 | archetypes::readable_iterator_t |
311 | > |
312 | { |
313 | template <class Value> |
314 | struct archetype |
315 | { |
316 | typedef typename remove_cv<Value>::type value_type; |
317 | typedef Value reference; |
318 | typedef Value* pointer; |
319 | |
320 | value_type operator*() const { return static_object<value_type>::get(); } |
321 | |
322 | detail::arrow_proxy<Value> operator->() const { return detail::arrow_proxy<Value>(); } |
323 | }; |
324 | }; |
325 | |
326 | template <> |
327 | struct iterator_access_archetype_impl< |
328 | archetypes::writable_iterator_t |
329 | > |
330 | { |
331 | template <class Value> |
332 | struct archetype |
333 | { |
334 | BOOST_STATIC_ASSERT(!is_const<Value>::value); |
335 | typedef void value_type; |
336 | typedef void reference; |
337 | typedef void pointer; |
338 | |
339 | detail::assign_proxy<Value> operator*() const { return detail::assign_proxy<Value>(); } |
340 | }; |
341 | }; |
342 | |
343 | template <> |
344 | struct iterator_access_archetype_impl< |
345 | archetypes::readable_writable_iterator_t |
346 | > |
347 | { |
348 | template <class Value> |
349 | struct archetype |
350 | : public virtual iterator_access_archetype< |
351 | Value, archetypes::readable_iterator_t |
352 | > |
353 | { |
354 | typedef detail::read_write_proxy<Value> reference; |
355 | |
356 | detail::read_write_proxy<Value> operator*() const { return detail::read_write_proxy<Value>(); } |
357 | }; |
358 | }; |
359 | |
360 | template <> |
361 | struct iterator_access_archetype_impl<archetypes::readable_lvalue_iterator_t> |
362 | { |
363 | template <class Value> |
364 | struct archetype |
365 | : public virtual iterator_access_archetype< |
366 | Value, archetypes::readable_iterator_t |
367 | > |
368 | { |
369 | typedef Value& reference; |
370 | |
371 | Value& operator*() const { return static_object<Value>::get(); } |
372 | Value* operator->() const { return 0; } |
373 | }; |
374 | }; |
375 | |
376 | template <> |
377 | struct iterator_access_archetype_impl<archetypes::writable_lvalue_iterator_t> |
378 | { |
379 | template <class Value> |
380 | struct archetype |
381 | : public virtual iterator_access_archetype< |
382 | Value, archetypes::readable_lvalue_iterator_t |
383 | > |
384 | { |
385 | BOOST_STATIC_ASSERT((!is_const<Value>::value)); |
386 | }; |
387 | }; |
388 | |
389 | |
390 | template <class Value, class AccessCategory, class TraversalCategory> |
391 | struct iterator_archetype; |
392 | |
393 | template <class Value, class AccessCategory, class TraversalCategory> |
394 | struct traversal_archetype_base |
395 | : detail::operator_brackets< |
396 | typename remove_cv<Value>::type |
397 | , AccessCategory |
398 | , TraversalCategory |
399 | > |
400 | , detail::traversal_archetype_< |
401 | iterator_archetype<Value, AccessCategory, TraversalCategory> |
402 | , Value |
403 | , TraversalCategory |
404 | > |
405 | { |
406 | }; |
407 | |
408 | namespace detail |
409 | { |
410 | template <class Value, class AccessCategory, class TraversalCategory> |
411 | struct iterator_archetype_base |
412 | : iterator_access_archetype<Value, AccessCategory> |
413 | , traversal_archetype_base<Value, AccessCategory, TraversalCategory> |
414 | { |
415 | typedef iterator_access_archetype<Value, AccessCategory> access; |
416 | |
417 | typedef typename detail::facade_iterator_category< |
418 | TraversalCategory |
419 | , typename mpl::eval_if< |
420 | archetypes::has_access< |
421 | AccessCategory, archetypes::writable_iterator_t |
422 | > |
423 | , remove_const<Value> |
424 | , add_const<Value> |
425 | >::type |
426 | , typename access::reference |
427 | >::type iterator_category; |
428 | |
429 | // Needed for some broken libraries (see below) |
430 | typedef boost::iterator< |
431 | iterator_category |
432 | , Value |
433 | , typename traversal_archetype_base< |
434 | Value, AccessCategory, TraversalCategory |
435 | >::difference_type |
436 | , typename access::pointer |
437 | , typename access::reference |
438 | > workaround_iterator_base; |
439 | }; |
440 | } |
441 | |
442 | template <class Value, class AccessCategory, class TraversalCategory> |
443 | struct iterator_archetype |
444 | : public detail::iterator_archetype_base<Value, AccessCategory, TraversalCategory> |
445 | |
446 | // These broken libraries require derivation from std::iterator |
447 | // (or related magic) in order to handle iter_swap and other |
448 | // iterator operations |
449 | # if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, < 310) \ |
450 | || BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(0x20101)) |
451 | , public detail::iterator_archetype_base< |
452 | Value, AccessCategory, TraversalCategory |
453 | >::workaround_iterator_base |
454 | # endif |
455 | { |
456 | // Derivation from std::iterator above caused references to nested |
457 | // types to be ambiguous, so now we have to redeclare them all |
458 | // here. |
459 | # if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, < 310) \ |
460 | || BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(0x20101)) |
461 | |
462 | typedef detail::iterator_archetype_base< |
463 | Value,AccessCategory,TraversalCategory |
464 | > base; |
465 | |
466 | typedef typename base::value_type value_type; |
467 | typedef typename base::reference reference; |
468 | typedef typename base::pointer pointer; |
469 | typedef typename base::difference_type difference_type; |
470 | typedef typename base::iterator_category iterator_category; |
471 | # endif |
472 | |
473 | iterator_archetype() { } |
474 | iterator_archetype(iterator_archetype const& x) |
475 | : detail::iterator_archetype_base< |
476 | Value |
477 | , AccessCategory |
478 | , TraversalCategory |
479 | >(x) |
480 | {} |
481 | |
482 | iterator_archetype& operator=(iterator_archetype const&) |
483 | { return *this; } |
484 | |
485 | # if 0 |
486 | // Optional conversion from mutable |
487 | iterator_archetype( |
488 | iterator_archetype< |
489 | typename detail::convertible_type<Value>::type |
490 | , AccessCategory |
491 | , TraversalCategory> const& |
492 | ); |
493 | # endif |
494 | }; |
495 | |
496 | } // namespace iterators |
497 | |
498 | // Backward compatibility names |
499 | namespace iterator_archetypes = iterators::archetypes; |
500 | using iterators::access_archetype; |
501 | using iterators::traversal_archetype; |
502 | using iterators::iterator_archetype; |
503 | using iterators::undefined; |
504 | using iterators::iterator_access_archetype_impl; |
505 | using iterators::traversal_archetype_base; |
506 | |
507 | } // namespace boost |
508 | |
509 | #endif // BOOST_ITERATOR_ARCHETYPES_HPP |
510 | |