iterator_facade.hpp

来自「CGAL is a collaborative effort of severa」· HPP 代码 · 共 879 行 · 第 1/2 页

HPP
879
字号
// (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_FACADE_23022003THW_HPP#define BOOST_ITERATOR_FACADE_23022003THW_HPP#include <boost/static_assert.hpp>#include <boost/iterator.hpp>#include <boost/iterator/interoperable.hpp>#include <boost/iterator/iterator_traits.hpp>#include <boost/iterator/detail/facade_iterator_category.hpp>#include <boost/iterator/detail/enable_if.hpp>#include <boost/type_traits/is_same.hpp>#include <boost/type_traits/add_const.hpp>#include <boost/type_traits/add_pointer.hpp>#include <boost/type_traits/remove_const.hpp>#include <boost/type_traits/remove_reference.hpp>#include <boost/type_traits/is_convertible.hpp>#include <boost/type_traits/is_pod.hpp>#include <boost/mpl/eval_if.hpp>#include <boost/mpl/if.hpp>#include <boost/mpl/or.hpp>#include <boost/mpl/and.hpp>#include <boost/mpl/not.hpp>#include <boost/mpl/always.hpp>#include <boost/mpl/apply.hpp>#include <boost/mpl/identity.hpp>#include <boost/iterator/detail/config_def.hpp> // this goes lastnamespace boost{  // This forward declaration is required for the friend declaration  // in iterator_core_access  template <class I, class V, class TC, class R, class D> class iterator_facade;  namespace detail  {    // A binary metafunction class that always returns bool.  VC6    // ICEs on mpl::always<bool>, probably because of the default    // parameters.    struct always_bool2    {        template <class T, class U>        struct apply        {            typedef bool type;        };    };    //    // enable if for use in operator implementation.    //    template <        class Facade1      , class Facade2      , class Return    >    struct enable_if_interoperable#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)    {        typedef typename mpl::if_<            mpl::or_<                is_convertible<Facade1, Facade2>              , is_convertible<Facade2, Facade1>            >          , Return          , int[3]        >::type type;    };        #else      : ::boost::iterators::enable_if<           mpl::or_<               is_convertible<Facade1, Facade2>             , is_convertible<Facade2, Facade1>           >         , Return        >    {};#endif     //    // Generates associated types for an iterator_facade with the    // given parameters.    //    template <        class ValueParam      , class CategoryOrTraversal      , class Reference       , class Difference    >    struct iterator_facade_types    {        typedef typename facade_iterator_category<            CategoryOrTraversal, ValueParam, Reference        >::type iterator_category;                typedef typename remove_const<ValueParam>::type value_type;                typedef typename mpl::eval_if<            detail::iterator_writability_disabled<ValueParam,Reference>          , add_pointer<typename add_const<value_type>::type>          , add_pointer<value_type>        >::type pointer;      # if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)                          \    && (BOOST_WORKAROUND(_STLPORT_VERSION, BOOST_TESTED_AT(0x452))              \        || BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, BOOST_TESTED_AT(310)))     \    || BOOST_WORKAROUND(BOOST_RWSTD_VER, BOOST_TESTED_AT(0x20101))              \    || BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, <= 310)        // To interoperate with some broken library/compiler        // combinations, user-defined iterators must be derived from        // std::iterator.  It is possible to implement a standard        // library for broken compilers without this limitation.#  define BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE 1        typedef           iterator<iterator_category, value_type, Difference, pointer, Reference>        base;# endif    };    // iterators whose dereference operators reference the same value    // for all iterators into the same sequence (like many input    // iterators) need help with their postfix ++: the referenced    // value must be read and stored away before the increment occurs    // so that *a++ yields the originally referenced element and not    // the next one.    template <class Iterator>    class postfix_increment_proxy    {        typedef typename iterator_value<Iterator>::type value_type;     public:        explicit postfix_increment_proxy(Iterator const& x)          : stored_value(*x)        {}        // Returning a mutable reference allows nonsense like        // (*r++).mutate(), but it imposes fewer assumptions about the        // behavior of the value_type.  In particular, recall taht        // (*r).mutate() is legal if operator* returns by value.        value_type&        operator*() const        {            return this->stored_value;        }     private:        mutable value_type stored_value;    };        //    // In general, we can't determine that such an iterator isn't    // writable -- we also need to store a copy of the old iterator so    // that it can be written into.    template <class Iterator>    class writable_postfix_increment_proxy    {        typedef typename iterator_value<Iterator>::type value_type;     public:        explicit writable_postfix_increment_proxy(Iterator const& x)          : stored_value(*x)          , stored_iterator(x)        {}        // Dereferencing must return a proxy so that both *r++ = o and        // value_type(*r++) can work.  In this case, *r is the same as        // *r++, and the conversion operator below is used to ensure        // readability.        writable_postfix_increment_proxy const&        operator*() const        {            return *this;        }        // Provides readability of *r++        operator value_type&() const        {            return stored_value;        }        // Provides writability of *r++        template <class T>        T const& operator=(T const& x) const        {            *this->stored_iterator = x;            return x;        }        // This overload just in case only non-const objects are writable        template <class T>        T& operator=(T& x) const        {            *this->stored_iterator = x;            return x;        }        // Provides X(r++)        operator Iterator const&() const        {            return stored_iterator;        }             private:        mutable value_type stored_value;        Iterator stored_iterator;    };# ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION    template <class Reference, class Value>    struct is_non_proxy_reference_impl    {        static Reference r;                template <class R>        static typename mpl::if_<            is_convertible<                R const volatile*              , Value const volatile*            >          , char[1]          , char[2]        >::type& helper(R const&);                BOOST_STATIC_CONSTANT(bool, value = sizeof(helper(r)) == 1);    };            template <class Reference, class Value>    struct is_non_proxy_reference      : mpl::bool_<            is_non_proxy_reference_impl<Reference, Value>::value        >    {};# else     template <class Reference, class Value>    struct is_non_proxy_reference      : is_convertible<            typename remove_reference<Reference>::type            const volatile*          , Value const volatile*        >    {};# endif             // A metafunction to choose the result type of postfix ++    //    // Because the C++98 input iterator requirements say that *r++ has    // type T (value_type), implementations of some standard    // algorithms like lexicographical_compare may use constructions    // like:    //    //          *r++ < *s++    //    // If *r++ returns a proxy (as required if r is writable but not    // multipass), this sort of expression will fail unless the proxy    // supports the operator<.  Since there are any number of such    // operations, we're not going to try to support them.  Therefore,    // even if r++ returns a proxy, *r++ will only return a proxy if    // *r also returns a proxy.    template <class Iterator, class Value, class Reference, class CategoryOrTraversal>    struct postfix_increment_result      : mpl::eval_if<            mpl::and_<            // A proxy is only needed for readable iterators            is_convertible<Reference,Value>                                // No multipass iterator can have values that disappear                // before positions can be re-visited              , mpl::not_<                    is_convertible<                        typename iterator_category_to_traversal<CategoryOrTraversal>::type                      , forward_traversal_tag                    >                >            >          , mpl::if_<                is_non_proxy_reference<Reference,Value>              , postfix_increment_proxy<Iterator>              , writable_postfix_increment_proxy<Iterator>            >          , mpl::identity<Iterator>        >    {};    // operator->() needs special support for input iterators to strictly meet the    // standard's requirements. If *i is not a reference type, we must still    // produce a (constant) lvalue to which a pointer can be formed. We do that by    // returning an instantiation of this special proxy class template.    template <class T>    struct operator_arrow_proxy    {        operator_arrow_proxy(T const* px) : m_value(*px) {}        const T* operator->() const { return &m_value; }        // This function is needed for MWCW and BCC, which won't call operator->        // again automatically per 13.3.1.2 para 8        operator const T*() const { return &m_value; }        T m_value;    };    // A metafunction that gets the result type for operator->.  Also    // has a static function make() which builds the result from a    // Reference    template <class ValueType, class Reference, class Pointer>    struct operator_arrow_result    {        // CWPro8.3 won't accept "operator_arrow_result::type", and we        // need that type below, so metafunction forwarding would be a        // losing proposition here.        typedef typename mpl::if_<            is_reference<Reference>          , Pointer          , operator_arrow_proxy<ValueType>        >::type type;        static type make(Reference x)        {            return type(&x);        }    };# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200)    // Deal with ETI    template<>    struct operator_arrow_result<int, int, int>    {        typedef int type;    };# endif    // A proxy return type for operator[], needed to deal with    // iterators that may invalidate referents upon destruction.    // Consider the temporary iterator in *(a + n)    template <class Iterator>    class operator_brackets_proxy    {        // Iterator is actually an iterator_facade, so we do not have to        // go through iterator_traits to access the traits.        typedef typename Iterator::reference  reference;        typedef typename Iterator::value_type value_type;     public:        operator_brackets_proxy(Iterator const& iter)          : m_iter(iter)        {}        operator reference() const        {            return *m_iter;        }        operator_brackets_proxy& operator=(value_type const& val)        {            *m_iter = val;            return *this;        }     private:        Iterator m_iter;    };    // A metafunction that determines whether operator[] must return a    // proxy, or whether it can simply return a copy of the value_type.    template <class ValueType, class Reference>    struct use_operator_brackets_proxy      : mpl::not_<            mpl::and_<                // Really we want an is_copy_constructible trait here,                // but is_POD will have to suffice in the meantime.                boost::is_POD<ValueType>              , iterator_writability_disabled<ValueType,Reference>            >        >    {};            template <class Iterator, class Value, class Reference>    struct operator_brackets_result    {        typedef typename mpl::if_<            use_operator_brackets_proxy<Value,Reference>          , operator_brackets_proxy<Iterator>          , Value        >::type type;    };    template <class Iterator>    operator_brackets_proxy<Iterator> make_operator_brackets_result(Iterator const& iter, mpl::true_)    {        return operator_brackets_proxy<Iterator>(iter);    }    template <class Iterator>    typename Iterator::value_type make_operator_brackets_result(Iterator const& iter, mpl::false_)    {      return *iter;    }    struct choose_difference_type    {        template <class I1, class I2>        struct apply          :# ifdef BOOST_NO_ONE_WAY_ITERATOR_INTEROP          iterator_difference<I1># elif BOOST_WORKAROUND(BOOST_MSVC, == 1200)          mpl::if_<              is_convertible<I2,I1>            , typename I1::difference_type            , typename I2::difference_type          ># else           mpl::eval_if<              is_convertible<I2,I1>            , iterator_difference<I1>            , iterator_difference<I2>          ># endif         {};    };  } // namespace detail  // Macros which describe the declarations of binary operators# ifdef BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY#  define BOOST_ITERATOR_FACADE_INTEROP_HEAD(prefix, op, result_type)   \    template <                                                          \        class Derived1, class V1, class TC1, class R1, class D1         \      , class Derived2, class V2, class TC2, class R2, class D2         \    >                                                                   \    prefix typename mpl::apply2<result_type,Derived1,Derived2>::type    \    operator op(                                                        \        iterator_facade<Derived1, V1, TC1, R1, D1> const& lhs           \

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?