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 + -
显示快捷键?