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.
365 lines
11 KiB
365 lines
11 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_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> |
|
#endif |
|
|
|
#include <boost/type_traits/add_reference.hpp> |
|
#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
|
|
|