Chris@16: // (C) Copyright David Abrahams 2002. Chris@16: // (C) Copyright Jeremy Siek 2002. Chris@16: // (C) Copyright Thomas Witt 2002. Chris@16: // Distributed under the Boost Software License, Version 1.0. (See Chris@16: // accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: #ifndef BOOST_ITERATOR_ADAPTOR_23022003THW_HPP Chris@16: #define BOOST_ITERATOR_ADAPTOR_23022003THW_HPP Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: Chris@16: #ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY Chris@16: # include Chris@16: #endif Chris@16: Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: Chris@101: namespace boost { Chris@101: namespace iterators { Chris@101: Chris@16: // Used as a default template argument internally, merely to Chris@16: // indicate "use the default", this can also be passed by users Chris@16: // explicitly in order to specify that the default should be used. Chris@16: struct use_default; Chris@101: Chris@101: } // namespace iterators Chris@101: Chris@101: using iterators::use_default; Chris@101: Chris@101: // the incompleteness of use_default causes massive problems for Chris@101: // is_convertible (naturally). This workaround is fortunately not Chris@101: // needed for vc6/vc7. Chris@101: template Chris@101: struct is_convertible Chris@101: : mpl::false_ {}; Chris@101: Chris@101: namespace iterators { Chris@101: Chris@16: namespace detail Chris@16: { Chris@16: Chris@101: // Chris@16: // Result type used in enable_if_convertible meta function. Chris@101: // This can be an incomplete type, as only pointers to Chris@16: // enable_if_convertible< ... >::type are used. Chris@16: // We could have used void for this, but conversion to Chris@16: // void* is just to easy. Chris@16: // Chris@16: struct enable_type; Chris@16: } Chris@16: Chris@16: Chris@16: // Chris@16: // enable_if for use in adapted iterators constructors. Chris@16: // Chris@16: // In order to provide interoperability between adapted constant and Chris@16: // mutable iterators, adapted iterators will usually provide templated Chris@16: // conversion constructors of the following form Chris@16: // Chris@16: // template Chris@16: // class adapted_iterator : Chris@16: // public iterator_adaptor< adapted_iterator, Iterator > Chris@16: // { Chris@16: // public: Chris@101: // Chris@16: // ... Chris@16: // Chris@16: // template Chris@16: // adapted_iterator( Chris@16: // OtherIterator const& it Chris@16: // , typename enable_if_convertible::type* = 0); Chris@16: // Chris@16: // ... Chris@16: // }; Chris@16: // Chris@16: // enable_if_convertible is used to remove those overloads from the overload Chris@16: // set that cannot be instantiated. For all practical purposes only overloads Chris@16: // for constant/mutable interaction will remain. This has the advantage that Chris@16: // meta functions like boost::is_convertible do not return false positives, Chris@16: // as they can only look at the signature of the conversion constructor Chris@16: // and not at the actual instantiation. Chris@16: // Chris@16: // enable_if_interoperable can be safely used in user code. It falls back to Chris@101: // always enabled for compilers that don't support enable_if or is_convertible. Chris@101: // There is no need for compiler specific workarounds in user code. Chris@16: // Chris@16: // The operators implementation relies on boost::is_convertible not returning Chris@16: // false positives for user/library defined iterator types. See comments Chris@16: // on operator implementation for consequences. Chris@16: // Chris@101: # if defined(BOOST_NO_IS_CONVERTIBLE) || defined(BOOST_NO_SFINAE) Chris@101: Chris@16: template Chris@16: struct enable_if_convertible Chris@16: { Chris@101: typedef boost::iterators::detail::enable_type type; Chris@16: }; Chris@101: Chris@101: # elif BOOST_WORKAROUND(_MSC_FULL_VER, BOOST_TESTED_AT(13102292)) Chris@101: Chris@16: // For some reason vc7.1 needs us to "cut off" instantiation Chris@16: // of is_convertible in a few cases. Chris@16: template Chris@16: struct enable_if_convertible Chris@16: : iterators::enable_if< Chris@16: mpl::or_< Chris@16: is_same Chris@16: , is_convertible Chris@16: > Chris@101: , boost::iterators::detail::enable_type Chris@16: > Chris@16: {}; Chris@101: Chris@101: # else Chris@101: Chris@16: template Chris@16: struct enable_if_convertible Chris@16: : iterators::enable_if< Chris@16: is_convertible Chris@101: , boost::iterators::detail::enable_type Chris@16: > Chris@16: {}; Chris@101: Chris@16: # endif Chris@101: Chris@16: // Chris@16: // Default template argument handling for iterator_adaptor Chris@16: // Chris@16: namespace detail Chris@16: { Chris@16: // If T is use_default, return the result of invoking Chris@16: // DefaultNullaryFn, otherwise return T. Chris@16: template Chris@16: struct ia_dflt_help Chris@16: : mpl::eval_if< Chris@16: is_same Chris@16: , DefaultNullaryFn Chris@16: , mpl::identity Chris@16: > Chris@16: { Chris@16: }; Chris@16: Chris@16: // A metafunction which computes an iterator_adaptor's base class, Chris@16: // a specialization of iterator_facade. Chris@16: template < Chris@16: class Derived Chris@16: , class Base Chris@16: , class Value Chris@16: , class Traversal Chris@16: , class Reference Chris@16: , class Difference Chris@16: > Chris@16: struct iterator_adaptor_base Chris@16: { Chris@16: typedef iterator_facade< Chris@16: Derived Chris@101: Chris@16: # ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY Chris@101: , typename boost::iterators::detail::ia_dflt_help< Chris@16: Value Chris@16: , mpl::eval_if< Chris@16: is_same Chris@16: , iterator_value Chris@16: , remove_reference Chris@16: > Chris@16: >::type Chris@16: # else Chris@101: , typename boost::iterators::detail::ia_dflt_help< Chris@16: Value, iterator_value Chris@16: >::type Chris@16: # endif Chris@101: Chris@101: , typename boost::iterators::detail::ia_dflt_help< Chris@16: Traversal Chris@16: , iterator_traversal Chris@16: >::type Chris@16: Chris@101: , typename boost::iterators::detail::ia_dflt_help< Chris@16: Reference Chris@16: , mpl::eval_if< Chris@16: is_same Chris@16: , iterator_reference Chris@16: , add_reference Chris@16: > Chris@16: >::type Chris@16: Chris@101: , typename boost::iterators::detail::ia_dflt_help< Chris@16: Difference, iterator_difference Chris@16: >::type Chris@16: > Chris@16: type; Chris@16: }; Chris@101: Chris@16: // workaround for aC++ CR JAGaf33512 Chris@16: template Chris@16: inline void iterator_adaptor_assert_traversal () Chris@16: { Chris@16: BOOST_STATIC_ASSERT((is_convertible::value)); Chris@16: } Chris@16: } Chris@101: Chris@16: // Chris@16: // Iterator Adaptor Chris@16: // Chris@16: // The parameter ordering changed slightly with respect to former Chris@16: // versions of iterator_adaptor The idea is that when the user needs Chris@16: // to fiddle with the reference type it is highly likely that the Chris@16: // iterator category has to be adjusted as well. Any of the Chris@16: // following four template arguments may be ommitted or explicitly Chris@16: // replaced by use_default. Chris@16: // Chris@16: // Value - if supplied, the value_type of the resulting iterator, unless Chris@16: // const. If const, a conforming compiler strips constness for the Chris@16: // value_type. If not supplied, iterator_traits::value_type is used Chris@16: // Chris@16: // Category - the traversal category of the resulting iterator. If not Chris@16: // supplied, iterator_traversal::type is used. Chris@16: // Chris@16: // Reference - the reference type of the resulting iterator, and in Chris@16: // particular, the result type of operator*(). If not supplied but Chris@16: // Value is supplied, Value& is used. Otherwise Chris@16: // iterator_traits::reference is used. Chris@16: // Chris@16: // Difference - the difference_type of the resulting iterator. If not Chris@16: // supplied, iterator_traits::difference_type is used. Chris@16: // Chris@16: template < Chris@16: class Derived Chris@16: , class Base Chris@16: , class Value = use_default Chris@16: , class Traversal = use_default Chris@16: , class Reference = use_default Chris@16: , class Difference = use_default Chris@16: > Chris@16: class iterator_adaptor Chris@101: : public boost::iterators::detail::iterator_adaptor_base< Chris@16: Derived, Base, Value, Traversal, Reference, Difference Chris@16: >::type Chris@16: { Chris@16: friend class iterator_core_access; Chris@16: Chris@16: protected: Chris@101: typedef typename boost::iterators::detail::iterator_adaptor_base< Chris@16: Derived, Base, Value, Traversal, Reference, Difference Chris@16: >::type super_t; Chris@16: public: Chris@16: iterator_adaptor() {} Chris@16: Chris@16: explicit iterator_adaptor(Base const &iter) Chris@16: : m_iterator(iter) Chris@16: { Chris@16: } Chris@16: Chris@16: typedef Base base_type; Chris@16: Chris@16: Base const& base() const Chris@16: { return m_iterator; } Chris@16: Chris@16: protected: Chris@16: // for convenience in derived classes Chris@16: typedef iterator_adaptor iterator_adaptor_; Chris@101: Chris@16: // Chris@16: // lvalue access to the Base object for Derived Chris@16: // Chris@16: Base const& base_reference() const Chris@16: { return m_iterator; } Chris@16: Chris@16: Base& base_reference() Chris@16: { return m_iterator; } Chris@16: Chris@16: private: Chris@16: // Chris@16: // Core iterator interface for iterator_facade. This is private Chris@16: // to prevent temptation for Derived classes to use it, which Chris@16: // will often result in an error. Derived classes should use Chris@16: // base_reference(), above, to get direct access to m_iterator. Chris@101: // Chris@16: typename super_t::reference dereference() const Chris@16: { return *m_iterator; } Chris@16: Chris@16: template < Chris@16: class OtherDerived, class OtherIterator, class V, class C, class R, class D Chris@101: > Chris@16: bool equal(iterator_adaptor const& x) const Chris@16: { Chris@16: // Maybe readd with same_distance Chris@16: // BOOST_STATIC_ASSERT( Chris@16: // (detail::same_category_and_difference::value) Chris@16: // ); Chris@16: return m_iterator == x.base(); Chris@16: } Chris@16: Chris@16: typedef typename iterator_category_to_traversal< Chris@16: typename super_t::iterator_category Chris@16: >::type my_traversal; Chris@16: Chris@16: # define BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(cat) \ Chris@101: boost::iterators::detail::iterator_adaptor_assert_traversal(); Chris@16: Chris@16: void advance(typename super_t::difference_type n) Chris@16: { Chris@16: BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(random_access_traversal_tag) Chris@16: m_iterator += n; Chris@16: } Chris@101: Chris@16: void increment() { ++m_iterator; } Chris@16: Chris@101: void decrement() Chris@16: { Chris@16: BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(bidirectional_traversal_tag) Chris@16: --m_iterator; Chris@16: } Chris@16: Chris@16: template < Chris@16: class OtherDerived, class OtherIterator, class V, class C, class R, class D Chris@101: > Chris@16: typename super_t::difference_type distance_to( Chris@16: iterator_adaptor const& y) const Chris@16: { Chris@16: BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(random_access_traversal_tag) Chris@16: // Maybe readd with same_distance Chris@16: // BOOST_STATIC_ASSERT( Chris@16: // (detail::same_category_and_difference::value) Chris@16: // ); Chris@16: return y.base() - m_iterator; Chris@16: } Chris@16: Chris@16: # undef BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL Chris@101: Chris@16: private: // data members Chris@16: Base m_iterator; Chris@16: }; Chris@16: Chris@101: } // namespace iterators Chris@101: Chris@101: using iterators::iterator_adaptor; Chris@101: using iterators::enable_if_convertible; Chris@101: Chris@16: } // namespace boost Chris@16: Chris@16: #include Chris@16: Chris@16: #endif // BOOST_ITERATOR_ADAPTOR_23022003THW_HPP