You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
878 lines
28 KiB
878 lines
28 KiB
// (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; |
|
|
|
// Not the real associated pointer 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 boost::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; |
|
|
|
typedef boost::detail::operator_arrow_result< |
|
typename associated_types::value_type |
|
, Reference |
|
, typename associated_types::pointer |
|
> pointer_; |
|
|
|
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 pointer_::type pointer; |
|
|
|
typedef typename associated_types::iterator_category iterator_category; |
|
|
|
reference operator*() const |
|
{ |
|
return iterator_core_access::dereference(this->derived()); |
|
} |
|
|
|
pointer operator->() const |
|
{ |
|
return 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
|
|
|