|
@@ -0,0 +1,878 @@
|
|
|
+// (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/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/implicit_cast.hpp>
|
|
|
+#include <boost/static_assert.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 last
|
|
|
+
|
|
|
+namespace 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<
|
|
|
+ boost::detail::iterator_writability_disabled<ValueParam,Reference>
|
|
|
+ , add_pointer<const value_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 const&>
|
|
|
+
|
|
|
+ // 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 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) {}
|
|
|
+ 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 T*() const { return &m_value; }
|
|
|
+ mutable 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 implicit_cast<type>(&x);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+# if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
|
|
|
+ // 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, < 1300)
|
|
|
+ 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 Reference1, class Difference1 \
|
|
|
+ , class Derived2, class V2, class TC2, class Reference2, class Difference2 \
|
|
|
+ > \
|
|
|
+ prefix typename mpl::apply2<result_type,Derived1,Derived2>::type \
|
|
|
+ operator op( \
|
|
|
+ iterator_facade<Derived1, V1, TC1, Reference1, Difference1> const& lhs \
|
|
|
+ , iterator_facade<Derived2, V2, TC2, Reference2, Difference2> const& rhs)
|
|
|
+# else
|
|
|
+# define BOOST_ITERATOR_FACADE_INTEROP_HEAD(prefix, op, result_type) \
|
|
|
+ template < \
|
|
|
+ class Derived1, class V1, class TC1, class Reference1, class Difference1 \
|
|
|
+ , class Derived2, class V2, class TC2, class Reference2, class Difference2 \
|
|
|
+ > \
|
|
|
+ prefix typename boost::detail::enable_if_interoperable< \
|
|
|
+ Derived1, Derived2 \
|
|
|
+ , typename mpl::apply2<result_type,Derived1,Derived2>::type \
|
|
|
+ >::type \
|
|
|
+ operator op( \
|
|
|
+ iterator_facade<Derived1, V1, TC1, Reference1, Difference1> const& lhs \
|
|
|
+ , iterator_facade<Derived2, V2, TC2, Reference2, Difference2> const& rhs)
|
|
|
+# endif
|
|
|
+
|
|
|
+# define BOOST_ITERATOR_FACADE_PLUS_HEAD(prefix,args) \
|
|
|
+ template <class Derived, class V, class TC, class R, class D> \
|
|
|
+ prefix Derived operator+ args
|
|
|
+
|
|
|
+ //
|
|
|
+ // Helper class for granting access to the iterator core interface.
|
|
|
+ //
|
|
|
+ // The simple core interface is used by iterator_facade. The core
|
|
|
+ // interface of a user/library defined iterator type should not be made public
|
|
|
+ // so that it does not clutter the public interface. Instead iterator_core_access
|
|
|
+ // should be made friend so that iterator_facade can access the core
|
|
|
+ // interface through iterator_core_access.
|
|
|
+ //
|
|
|
+ class iterator_core_access
|
|
|
+ {
|
|
|
+# if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
|
|
|
+ // Tasteless as this may seem, making all members public allows member templates
|
|
|
+ // to work in the absence of member template friends.
|
|
|
+ public:
|
|
|
+# else
|
|
|
+
|
|
|
+ template <class I, class V, class TC, class R, class D> friend class iterator_facade;
|
|
|
+
|
|
|
+# define BOOST_ITERATOR_FACADE_RELATION(op) \
|
|
|
+ BOOST_ITERATOR_FACADE_INTEROP_HEAD(friend,op, boost::detail::always_bool2);
|
|
|
+
|
|
|
+ BOOST_ITERATOR_FACADE_RELATION(==)
|
|
|
+ BOOST_ITERATOR_FACADE_RELATION(!=)
|
|
|
+
|
|
|
+ BOOST_ITERATOR_FACADE_RELATION(<)
|
|
|
+ BOOST_ITERATOR_FACADE_RELATION(>)
|
|
|
+ BOOST_ITERATOR_FACADE_RELATION(<=)
|
|
|
+ BOOST_ITERATOR_FACADE_RELATION(>=)
|
|
|
+# undef BOOST_ITERATOR_FACADE_RELATION
|
|
|
+
|
|
|
+ BOOST_ITERATOR_FACADE_INTEROP_HEAD(
|
|
|
+ friend, -, boost::detail::choose_difference_type)
|
|
|
+ ;
|
|
|
+
|
|
|
+ BOOST_ITERATOR_FACADE_PLUS_HEAD(
|
|
|
+ friend inline
|
|
|
+ , (iterator_facade<Derived, V, TC, R, D> const&
|
|
|
+ , typename Derived::difference_type)
|
|
|
+ )
|
|
|
+ ;
|
|
|
+
|
|
|
+ BOOST_ITERATOR_FACADE_PLUS_HEAD(
|
|
|
+ friend inline
|
|
|
+ , (typename Derived::difference_type
|
|
|
+ , iterator_facade<Derived, V, TC, R, D> const&)
|
|
|
+ )
|
|
|
+ ;
|
|
|
+
|
|
|
+# endif
|
|
|
+
|
|
|
+ template <class Facade>
|
|
|
+ static typename Facade::reference dereference(Facade const& f)
|
|
|
+ {
|
|
|
+ return f.dereference();
|
|
|
+ }
|
|
|
+
|
|
|
+ template <class Facade>
|
|
|
+ static void increment(Facade& f)
|
|
|
+ {
|
|
|
+ f.increment();
|
|
|
+ }
|
|
|
+
|
|
|
+ template <class Facade>
|
|
|
+ static void decrement(Facade& f)
|
|
|
+ {
|
|
|
+ f.decrement();
|
|
|
+ }
|
|
|
+
|
|
|
+ template <class Facade1, class Facade2>
|
|
|
+ static bool equal(Facade1 const& f1, Facade2 const& f2, mpl::true_)
|
|
|
+ {
|
|
|
+ return f1.equal(f2);
|
|
|
+ }
|
|
|
+
|
|
|
+ template <class Facade1, class Facade2>
|
|
|
+ static bool equal(Facade1 const& f1, Facade2 const& f2, mpl::false_)
|
|
|
+ {
|
|
|
+ return f2.equal(f1);
|
|
|
+ }
|
|
|
+
|
|
|
+ template <class Facade>
|
|
|
+ static void advance(Facade& f, typename Facade::difference_type n)
|
|
|
+ {
|
|
|
+ f.advance(n);
|
|
|
+ }
|
|
|
+
|
|
|
+ template <class Facade1, class Facade2>
|
|
|
+ static typename Facade1::difference_type distance_from(
|
|
|
+ Facade1 const& f1, Facade2 const& f2, mpl::true_)
|
|
|
+ {
|
|
|
+ return -f1.distance_to(f2);
|
|
|
+ }
|
|
|
+
|
|
|
+ template <class Facade1, class Facade2>
|
|
|
+ static typename Facade2::difference_type distance_from(
|
|
|
+ Facade1 const& f1, Facade2 const& f2, mpl::false_)
|
|
|
+ {
|
|
|
+ return f2.distance_to(f1);
|
|
|
+ }
|
|
|
+
|
|
|
+ //
|
|
|
+ // Curiously Recurring Template interface.
|
|
|
+ //
|
|
|
+ template <class I, class V, class TC, class R, class D>
|
|
|
+ static I& derived(iterator_facade<I,V,TC,R,D>& facade)
|
|
|
+ {
|
|
|
+ return *static_cast<I*>(&facade);
|
|
|
+ }
|
|
|
+
|
|
|
+ template <class I, class V, class TC, class R, class D>
|
|
|
+ static I const& derived(iterator_facade<I,V,TC,R,D> const& facade)
|
|
|
+ {
|
|
|
+ return *static_cast<I const*>(&facade);
|
|
|
+ }
|
|
|
+
|
|
|
+ private:
|
|
|
+ // objects of this class are useless
|
|
|
+ iterator_core_access(); //undefined
|
|
|
+ };
|
|
|
+
|
|
|
+ //
|
|
|
+ // iterator_facade - use as a public base class for defining new
|
|
|
+ // standard-conforming iterators.
|
|
|
+ //
|
|
|
+ template <
|
|
|
+ class Derived // The derived iterator type being constructed
|
|
|
+ , class Value
|
|
|
+ , class CategoryOrTraversal
|
|
|
+ , class Reference = Value&
|
|
|
+ , class Difference = std::ptrdiff_t
|
|
|
+ >
|
|
|
+ class iterator_facade
|
|
|
+# ifdef BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE
|
|
|
+ : public boost::detail::iterator_facade_types<
|
|
|
+ Value, CategoryOrTraversal, Reference, Difference
|
|
|
+ >::base
|
|
|
+# undef BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE
|
|
|
+# endif
|
|
|
+ {
|
|
|
+ private:
|
|
|
+ //
|
|
|
+ // Curiously Recurring Template interface.
|
|
|
+ //
|
|
|
+ Derived& derived()
|
|
|
+ {
|
|
|
+ return *static_cast<Derived*>(this);
|
|
|
+ }
|
|
|
+
|
|
|
+ Derived const& derived() const
|
|
|
+ {
|
|
|
+ return *static_cast<Derived const*>(this);
|
|
|
+ }
|
|
|
+
|
|
|
+ typedef boost::detail::iterator_facade_types<
|
|
|
+ Value, CategoryOrTraversal, Reference, Difference
|
|
|
+ > associated_types;
|
|
|
+
|
|
|
+ protected:
|
|
|
+ // For use by derived classes
|
|
|
+ typedef iterator_facade<Derived,Value,CategoryOrTraversal,Reference,Difference> iterator_facade_;
|
|
|
+
|
|
|
+ public:
|
|
|
+
|
|
|
+ typedef typename associated_types::value_type value_type;
|
|
|
+ typedef Reference reference;
|
|
|
+ typedef Difference difference_type;
|
|
|
+ typedef typename associated_types::pointer pointer;
|
|
|
+ typedef typename associated_types::iterator_category iterator_category;
|
|
|
+
|
|
|
+ reference operator*() const
|
|
|
+ {
|
|
|
+ return iterator_core_access::dereference(this->derived());
|
|
|
+ }
|
|
|
+
|
|
|
+ typename boost::detail::operator_arrow_result<
|
|
|
+ value_type
|
|
|
+ , reference
|
|
|
+ , pointer
|
|
|
+ >::type
|
|
|
+ operator->() const
|
|
|
+ {
|
|
|
+ return boost::detail::operator_arrow_result<
|
|
|
+ value_type
|
|
|
+ , reference
|
|
|
+ , pointer
|
|
|
+ >::make(*this->derived());
|
|
|
+ }
|
|
|
+
|
|
|
+ typename boost::detail::operator_brackets_result<Derived,Value,reference>::type
|
|
|
+ operator[](difference_type n) const
|
|
|
+ {
|
|
|
+ typedef boost::detail::use_operator_brackets_proxy<Value,Reference> use_proxy;
|
|
|
+
|
|
|
+ return boost::detail::make_operator_brackets_result<Derived>(
|
|
|
+ this->derived() + n
|
|
|
+ , use_proxy()
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ Derived& operator++()
|
|
|
+ {
|
|
|
+ iterator_core_access::increment(this->derived());
|
|
|
+ return this->derived();
|
|
|
+ }
|
|
|
+
|
|
|
+# if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
|
|
|
+ typename boost::detail::postfix_increment_result<Derived,Value,Reference,CategoryOrTraversal>::type
|
|
|
+ operator++(int)
|
|
|
+ {
|
|
|
+ typename boost::detail::postfix_increment_result<Derived,Value,Reference,CategoryOrTraversal>::type
|
|
|
+ tmp(this->derived());
|
|
|
+ ++*this;
|
|
|
+ return tmp;
|
|
|
+ }
|
|
|
+# endif
|
|
|
+
|
|
|
+ Derived& operator--()
|
|
|
+ {
|
|
|
+ iterator_core_access::decrement(this->derived());
|
|
|
+ return this->derived();
|
|
|
+ }
|
|
|
+
|
|
|
+ Derived operator--(int)
|
|
|
+ {
|
|
|
+ Derived tmp(this->derived());
|
|
|
+ --*this;
|
|
|
+ return tmp;
|
|
|
+ }
|
|
|
+
|
|
|
+ Derived& operator+=(difference_type n)
|
|
|
+ {
|
|
|
+ iterator_core_access::advance(this->derived(), n);
|
|
|
+ return this->derived();
|
|
|
+ }
|
|
|
+
|
|
|
+ Derived& operator-=(difference_type n)
|
|
|
+ {
|
|
|
+ iterator_core_access::advance(this->derived(), -n);
|
|
|
+ return this->derived();
|
|
|
+ }
|
|
|
+
|
|
|
+ Derived operator-(difference_type x) const
|
|
|
+ {
|
|
|
+ Derived result(this->derived());
|
|
|
+ return result -= x;
|
|
|
+ }
|
|
|
+
|
|
|
+# if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
|
|
|
+ // There appears to be a bug which trashes the data of classes
|
|
|
+ // derived from iterator_facade when they are assigned unless we
|
|
|
+ // define this assignment operator. This bug is only revealed
|
|
|
+ // (so far) in STLPort debug mode, but it's clearly a codegen
|
|
|
+ // problem so we apply the workaround for all MSVC6.
|
|
|
+ iterator_facade& operator=(iterator_facade const&)
|
|
|
+ {
|
|
|
+ return *this;
|
|
|
+ }
|
|
|
+# endif
|
|
|
+ };
|
|
|
+
|
|
|
+# if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
|
|
|
+ template <class I, class V, class TC, class R, class D>
|
|
|
+ inline typename boost::detail::postfix_increment_result<I,V,R,TC>::type
|
|
|
+ operator++(
|
|
|
+ iterator_facade<I,V,TC,R,D>& i
|
|
|
+ , int
|
|
|
+ )
|
|
|
+ {
|
|
|
+ typename boost::detail::postfix_increment_result<I,V,R,TC>::type
|
|
|
+ tmp(*static_cast<I*>(&i));
|
|
|
+
|
|
|
+ ++i;
|
|
|
+
|
|
|
+ return tmp;
|
|
|
+ }
|
|
|
+# endif
|
|
|
+
|
|
|
+
|
|
|
+ //
|
|
|
+ // Comparison operator implementation. The library supplied operators
|
|
|
+ // enables the user to provide fully interoperable constant/mutable
|
|
|
+ // iterator types. I.e. the library provides all operators
|
|
|
+ // for all mutable/constant iterator combinations.
|
|
|
+ //
|
|
|
+ // Note though that this kind of interoperability for constant/mutable
|
|
|
+ // iterators is not required by the standard for container iterators.
|
|
|
+ // All the standard asks for is a conversion mutable -> constant.
|
|
|
+ // Most standard library implementations nowadays provide fully interoperable
|
|
|
+ // iterator implementations, but there are still heavily used implementations
|
|
|
+ // that do not provide them. (Actually it's even worse, they do not provide
|
|
|
+ // them for only a few iterators.)
|
|
|
+ //
|
|
|
+ // ?? Maybe a BOOST_ITERATOR_NO_FULL_INTEROPERABILITY macro should
|
|
|
+ // enable the user to turn off mixed type operators
|
|
|
+ //
|
|
|
+ // The library takes care to provide only the right operator overloads.
|
|
|
+ // I.e.
|
|
|
+ //
|
|
|
+ // bool operator==(Iterator, Iterator);
|
|
|
+ // bool operator==(ConstIterator, Iterator);
|
|
|
+ // bool operator==(Iterator, ConstIterator);
|
|
|
+ // bool operator==(ConstIterator, ConstIterator);
|
|
|
+ //
|
|
|
+ // ...
|
|
|
+ //
|
|
|
+ // In order to do so it uses c++ idioms that are not yet widely supported
|
|
|
+ // by current compiler releases. The library is designed to degrade gracefully
|
|
|
+ // in the face of compiler deficiencies. In general compiler
|
|
|
+ // deficiencies result in less strict error checking and more obscure
|
|
|
+ // error messages, functionality is not affected.
|
|
|
+ //
|
|
|
+ // For full operation compiler support for "Substitution Failure Is Not An Error"
|
|
|
+ // (aka. enable_if) and boost::is_convertible is required.
|
|
|
+ //
|
|
|
+ // The following problems occur if support is lacking.
|
|
|
+ //
|
|
|
+ // Pseudo code
|
|
|
+ //
|
|
|
+ // ---------------
|
|
|
+ // AdaptorA<Iterator1> a1;
|
|
|
+ // AdaptorA<Iterator2> a2;
|
|
|
+ //
|
|
|
+ // // This will result in a no such overload error in full operation
|
|
|
+ // // If enable_if or is_convertible is not supported
|
|
|
+ // // The instantiation will fail with an error hopefully indicating that
|
|
|
+ // // there is no operator== for Iterator1, Iterator2
|
|
|
+ // // The same will happen if no enable_if is used to remove
|
|
|
+ // // false overloads from the templated conversion constructor
|
|
|
+ // // of AdaptorA.
|
|
|
+ //
|
|
|
+ // a1 == a2;
|
|
|
+ // ----------------
|
|
|
+ //
|
|
|
+ // AdaptorA<Iterator> a;
|
|
|
+ // AdaptorB<Iterator> b;
|
|
|
+ //
|
|
|
+ // // This will result in a no such overload error in full operation
|
|
|
+ // // If enable_if is not supported the static assert used
|
|
|
+ // // in the operator implementation will fail.
|
|
|
+ // // This will accidently work if is_convertible is not supported.
|
|
|
+ //
|
|
|
+ // a == b;
|
|
|
+ // ----------------
|
|
|
+ //
|
|
|
+
|
|
|
+# ifdef BOOST_NO_ONE_WAY_ITERATOR_INTEROP
|
|
|
+# define BOOST_ITERATOR_CONVERTIBLE(a,b) mpl::true_()
|
|
|
+# else
|
|
|
+# define BOOST_ITERATOR_CONVERTIBLE(a,b) is_convertible<a,b>()
|
|
|
+# endif
|
|
|
+
|
|
|
+# define BOOST_ITERATOR_FACADE_INTEROP(op, result_type, return_prefix, base_op) \
|
|
|
+ BOOST_ITERATOR_FACADE_INTEROP_HEAD(inline, op, result_type) \
|
|
|
+ { \
|
|
|
+ /* For those compilers that do not support enable_if */ \
|
|
|
+ BOOST_STATIC_ASSERT(( \
|
|
|
+ is_interoperable< Derived1, Derived2 >::value \
|
|
|
+ )); \
|
|
|
+ return_prefix iterator_core_access::base_op( \
|
|
|
+ *static_cast<Derived1 const*>(&lhs) \
|
|
|
+ , *static_cast<Derived2 const*>(&rhs) \
|
|
|
+ , BOOST_ITERATOR_CONVERTIBLE(Derived2,Derived1) \
|
|
|
+ ); \
|
|
|
+ }
|
|
|
+
|
|
|
+# define BOOST_ITERATOR_FACADE_RELATION(op, return_prefix, base_op) \
|
|
|
+ BOOST_ITERATOR_FACADE_INTEROP( \
|
|
|
+ op \
|
|
|
+ , boost::detail::always_bool2 \
|
|
|
+ , return_prefix \
|
|
|
+ , base_op \
|
|
|
+ )
|
|
|
+
|
|
|
+ BOOST_ITERATOR_FACADE_RELATION(==, return, equal)
|
|
|
+ BOOST_ITERATOR_FACADE_RELATION(!=, return !, equal)
|
|
|
+
|
|
|
+ BOOST_ITERATOR_FACADE_RELATION(<, return 0 >, distance_from)
|
|
|
+ BOOST_ITERATOR_FACADE_RELATION(>, return 0 <, distance_from)
|
|
|
+ BOOST_ITERATOR_FACADE_RELATION(<=, return 0 >=, distance_from)
|
|
|
+ BOOST_ITERATOR_FACADE_RELATION(>=, return 0 <=, distance_from)
|
|
|
+# undef BOOST_ITERATOR_FACADE_RELATION
|
|
|
+
|
|
|
+ // operator- requires an additional part in the static assertion
|
|
|
+ BOOST_ITERATOR_FACADE_INTEROP(
|
|
|
+ -
|
|
|
+ , boost::detail::choose_difference_type
|
|
|
+ , return
|
|
|
+ , distance_from
|
|
|
+ )
|
|
|
+# undef BOOST_ITERATOR_FACADE_INTEROP
|
|
|
+# undef BOOST_ITERATOR_FACADE_INTEROP_HEAD
|
|
|
+
|
|
|
+# define BOOST_ITERATOR_FACADE_PLUS(args) \
|
|
|
+ BOOST_ITERATOR_FACADE_PLUS_HEAD(inline, args) \
|
|
|
+ { \
|
|
|
+ Derived tmp(static_cast<Derived const&>(i)); \
|
|
|
+ return tmp += n; \
|
|
|
+ }
|
|
|
+
|
|
|
+BOOST_ITERATOR_FACADE_PLUS((
|
|
|
+ iterator_facade<Derived, V, TC, R, D> const& i
|
|
|
+ , typename Derived::difference_type n
|
|
|
+))
|
|
|
+
|
|
|
+BOOST_ITERATOR_FACADE_PLUS((
|
|
|
+ typename Derived::difference_type n
|
|
|
+ , iterator_facade<Derived, V, TC, R, D> const& i
|
|
|
+))
|
|
|
+# undef BOOST_ITERATOR_FACADE_PLUS
|
|
|
+# undef BOOST_ITERATOR_FACADE_PLUS_HEAD
|
|
|
+
|
|
|
+} // namespace boost
|
|
|
+
|
|
|
+#include <boost/iterator/detail/config_undef.hpp>
|
|
|
+
|
|
|
+#endif // BOOST_ITERATOR_FACADE_23022003THW_HPP
|