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