// (C) Copyright Jeremy Siek 2002. // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_ITERATOR_ARCHETYPES_HPP #define BOOST_ITERATOR_ARCHETYPES_HPP #include #include #include #include #include #include #include namespace boost { namespace iterators { template struct access_archetype; template struct traversal_archetype; namespace archetypes { enum { readable_iterator_bit = 1, writable_iterator_bit = 2, swappable_iterator_bit = 4, lvalue_iterator_bit = 8 }; // Not quite tags, since dispatching wouldn't work. using readable_iterator_t = std::integral_constant; using writable_iterator_t = std::integral_constant; using readable_writable_iterator_t = std::integral_constant< unsigned int, (readable_iterator_bit | writable_iterator_bit) >; using readable_lvalue_iterator_t = std::integral_constant< unsigned int, (readable_iterator_bit | lvalue_iterator_bit) >; using writable_lvalue_iterator_t = std::integral_constant< unsigned int, (lvalue_iterator_bit | writable_iterator_bit) >; using swappable_iterator_t = std::integral_constant; using lvalue_iterator_t = std::integral_constant; template struct has_access : public std::integral_constant {}; } // namespace archetypes namespace detail { template struct assign_proxy { assign_proxy& operator=(T) { return *this; } }; template struct read_proxy { operator T() { return static_object::get(); } }; template struct read_write_proxy : public read_proxy // Used to inherit from assign_proxy, but that doesn't work. -JGS { read_write_proxy& operator=(T) { return *this; } }; template struct arrow_proxy { T const* operator->() const { return 0; } }; struct no_operator_brackets {}; template struct readable_operator_brackets { read_proxy operator[](std::ptrdiff_t n) const { return read_proxy(); } }; template struct writable_operator_brackets { read_write_proxy operator[](std::ptrdiff_t n) const { return read_write_proxy(); } }; template struct operator_brackets : public mp11::mp_eval_if_c< !std::is_convertible::value, no_operator_brackets, mp11::mp_cond, archetypes::has_access, writable_operator_brackets, archetypes::has_access, readable_operator_brackets, std::true_type, no_operator_brackets > {}; template struct traversal_archetype_impl { template struct archetype; }; // Constructor argument for those iterators that // are not default constructible struct ctor_arg {}; template struct traversal_archetype_ : public traversal_archetype_impl::template archetype { using base = typename traversal_archetype_impl::template archetype; traversal_archetype_() {} traversal_archetype_(ctor_arg arg) : base(arg) {} }; template <> struct traversal_archetype_impl { template struct archetype { explicit archetype(ctor_arg) {} struct bogus { }; // This used to be void, but that causes trouble for iterator_facade. Need more research. -JGS using difference_type = bogus; Derived& operator++() { return (Derived&)static_object::get(); } Derived operator++(int) const { return (Derived&)static_object::get(); } }; }; template <> struct traversal_archetype_impl { template struct archetype : public equality_comparable< traversal_archetype_ >, public traversal_archetype_ { explicit archetype(ctor_arg arg) : traversal_archetype_(arg) {} using difference_type = std::ptrdiff_t; }; }; template bool operator==( traversal_archetype_ const&, traversal_archetype_ const&) { return true; } template <> struct traversal_archetype_impl { template struct archetype : public traversal_archetype_ { archetype() : traversal_archetype_(ctor_arg()) {} }; }; template <> struct traversal_archetype_impl { template struct archetype : public traversal_archetype_ { Derived& operator--() { return static_object::get(); } Derived operator--(int) const { return static_object::get(); } }; }; template <> struct traversal_archetype_impl { template struct archetype : public traversal_archetype_ { Derived& operator+=(std::ptrdiff_t) { return static_object::get(); } Derived& operator-=(std::ptrdiff_t) { return static_object::get(); } }; }; template Derived& operator+( traversal_archetype_ const&, std::ptrdiff_t) { return static_object::get(); } template Derived& operator+( std::ptrdiff_t, traversal_archetype_ const&) { return static_object::get(); } template Derived& operator-( traversal_archetype_ const&, std::ptrdiff_t) { return static_object::get(); } template std::ptrdiff_t operator-( traversal_archetype_ const&, traversal_archetype_ const&) { return 0; } template bool operator<( traversal_archetype_ const&, traversal_archetype_ const&) { return true; } template bool operator>( traversal_archetype_ const&, traversal_archetype_ const&) { return true; } template bool operator<=( traversal_archetype_ const&, traversal_archetype_ const&) { return true; } template bool operator>=( traversal_archetype_ const&, traversal_archetype_ const&) { return true; } struct bogus_type; template struct convertible_type { using type = bogus_type; }; template struct convertible_type { using type = Value; }; } // namespace detail template struct undefined; template struct iterator_access_archetype_impl { template struct archetype; }; template struct iterator_access_archetype : public iterator_access_archetype_impl::template archetype { }; template <> struct iterator_access_archetype_impl { template struct archetype { using value_type = typename std::remove_cv::type; using reference = Value; using pointer = Value*; value_type operator*() const { return static_object::get(); } detail::arrow_proxy operator->() const { return detail::arrow_proxy(); } }; }; template <> struct iterator_access_archetype_impl { template struct archetype { static_assert(!std::is_const::value, "Value type must not be const."); using value_type = void; using reference = void; using pointer = void; detail::assign_proxy operator*() const { return detail::assign_proxy(); } }; }; template <> struct iterator_access_archetype_impl { template struct archetype : public virtual iterator_access_archetype { using reference = detail::read_write_proxy; detail::read_write_proxy operator*() const { return detail::read_write_proxy(); } }; }; template <> struct iterator_access_archetype_impl { template struct archetype : public virtual iterator_access_archetype { using reference = Value&; Value& operator*() const { return static_object::get(); } Value* operator->() const { return 0; } }; }; template <> struct iterator_access_archetype_impl { template struct archetype : public virtual iterator_access_archetype { static_assert(!std::is_const::value, "Value type must not be const."); }; }; template struct iterator_archetype; template struct traversal_archetype_base : public detail::operator_brackets< typename std::remove_cv::type, AccessCategory, TraversalCategory >, public detail::traversal_archetype_< iterator_archetype, Value, TraversalCategory > { }; namespace detail { template struct iterator_archetype_base : public iterator_access_archetype, public traversal_archetype_base { using access = iterator_access_archetype; using iterator_category = typename detail::facade_iterator_category< TraversalCategory, typename std::conditional< archetypes::has_access< AccessCategory, archetypes::writable_iterator_t >::value, std::remove_const, std::add_const >::type::type, typename access::reference >::type; // Needed for some broken libraries (see below) struct workaround_iterator_base { using iterator_category = typename iterator_archetype_base::iterator_category; using value_type = Value; using difference_type = typename traversal_archetype_base< Value, AccessCategory, TraversalCategory >::difference_type; using pointer = typename access::pointer; using reference = typename access::reference; }; }; } // namespace detail template struct iterator_archetype : public detail::iterator_archetype_base // These broken libraries require derivation from std::iterator // (or related magic) in order to handle iter_swap and other // iterator operations # if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, < 310) \ || BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(0x20101)) , public detail::iterator_archetype_base< Value, AccessCategory, TraversalCategory >::workaround_iterator_base # endif { // Derivation from std::iterator above caused references to nested // types to be ambiguous, so now we have to redeclare them all // here. # if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, < 310) \ || BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(0x20101)) using base = detail::iterator_archetype_base< Value, AccessCategory, TraversalCategory >; using value_type = typename base::value_type; using reference = typename base::reference; using pointer = typename base::pointer; using difference_type = typename base::difference_type; using iterator_category = typename base::iterator_category; # endif iterator_archetype() { } iterator_archetype(iterator_archetype const& x) : detail::iterator_archetype_base(x) {} iterator_archetype& operator=(iterator_archetype const&) { return *this; } # if 0 // Optional conversion from mutable iterator_archetype( iterator_archetype< typename detail::convertible_type::type , AccessCategory , TraversalCategory> const& ); # endif }; } // namespace iterators // Backward compatibility names namespace iterator_archetypes = iterators::archetypes; using iterators::access_archetype; using iterators::traversal_archetype; using iterators::iterator_archetype; using iterators::undefined; using iterators::iterator_access_archetype_impl; using iterators::traversal_archetype_base; } // namespace boost #endif // BOOST_ITERATOR_ARCHETYPES_HPP