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