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)
6 #ifndef BOOST_ITERATOR_ARCHETYPES_HPP
7 #define BOOST_ITERATOR_ARCHETYPES_HPP
9 #include <boost/iterator/iterator_categories.hpp>
10 #include <boost/operators.hpp>
11 #include <boost/static_assert.hpp>
13 #include <boost/iterator/detail/facade_iterator_category.hpp>
15 #include <boost/type_traits/is_const.hpp>
16 #include <boost/type_traits/add_const.hpp>
17 #include <boost/type_traits/remove_const.hpp>
18 #include <boost/type_traits/remove_cv.hpp>
20 #include <boost/concept_archetype.hpp>
22 #include <boost/mpl/bitand.hpp>
23 #include <boost/mpl/int.hpp>
24 #include <boost/mpl/equal_to.hpp>
25 #include <boost/mpl/if.hpp>
26 #include <boost/mpl/eval_if.hpp>
27 #include <boost/mpl/and.hpp>
28 #include <boost/mpl/identity.hpp>
35 template <class Value, class AccessCategory>
36 struct access_archetype;
38 template <class Derived, class Value, class AccessCategory, class TraversalCategory>
39 struct traversal_archetype;
44 readable_iterator_bit = 1
45 , writable_iterator_bit = 2
46 , swappable_iterator_bit = 4
47 , lvalue_iterator_bit = 8
50 // Not quite tags, since dispatching wouldn't work.
51 typedef mpl::int_<readable_iterator_bit>::type readable_iterator_t;
52 typedef mpl::int_<writable_iterator_bit>::type writable_iterator_t;
55 (readable_iterator_bit|writable_iterator_bit)
56 >::type readable_writable_iterator_t;
59 (readable_iterator_bit|lvalue_iterator_bit)
60 >::type readable_lvalue_iterator_t;
63 (lvalue_iterator_bit|writable_iterator_bit)
64 >::type writable_lvalue_iterator_t;
66 typedef mpl::int_<swappable_iterator_bit>::type swappable_iterator_t;
67 typedef mpl::int_<lvalue_iterator_bit>::type lvalue_iterator_t;
69 template <class Derived, class Base>
72 mpl::bitand_<Derived,Base>
83 assign_proxy& operator=(T) { return *this; }
89 operator T() { return static_object<T>::get(); }
93 struct read_write_proxy
94 : read_proxy<T> // Use to inherit from assign_proxy, but that doesn't work. -JGS
96 read_write_proxy& operator=(T) { return *this; }
102 T const* operator->() const { return 0; }
105 struct no_operator_brackets {};
107 template <class ValueType>
108 struct readable_operator_brackets
110 read_proxy<ValueType> operator[](std::ptrdiff_t n) const { return read_proxy<ValueType>(); }
113 template <class ValueType>
114 struct writable_operator_brackets
116 read_write_proxy<ValueType> operator[](std::ptrdiff_t n) const { return read_write_proxy<ValueType>(); }
119 template <class Value, class AccessCategory, class TraversalCategory>
120 struct operator_brackets
122 is_convertible<TraversalCategory, random_access_traversal_tag>
124 archetypes::has_access<
126 , archetypes::writable_iterator_t
128 , mpl::identity<writable_operator_brackets<Value> >
130 archetypes::has_access<
132 , archetypes::readable_iterator_t
134 , readable_operator_brackets<Value>
135 , no_operator_brackets
138 , mpl::identity<no_operator_brackets>
142 template <class TraversalCategory>
143 struct traversal_archetype_impl
145 template <class Derived,class Value> struct archetype;
148 // Constructor argument for those iterators that
149 // are not default constructible
152 template <class Derived, class Value, class TraversalCategory>
153 struct traversal_archetype_
154 : traversal_archetype_impl<TraversalCategory>::template archetype<Derived,Value>
157 traversal_archetype_impl<TraversalCategory>::template archetype<Derived,Value>
160 traversal_archetype_() {}
162 traversal_archetype_(ctor_arg arg)
168 struct traversal_archetype_impl<incrementable_traversal_tag>
170 template<class Derived, class Value>
173 explicit archetype(ctor_arg) {}
175 struct bogus { }; // This use to be void, but that causes trouble for iterator_facade. Need more research. -JGS
176 typedef bogus difference_type;
178 Derived& operator++() { return (Derived&)static_object<Derived>::get(); }
179 Derived operator++(int) const { return (Derived&)static_object<Derived>::get(); }
184 struct traversal_archetype_impl<single_pass_traversal_tag>
186 template<class Derived, class Value>
188 : public equality_comparable< traversal_archetype_<Derived, Value, single_pass_traversal_tag> >,
189 public traversal_archetype_<Derived, Value, incrementable_traversal_tag>
191 explicit archetype(ctor_arg arg)
192 : traversal_archetype_<Derived, Value, incrementable_traversal_tag>(arg)
195 typedef std::ptrdiff_t difference_type;
199 template <class Derived, class Value>
200 bool operator==(traversal_archetype_<Derived, Value, single_pass_traversal_tag> const&,
201 traversal_archetype_<Derived, Value, single_pass_traversal_tag> const&) { return true; }
204 struct traversal_archetype_impl<forward_traversal_tag>
206 template<class Derived, class Value>
208 : public traversal_archetype_<Derived, Value, single_pass_traversal_tag>
211 : traversal_archetype_<Derived, Value, single_pass_traversal_tag>(ctor_arg())
217 struct traversal_archetype_impl<bidirectional_traversal_tag>
219 template<class Derived, class Value>
221 : public traversal_archetype_<Derived, Value, forward_traversal_tag>
223 Derived& operator--() { return static_object<Derived>::get(); }
224 Derived operator--(int) const { return static_object<Derived>::get(); }
229 struct traversal_archetype_impl<random_access_traversal_tag>
231 template<class Derived, class Value>
233 : public traversal_archetype_<Derived, Value, bidirectional_traversal_tag>
235 Derived& operator+=(std::ptrdiff_t) { return static_object<Derived>::get(); }
236 Derived& operator-=(std::ptrdiff_t) { return static_object<Derived>::get(); }
240 template <class Derived, class Value>
241 Derived& operator+(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
242 std::ptrdiff_t) { return static_object<Derived>::get(); }
244 template <class Derived, class Value>
245 Derived& operator+(std::ptrdiff_t,
246 traversal_archetype_<Derived, Value, random_access_traversal_tag> const&)
247 { return static_object<Derived>::get(); }
249 template <class Derived, class Value>
250 Derived& operator-(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
252 { return static_object<Derived>::get(); }
254 template <class Derived, class Value>
255 std::ptrdiff_t operator-(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
256 traversal_archetype_<Derived, Value, random_access_traversal_tag> const&)
259 template <class Derived, class Value>
260 bool operator<(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
261 traversal_archetype_<Derived, Value, random_access_traversal_tag> const&)
264 template <class Derived, class Value>
265 bool operator>(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
266 traversal_archetype_<Derived, Value, random_access_traversal_tag> const&)
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&)
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&)
281 template <class Value>
282 struct convertible_type
283 : mpl::if_< is_const<Value>,
284 typename remove_const<Value>::type,
288 } // namespace detail
291 template <class> struct undefined;
293 template <class AccessCategory>
294 struct iterator_access_archetype_impl
296 template <class Value> struct archetype;
299 template <class Value, class AccessCategory>
300 struct iterator_access_archetype
301 : iterator_access_archetype_impl<
303 >::template archetype<Value>
308 struct iterator_access_archetype_impl<
309 archetypes::readable_iterator_t
312 template <class Value>
315 typedef typename remove_cv<Value>::type value_type;
316 typedef Value reference;
317 typedef Value* pointer;
319 value_type operator*() const { return static_object<value_type>::get(); }
321 detail::arrow_proxy<Value> operator->() const { return detail::arrow_proxy<Value>(); }
326 struct iterator_access_archetype_impl<
327 archetypes::writable_iterator_t
330 template <class Value>
333 BOOST_STATIC_ASSERT(!is_const<Value>::value);
334 typedef void value_type;
335 typedef void reference;
336 typedef void pointer;
338 detail::assign_proxy<Value> operator*() const { return detail::assign_proxy<Value>(); }
343 struct iterator_access_archetype_impl<
344 archetypes::readable_writable_iterator_t
347 template <class Value>
349 : public virtual iterator_access_archetype<
350 Value, archetypes::readable_iterator_t
353 typedef detail::read_write_proxy<Value> reference;
355 detail::read_write_proxy<Value> operator*() const { return detail::read_write_proxy<Value>(); }
360 struct iterator_access_archetype_impl<archetypes::readable_lvalue_iterator_t>
362 template <class Value>
364 : public virtual iterator_access_archetype<
365 Value, archetypes::readable_iterator_t
368 typedef Value& reference;
370 Value& operator*() const { return static_object<Value>::get(); }
371 Value* operator->() const { return 0; }
376 struct iterator_access_archetype_impl<archetypes::writable_lvalue_iterator_t>
378 template <class Value>
380 : public virtual iterator_access_archetype<
381 Value, archetypes::readable_lvalue_iterator_t
384 BOOST_STATIC_ASSERT((!is_const<Value>::value));
389 template <class Value, class AccessCategory, class TraversalCategory>
390 struct iterator_archetype;
392 template <class Value, class AccessCategory, class TraversalCategory>
393 struct traversal_archetype_base
394 : detail::operator_brackets<
395 typename remove_cv<Value>::type
399 , detail::traversal_archetype_<
400 iterator_archetype<Value, AccessCategory, TraversalCategory>
409 template <class Value, class AccessCategory, class TraversalCategory>
410 struct iterator_archetype_base
411 : iterator_access_archetype<Value, AccessCategory>
412 , traversal_archetype_base<Value, AccessCategory, TraversalCategory>
414 typedef iterator_access_archetype<Value, AccessCategory> access;
416 typedef typename detail::facade_iterator_category<
418 , typename mpl::eval_if<
419 archetypes::has_access<
420 AccessCategory, archetypes::writable_iterator_t
422 , remove_const<Value>
425 , typename access::reference
426 >::type iterator_category;
428 // Needed for some broken libraries (see below)
429 struct workaround_iterator_base
431 typedef typename iterator_archetype_base::iterator_category iterator_category;
432 typedef Value value_type;
433 typedef typename traversal_archetype_base<
434 Value, AccessCategory, TraversalCategory
435 >::difference_type difference_type;
436 typedef typename access::pointer pointer;
437 typedef typename access::reference reference;
442 template <class Value, class AccessCategory, class TraversalCategory>
443 struct iterator_archetype
444 : public detail::iterator_archetype_base<Value, AccessCategory, TraversalCategory>
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
456 // Derivation from std::iterator above caused references to nested
457 // types to be ambiguous, so now we have to redeclare them all
459 # if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, < 310) \
460 || BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(0x20101))
462 typedef detail::iterator_archetype_base<
463 Value,AccessCategory,TraversalCategory
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;
473 iterator_archetype() { }
474 iterator_archetype(iterator_archetype const& x)
475 : detail::iterator_archetype_base<
482 iterator_archetype& operator=(iterator_archetype const&)
486 // Optional conversion from mutable
489 typename detail::convertible_type<Value>::type
491 , TraversalCategory> const&
496 } // namespace iterators
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;
509 #endif // BOOST_ITERATOR_ARCHETYPES_HPP