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/aux_/msvc_eti_base.hpp>
|
---|
24 | #include <boost/mpl/bitand.hpp>
|
---|
25 | #include <boost/mpl/int.hpp>
|
---|
26 | #include <boost/mpl/equal_to.hpp>
|
---|
27 | #include <boost/mpl/if.hpp>
|
---|
28 | #include <boost/mpl/eval_if.hpp>
|
---|
29 | #include <boost/mpl/and.hpp>
|
---|
30 | #include <boost/mpl/identity.hpp>
|
---|
31 |
|
---|
32 | #include <cstddef>
|
---|
33 |
|
---|
34 | namespace boost {
|
---|
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 iterator_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::aux::msvc_eti_base<
|
---|
123 | typename mpl::eval_if<
|
---|
124 | is_convertible<TraversalCategory, random_access_traversal_tag>
|
---|
125 | , mpl::eval_if<
|
---|
126 | iterator_archetypes::has_access<
|
---|
127 | AccessCategory
|
---|
128 | , iterator_archetypes::writable_iterator_t
|
---|
129 | >
|
---|
130 | , mpl::identity<writable_operator_brackets<Value> >
|
---|
131 | , mpl::if_<
|
---|
132 | iterator_archetypes::has_access<
|
---|
133 | AccessCategory
|
---|
134 | , iterator_archetypes::readable_iterator_t
|
---|
135 | >
|
---|
136 | , readable_operator_brackets<Value>
|
---|
137 | , no_operator_brackets
|
---|
138 | >
|
---|
139 | >
|
---|
140 | , mpl::identity<no_operator_brackets>
|
---|
141 | >::type
|
---|
142 | >::type
|
---|
143 | {};
|
---|
144 |
|
---|
145 | template <class TraversalCategory>
|
---|
146 | struct traversal_archetype_impl
|
---|
147 | {
|
---|
148 | template <class Derived,class Value> struct archetype;
|
---|
149 | };
|
---|
150 |
|
---|
151 | // Constructor argument for those iterators that
|
---|
152 | // are not default constructible
|
---|
153 | struct ctor_arg {};
|
---|
154 |
|
---|
155 | template <class Derived, class Value, class TraversalCategory>
|
---|
156 | struct traversal_archetype_
|
---|
157 | : mpl::aux::msvc_eti_base<
|
---|
158 | typename traversal_archetype_impl<TraversalCategory>::template archetype<Derived,Value>
|
---|
159 | >::type
|
---|
160 | {
|
---|
161 | typedef typename
|
---|
162 | traversal_archetype_impl<TraversalCategory>::template archetype<Derived,Value>
|
---|
163 | base;
|
---|
164 |
|
---|
165 | traversal_archetype_() {}
|
---|
166 |
|
---|
167 | traversal_archetype_(ctor_arg arg)
|
---|
168 | : base(arg)
|
---|
169 | {}
|
---|
170 | };
|
---|
171 |
|
---|
172 | template <>
|
---|
173 | struct traversal_archetype_impl<incrementable_traversal_tag>
|
---|
174 | {
|
---|
175 | template<class Derived, class Value>
|
---|
176 | struct archetype
|
---|
177 | {
|
---|
178 | explicit archetype(ctor_arg) {}
|
---|
179 |
|
---|
180 | struct bogus { }; // This use to be void, but that causes trouble for iterator_facade. Need more research. -JGS
|
---|
181 | typedef bogus difference_type;
|
---|
182 |
|
---|
183 | Derived& operator++() { return (Derived&)static_object<Derived>::get(); }
|
---|
184 | Derived operator++(int) const { return (Derived&)static_object<Derived>::get(); }
|
---|
185 | };
|
---|
186 | };
|
---|
187 |
|
---|
188 | template <>
|
---|
189 | struct traversal_archetype_impl<single_pass_traversal_tag>
|
---|
190 | {
|
---|
191 | template<class Derived, class Value>
|
---|
192 | struct archetype
|
---|
193 | : public equality_comparable< traversal_archetype_<Derived, Value, single_pass_traversal_tag> >,
|
---|
194 | public traversal_archetype_<Derived, Value, incrementable_traversal_tag>
|
---|
195 | {
|
---|
196 | explicit archetype(ctor_arg arg)
|
---|
197 | : traversal_archetype_<Derived, Value, incrementable_traversal_tag>(arg)
|
---|
198 | {}
|
---|
199 | };
|
---|
200 | };
|
---|
201 |
|
---|
202 | template <class Derived, class Value>
|
---|
203 | bool operator==(traversal_archetype_<Derived, Value, single_pass_traversal_tag> const&,
|
---|
204 | traversal_archetype_<Derived, Value, single_pass_traversal_tag> const&) { return true; }
|
---|
205 |
|
---|
206 | #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
---|
207 | // doesn't seem to pick up != from equality_comparable
|
---|
208 | template <class Derived, class Value>
|
---|
209 | bool operator!=(traversal_archetype_<Derived, Value, single_pass_traversal_tag> const&,
|
---|
210 | traversal_archetype_<Derived, Value, single_pass_traversal_tag> const&) { return true; }
|
---|
211 | #endif
|
---|
212 | template <>
|
---|
213 | struct traversal_archetype_impl<forward_traversal_tag>
|
---|
214 | {
|
---|
215 | template<class Derived, class Value>
|
---|
216 | struct archetype
|
---|
217 | : public traversal_archetype_<Derived, Value, single_pass_traversal_tag>
|
---|
218 | {
|
---|
219 | archetype()
|
---|
220 | : traversal_archetype_<Derived, Value, single_pass_traversal_tag>(ctor_arg())
|
---|
221 | {}
|
---|
222 | typedef std::ptrdiff_t difference_type;
|
---|
223 | };
|
---|
224 | };
|
---|
225 |
|
---|
226 | template <>
|
---|
227 | struct traversal_archetype_impl<bidirectional_traversal_tag>
|
---|
228 | {
|
---|
229 | template<class Derived, class Value>
|
---|
230 | struct archetype
|
---|
231 | : public traversal_archetype_<Derived, Value, forward_traversal_tag>
|
---|
232 | {
|
---|
233 | Derived& operator--() { return static_object<Derived>::get(); }
|
---|
234 | Derived operator--(int) const { return static_object<Derived>::get(); }
|
---|
235 | };
|
---|
236 | };
|
---|
237 |
|
---|
238 | template <>
|
---|
239 | struct traversal_archetype_impl<random_access_traversal_tag>
|
---|
240 | {
|
---|
241 | template<class Derived, class Value>
|
---|
242 | struct archetype
|
---|
243 | : public traversal_archetype_<Derived, Value, bidirectional_traversal_tag>
|
---|
244 | {
|
---|
245 | Derived& operator+=(std::ptrdiff_t) { return static_object<Derived>::get(); }
|
---|
246 | Derived& operator-=(std::ptrdiff_t) { return static_object<Derived>::get(); }
|
---|
247 | };
|
---|
248 | };
|
---|
249 |
|
---|
250 | template <class Derived, class Value>
|
---|
251 | Derived& operator+(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
|
---|
252 | std::ptrdiff_t) { return static_object<Derived>::get(); }
|
---|
253 |
|
---|
254 | template <class Derived, class Value>
|
---|
255 | Derived& operator+(std::ptrdiff_t,
|
---|
256 | traversal_archetype_<Derived, Value, random_access_traversal_tag> const&)
|
---|
257 | { return static_object<Derived>::get(); }
|
---|
258 |
|
---|
259 | template <class Derived, class Value>
|
---|
260 | Derived& operator-(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
|
---|
261 | std::ptrdiff_t)
|
---|
262 | { return static_object<Derived>::get(); }
|
---|
263 |
|
---|
264 | template <class Derived, class Value>
|
---|
265 | std::ptrdiff_t operator-(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
|
---|
266 | traversal_archetype_<Derived, Value, random_access_traversal_tag> const&)
|
---|
267 | { return 0; }
|
---|
268 |
|
---|
269 | template <class Derived, class Value>
|
---|
270 | bool operator<(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
|
---|
271 | traversal_archetype_<Derived, Value, random_access_traversal_tag> const&)
|
---|
272 | { return true; }
|
---|
273 |
|
---|
274 | template <class Derived, class Value>
|
---|
275 | bool operator>(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
|
---|
276 | traversal_archetype_<Derived, Value, random_access_traversal_tag> const&)
|
---|
277 | { return true; }
|
---|
278 |
|
---|
279 | template <class Derived, class Value>
|
---|
280 | bool operator<=(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
|
---|
281 | traversal_archetype_<Derived, Value, random_access_traversal_tag> const&)
|
---|
282 | { return true; }
|
---|
283 |
|
---|
284 | template <class Derived, class Value>
|
---|
285 | bool operator>=(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
|
---|
286 | traversal_archetype_<Derived, Value, random_access_traversal_tag> const&)
|
---|
287 | { return true; }
|
---|
288 |
|
---|
289 | struct bogus_type;
|
---|
290 |
|
---|
291 | template <class Value>
|
---|
292 | struct convertible_type
|
---|
293 | : mpl::if_< is_const<Value>,
|
---|
294 | typename remove_const<Value>::type,
|
---|
295 | bogus_type >
|
---|
296 | {};
|
---|
297 |
|
---|
298 | } // namespace detail
|
---|
299 |
|
---|
300 |
|
---|
301 | template <class> struct undefined;
|
---|
302 |
|
---|
303 | template <class AccessCategory>
|
---|
304 | struct iterator_access_archetype_impl
|
---|
305 | {
|
---|
306 | template <class Value> struct archetype;
|
---|
307 | };
|
---|
308 |
|
---|
309 | template <class Value, class AccessCategory>
|
---|
310 | struct iterator_access_archetype
|
---|
311 | : mpl::aux::msvc_eti_base<
|
---|
312 | typename iterator_access_archetype_impl<
|
---|
313 | AccessCategory
|
---|
314 | >::template archetype<Value>
|
---|
315 | >::type
|
---|
316 | {
|
---|
317 | };
|
---|
318 |
|
---|
319 | template <>
|
---|
320 | struct iterator_access_archetype_impl<
|
---|
321 | iterator_archetypes::readable_iterator_t
|
---|
322 | >
|
---|
323 | {
|
---|
324 | template <class Value>
|
---|
325 | struct archetype
|
---|
326 | {
|
---|
327 | typedef typename remove_cv<Value>::type value_type;
|
---|
328 | typedef Value reference;
|
---|
329 | typedef Value* pointer;
|
---|
330 |
|
---|
331 | value_type operator*() const { return static_object<value_type>::get(); }
|
---|
332 |
|
---|
333 | detail::arrow_proxy<Value> operator->() const { return detail::arrow_proxy<Value>(); }
|
---|
334 | };
|
---|
335 | };
|
---|
336 |
|
---|
337 | template <>
|
---|
338 | struct iterator_access_archetype_impl<
|
---|
339 | iterator_archetypes::writable_iterator_t
|
---|
340 | >
|
---|
341 | {
|
---|
342 | template <class Value>
|
---|
343 | struct archetype
|
---|
344 | {
|
---|
345 | # if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
---|
346 | BOOST_STATIC_ASSERT(!is_const<Value>::value);
|
---|
347 | # endif
|
---|
348 | typedef void value_type;
|
---|
349 | typedef void reference;
|
---|
350 | typedef void pointer;
|
---|
351 |
|
---|
352 | detail::assign_proxy<Value> operator*() const { return detail::assign_proxy<Value>(); }
|
---|
353 | };
|
---|
354 | };
|
---|
355 |
|
---|
356 | template <>
|
---|
357 | struct iterator_access_archetype_impl<
|
---|
358 | iterator_archetypes::readable_writable_iterator_t
|
---|
359 | >
|
---|
360 | {
|
---|
361 | template <class Value>
|
---|
362 | struct archetype
|
---|
363 | : public virtual iterator_access_archetype<
|
---|
364 | Value, iterator_archetypes::readable_iterator_t
|
---|
365 | >
|
---|
366 | {
|
---|
367 | typedef detail::read_write_proxy<Value> reference;
|
---|
368 |
|
---|
369 | detail::read_write_proxy<Value> operator*() const { return detail::read_write_proxy<Value>(); }
|
---|
370 | };
|
---|
371 | };
|
---|
372 |
|
---|
373 | template <>
|
---|
374 | struct iterator_access_archetype_impl<iterator_archetypes::readable_lvalue_iterator_t>
|
---|
375 | {
|
---|
376 | template <class Value>
|
---|
377 | struct archetype
|
---|
378 | : public virtual iterator_access_archetype<
|
---|
379 | Value, iterator_archetypes::readable_iterator_t
|
---|
380 | >
|
---|
381 | {
|
---|
382 | typedef Value& reference;
|
---|
383 |
|
---|
384 | Value& operator*() const { return static_object<Value>::get(); }
|
---|
385 | Value* operator->() const { return 0; }
|
---|
386 | };
|
---|
387 | };
|
---|
388 |
|
---|
389 | template <>
|
---|
390 | struct iterator_access_archetype_impl<iterator_archetypes::writable_lvalue_iterator_t>
|
---|
391 | {
|
---|
392 | template <class Value>
|
---|
393 | struct archetype
|
---|
394 | : public virtual iterator_access_archetype<
|
---|
395 | Value, iterator_archetypes::readable_lvalue_iterator_t
|
---|
396 | >
|
---|
397 | {
|
---|
398 | # if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
---|
399 | BOOST_STATIC_ASSERT((!is_const<Value>::value));
|
---|
400 | # endif
|
---|
401 | };
|
---|
402 | };
|
---|
403 |
|
---|
404 |
|
---|
405 | template <class Value, class AccessCategory, class TraversalCategory>
|
---|
406 | struct iterator_archetype;
|
---|
407 |
|
---|
408 | template <class Value, class AccessCategory, class TraversalCategory>
|
---|
409 | struct traversal_archetype_base
|
---|
410 | : detail::operator_brackets<
|
---|
411 | typename remove_cv<Value>::type
|
---|
412 | , AccessCategory
|
---|
413 | , TraversalCategory
|
---|
414 | >
|
---|
415 | , detail::traversal_archetype_<
|
---|
416 | iterator_archetype<Value, AccessCategory, TraversalCategory>
|
---|
417 | , Value
|
---|
418 | , TraversalCategory
|
---|
419 | >
|
---|
420 | {
|
---|
421 | };
|
---|
422 |
|
---|
423 | namespace detail
|
---|
424 | {
|
---|
425 | template <class Value, class AccessCategory, class TraversalCategory>
|
---|
426 | struct iterator_archetype_base
|
---|
427 | : iterator_access_archetype<Value, AccessCategory>
|
---|
428 | , traversal_archetype_base<Value, AccessCategory, TraversalCategory>
|
---|
429 | {
|
---|
430 | typedef iterator_access_archetype<Value, AccessCategory> access;
|
---|
431 |
|
---|
432 | typedef typename detail::facade_iterator_category<
|
---|
433 | TraversalCategory
|
---|
434 | , typename mpl::eval_if<
|
---|
435 | iterator_archetypes::has_access<
|
---|
436 | AccessCategory, iterator_archetypes::writable_iterator_t
|
---|
437 | >
|
---|
438 | , remove_const<Value>
|
---|
439 | , add_const<Value>
|
---|
440 | >::type
|
---|
441 | , typename access::reference
|
---|
442 | >::type iterator_category;
|
---|
443 |
|
---|
444 | // Needed for some broken libraries (see below)
|
---|
445 | typedef boost::iterator<
|
---|
446 | iterator_category
|
---|
447 | , Value
|
---|
448 | , typename traversal_archetype_base<
|
---|
449 | Value, AccessCategory, TraversalCategory
|
---|
450 | >::difference_type
|
---|
451 | , typename access::pointer
|
---|
452 | , typename access::reference
|
---|
453 | > workaround_iterator_base;
|
---|
454 | };
|
---|
455 | }
|
---|
456 |
|
---|
457 | template <class Value, class AccessCategory, class TraversalCategory>
|
---|
458 | struct iterator_archetype
|
---|
459 | : public detail::iterator_archetype_base<Value, AccessCategory, TraversalCategory>
|
---|
460 |
|
---|
461 | // These broken libraries require derivation from std::iterator
|
---|
462 | // (or related magic) in order to handle iter_swap and other
|
---|
463 | // iterator operations
|
---|
464 | # if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, < 310) \
|
---|
465 | || BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(0x20101))
|
---|
466 | , public detail::iterator_archetype_base<
|
---|
467 | Value, AccessCategory, TraversalCategory
|
---|
468 | >::workaround_iterator_base
|
---|
469 | # endif
|
---|
470 | {
|
---|
471 | // Derivation from std::iterator above caused references to nested
|
---|
472 | // types to be ambiguous, so now we have to redeclare them all
|
---|
473 | // here.
|
---|
474 | # if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, < 310) \
|
---|
475 | || BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(0x20101))
|
---|
476 |
|
---|
477 | typedef detail::iterator_archetype_base<
|
---|
478 | Value,AccessCategory,TraversalCategory
|
---|
479 | > base;
|
---|
480 |
|
---|
481 | typedef typename base::value_type value_type;
|
---|
482 | typedef typename base::reference reference;
|
---|
483 | typedef typename base::pointer pointer;
|
---|
484 | typedef typename base::difference_type difference_type;
|
---|
485 | typedef typename base::iterator_category iterator_category;
|
---|
486 | # endif
|
---|
487 |
|
---|
488 | iterator_archetype() { }
|
---|
489 | iterator_archetype(iterator_archetype const& x)
|
---|
490 | : detail::iterator_archetype_base<
|
---|
491 | Value
|
---|
492 | , AccessCategory
|
---|
493 | , TraversalCategory
|
---|
494 | >(x)
|
---|
495 | {}
|
---|
496 |
|
---|
497 | iterator_archetype& operator=(iterator_archetype const&)
|
---|
498 | { return *this; }
|
---|
499 |
|
---|
500 | # if 0
|
---|
501 | // Optional conversion from mutable
|
---|
502 | iterator_archetype(
|
---|
503 | iterator_archetype<
|
---|
504 | typename detail::convertible_type<Value>::type
|
---|
505 | , AccessCategory
|
---|
506 | , TraversalCategory> const&
|
---|
507 | );
|
---|
508 | # endif
|
---|
509 | };
|
---|
510 |
|
---|
511 | } // namespace boost
|
---|
512 |
|
---|
513 |
|
---|
514 | #endif // BOOST_ITERATOR_ARCHETYPES_HPP
|
---|