510 lines
16 KiB
Plaintext
510 lines
16 KiB
Plaintext
// (C) Copyright Jeremy Siek 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_ARCHETYPES_HPP
|
|
#define BOOST_ITERATOR_ARCHETYPES_HPP
|
|
|
|
#include <boost/iterator/iterator_categories.hpp>
|
|
#include <boost/operators.hpp>
|
|
#include <boost/static_assert.hpp>
|
|
#include <boost/iterator.hpp>
|
|
|
|
#include <boost/iterator/detail/facade_iterator_category.hpp>
|
|
|
|
#include <boost/type_traits/is_const.hpp>
|
|
#include <boost/type_traits/add_const.hpp>
|
|
#include <boost/type_traits/remove_const.hpp>
|
|
#include <boost/type_traits/remove_cv.hpp>
|
|
|
|
#include <boost/concept_archetype.hpp>
|
|
|
|
#include <boost/mpl/bitand.hpp>
|
|
#include <boost/mpl/int.hpp>
|
|
#include <boost/mpl/equal_to.hpp>
|
|
#include <boost/mpl/if.hpp>
|
|
#include <boost/mpl/eval_if.hpp>
|
|
#include <boost/mpl/and.hpp>
|
|
#include <boost/mpl/identity.hpp>
|
|
|
|
#include <cstddef>
|
|
|
|
namespace boost {
|
|
namespace iterators {
|
|
|
|
template <class Value, class AccessCategory>
|
|
struct access_archetype;
|
|
|
|
template <class Derived, class Value, class AccessCategory, class TraversalCategory>
|
|
struct traversal_archetype;
|
|
|
|
namespace archetypes
|
|
{
|
|
enum {
|
|
readable_iterator_bit = 1
|
|
, writable_iterator_bit = 2
|
|
, swappable_iterator_bit = 4
|
|
, lvalue_iterator_bit = 8
|
|
};
|
|
|
|
// Not quite tags, since dispatching wouldn't work.
|
|
typedef mpl::int_<readable_iterator_bit>::type readable_iterator_t;
|
|
typedef mpl::int_<writable_iterator_bit>::type writable_iterator_t;
|
|
|
|
typedef mpl::int_<
|
|
(readable_iterator_bit|writable_iterator_bit)
|
|
>::type readable_writable_iterator_t;
|
|
|
|
typedef mpl::int_<
|
|
(readable_iterator_bit|lvalue_iterator_bit)
|
|
>::type readable_lvalue_iterator_t;
|
|
|
|
typedef mpl::int_<
|
|
(lvalue_iterator_bit|writable_iterator_bit)
|
|
>::type writable_lvalue_iterator_t;
|
|
|
|
typedef mpl::int_<swappable_iterator_bit>::type swappable_iterator_t;
|
|
typedef mpl::int_<lvalue_iterator_bit>::type lvalue_iterator_t;
|
|
|
|
template <class Derived, class Base>
|
|
struct has_access
|
|
: mpl::equal_to<
|
|
mpl::bitand_<Derived,Base>
|
|
, Base
|
|
>
|
|
{};
|
|
}
|
|
|
|
namespace detail
|
|
{
|
|
template <class T>
|
|
struct assign_proxy
|
|
{
|
|
assign_proxy& operator=(T) { return *this; }
|
|
};
|
|
|
|
template <class T>
|
|
struct read_proxy
|
|
{
|
|
operator T() { return static_object<T>::get(); }
|
|
};
|
|
|
|
template <class T>
|
|
struct read_write_proxy
|
|
: read_proxy<T> // Use to inherit from assign_proxy, but that doesn't work. -JGS
|
|
{
|
|
read_write_proxy& operator=(T) { return *this; }
|
|
};
|
|
|
|
template <class T>
|
|
struct arrow_proxy
|
|
{
|
|
T const* operator->() const { return 0; }
|
|
};
|
|
|
|
struct no_operator_brackets {};
|
|
|
|
template <class ValueType>
|
|
struct readable_operator_brackets
|
|
{
|
|
read_proxy<ValueType> operator[](std::ptrdiff_t n) const { return read_proxy<ValueType>(); }
|
|
};
|
|
|
|
template <class ValueType>
|
|
struct writable_operator_brackets
|
|
{
|
|
read_write_proxy<ValueType> operator[](std::ptrdiff_t n) const { return read_write_proxy<ValueType>(); }
|
|
};
|
|
|
|
template <class Value, class AccessCategory, class TraversalCategory>
|
|
struct operator_brackets
|
|
: mpl::eval_if<
|
|
is_convertible<TraversalCategory, random_access_traversal_tag>
|
|
, mpl::eval_if<
|
|
archetypes::has_access<
|
|
AccessCategory
|
|
, archetypes::writable_iterator_t
|
|
>
|
|
, mpl::identity<writable_operator_brackets<Value> >
|
|
, mpl::if_<
|
|
archetypes::has_access<
|
|
AccessCategory
|
|
, archetypes::readable_iterator_t
|
|
>
|
|
, readable_operator_brackets<Value>
|
|
, no_operator_brackets
|
|
>
|
|
>
|
|
, mpl::identity<no_operator_brackets>
|
|
>::type
|
|
{};
|
|
|
|
template <class TraversalCategory>
|
|
struct traversal_archetype_impl
|
|
{
|
|
template <class Derived,class Value> struct archetype;
|
|
};
|
|
|
|
// Constructor argument for those iterators that
|
|
// are not default constructible
|
|
struct ctor_arg {};
|
|
|
|
template <class Derived, class Value, class TraversalCategory>
|
|
struct traversal_archetype_
|
|
: traversal_archetype_impl<TraversalCategory>::template archetype<Derived,Value>
|
|
{
|
|
typedef typename
|
|
traversal_archetype_impl<TraversalCategory>::template archetype<Derived,Value>
|
|
base;
|
|
|
|
traversal_archetype_() {}
|
|
|
|
traversal_archetype_(ctor_arg arg)
|
|
: base(arg)
|
|
{}
|
|
};
|
|
|
|
template <>
|
|
struct traversal_archetype_impl<incrementable_traversal_tag>
|
|
{
|
|
template<class Derived, class Value>
|
|
struct archetype
|
|
{
|
|
explicit archetype(ctor_arg) {}
|
|
|
|
struct bogus { }; // This use to be void, but that causes trouble for iterator_facade. Need more research. -JGS
|
|
typedef bogus difference_type;
|
|
|
|
Derived& operator++() { return (Derived&)static_object<Derived>::get(); }
|
|
Derived operator++(int) const { return (Derived&)static_object<Derived>::get(); }
|
|
};
|
|
};
|
|
|
|
template <>
|
|
struct traversal_archetype_impl<single_pass_traversal_tag>
|
|
{
|
|
template<class Derived, class Value>
|
|
struct archetype
|
|
: public equality_comparable< traversal_archetype_<Derived, Value, single_pass_traversal_tag> >,
|
|
public traversal_archetype_<Derived, Value, incrementable_traversal_tag>
|
|
{
|
|
explicit archetype(ctor_arg arg)
|
|
: traversal_archetype_<Derived, Value, incrementable_traversal_tag>(arg)
|
|
{}
|
|
|
|
typedef std::ptrdiff_t difference_type;
|
|
};
|
|
};
|
|
|
|
template <class Derived, class Value>
|
|
bool operator==(traversal_archetype_<Derived, Value, single_pass_traversal_tag> const&,
|
|
traversal_archetype_<Derived, Value, single_pass_traversal_tag> const&) { return true; }
|
|
|
|
template <>
|
|
struct traversal_archetype_impl<forward_traversal_tag>
|
|
{
|
|
template<class Derived, class Value>
|
|
struct archetype
|
|
: public traversal_archetype_<Derived, Value, single_pass_traversal_tag>
|
|
{
|
|
archetype()
|
|
: traversal_archetype_<Derived, Value, single_pass_traversal_tag>(ctor_arg())
|
|
{}
|
|
};
|
|
};
|
|
|
|
template <>
|
|
struct traversal_archetype_impl<bidirectional_traversal_tag>
|
|
{
|
|
template<class Derived, class Value>
|
|
struct archetype
|
|
: public traversal_archetype_<Derived, Value, forward_traversal_tag>
|
|
{
|
|
Derived& operator--() { return static_object<Derived>::get(); }
|
|
Derived operator--(int) const { return static_object<Derived>::get(); }
|
|
};
|
|
};
|
|
|
|
template <>
|
|
struct traversal_archetype_impl<random_access_traversal_tag>
|
|
{
|
|
template<class Derived, class Value>
|
|
struct archetype
|
|
: public traversal_archetype_<Derived, Value, bidirectional_traversal_tag>
|
|
{
|
|
Derived& operator+=(std::ptrdiff_t) { return static_object<Derived>::get(); }
|
|
Derived& operator-=(std::ptrdiff_t) { return static_object<Derived>::get(); }
|
|
};
|
|
};
|
|
|
|
template <class Derived, class Value>
|
|
Derived& operator+(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
|
|
std::ptrdiff_t) { return static_object<Derived>::get(); }
|
|
|
|
template <class Derived, class Value>
|
|
Derived& operator+(std::ptrdiff_t,
|
|
traversal_archetype_<Derived, Value, random_access_traversal_tag> const&)
|
|
{ return static_object<Derived>::get(); }
|
|
|
|
template <class Derived, class Value>
|
|
Derived& operator-(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
|
|
std::ptrdiff_t)
|
|
{ return static_object<Derived>::get(); }
|
|
|
|
template <class Derived, class Value>
|
|
std::ptrdiff_t operator-(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
|
|
traversal_archetype_<Derived, Value, random_access_traversal_tag> const&)
|
|
{ return 0; }
|
|
|
|
template <class Derived, class Value>
|
|
bool operator<(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
|
|
traversal_archetype_<Derived, Value, random_access_traversal_tag> const&)
|
|
{ return true; }
|
|
|
|
template <class Derived, class Value>
|
|
bool operator>(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
|
|
traversal_archetype_<Derived, Value, random_access_traversal_tag> const&)
|
|
{ return true; }
|
|
|
|
template <class Derived, class Value>
|
|
bool operator<=(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
|
|
traversal_archetype_<Derived, Value, random_access_traversal_tag> const&)
|
|
{ return true; }
|
|
|
|
template <class Derived, class Value>
|
|
bool operator>=(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
|
|
traversal_archetype_<Derived, Value, random_access_traversal_tag> const&)
|
|
{ return true; }
|
|
|
|
struct bogus_type;
|
|
|
|
template <class Value>
|
|
struct convertible_type
|
|
: mpl::if_< is_const<Value>,
|
|
typename remove_const<Value>::type,
|
|
bogus_type >
|
|
{};
|
|
|
|
} // namespace detail
|
|
|
|
|
|
template <class> struct undefined;
|
|
|
|
template <class AccessCategory>
|
|
struct iterator_access_archetype_impl
|
|
{
|
|
template <class Value> struct archetype;
|
|
};
|
|
|
|
template <class Value, class AccessCategory>
|
|
struct iterator_access_archetype
|
|
: iterator_access_archetype_impl<
|
|
AccessCategory
|
|
>::template archetype<Value>
|
|
{
|
|
};
|
|
|
|
template <>
|
|
struct iterator_access_archetype_impl<
|
|
archetypes::readable_iterator_t
|
|
>
|
|
{
|
|
template <class Value>
|
|
struct archetype
|
|
{
|
|
typedef typename remove_cv<Value>::type value_type;
|
|
typedef Value reference;
|
|
typedef Value* pointer;
|
|
|
|
value_type operator*() const { return static_object<value_type>::get(); }
|
|
|
|
detail::arrow_proxy<Value> operator->() const { return detail::arrow_proxy<Value>(); }
|
|
};
|
|
};
|
|
|
|
template <>
|
|
struct iterator_access_archetype_impl<
|
|
archetypes::writable_iterator_t
|
|
>
|
|
{
|
|
template <class Value>
|
|
struct archetype
|
|
{
|
|
BOOST_STATIC_ASSERT(!is_const<Value>::value);
|
|
typedef void value_type;
|
|
typedef void reference;
|
|
typedef void pointer;
|
|
|
|
detail::assign_proxy<Value> operator*() const { return detail::assign_proxy<Value>(); }
|
|
};
|
|
};
|
|
|
|
template <>
|
|
struct iterator_access_archetype_impl<
|
|
archetypes::readable_writable_iterator_t
|
|
>
|
|
{
|
|
template <class Value>
|
|
struct archetype
|
|
: public virtual iterator_access_archetype<
|
|
Value, archetypes::readable_iterator_t
|
|
>
|
|
{
|
|
typedef detail::read_write_proxy<Value> reference;
|
|
|
|
detail::read_write_proxy<Value> operator*() const { return detail::read_write_proxy<Value>(); }
|
|
};
|
|
};
|
|
|
|
template <>
|
|
struct iterator_access_archetype_impl<archetypes::readable_lvalue_iterator_t>
|
|
{
|
|
template <class Value>
|
|
struct archetype
|
|
: public virtual iterator_access_archetype<
|
|
Value, archetypes::readable_iterator_t
|
|
>
|
|
{
|
|
typedef Value& reference;
|
|
|
|
Value& operator*() const { return static_object<Value>::get(); }
|
|
Value* operator->() const { return 0; }
|
|
};
|
|
};
|
|
|
|
template <>
|
|
struct iterator_access_archetype_impl<archetypes::writable_lvalue_iterator_t>
|
|
{
|
|
template <class Value>
|
|
struct archetype
|
|
: public virtual iterator_access_archetype<
|
|
Value, archetypes::readable_lvalue_iterator_t
|
|
>
|
|
{
|
|
BOOST_STATIC_ASSERT((!is_const<Value>::value));
|
|
};
|
|
};
|
|
|
|
|
|
template <class Value, class AccessCategory, class TraversalCategory>
|
|
struct iterator_archetype;
|
|
|
|
template <class Value, class AccessCategory, class TraversalCategory>
|
|
struct traversal_archetype_base
|
|
: detail::operator_brackets<
|
|
typename remove_cv<Value>::type
|
|
, AccessCategory
|
|
, TraversalCategory
|
|
>
|
|
, detail::traversal_archetype_<
|
|
iterator_archetype<Value, AccessCategory, TraversalCategory>
|
|
, Value
|
|
, TraversalCategory
|
|
>
|
|
{
|
|
};
|
|
|
|
namespace detail
|
|
{
|
|
template <class Value, class AccessCategory, class TraversalCategory>
|
|
struct iterator_archetype_base
|
|
: iterator_access_archetype<Value, AccessCategory>
|
|
, traversal_archetype_base<Value, AccessCategory, TraversalCategory>
|
|
{
|
|
typedef iterator_access_archetype<Value, AccessCategory> access;
|
|
|
|
typedef typename detail::facade_iterator_category<
|
|
TraversalCategory
|
|
, typename mpl::eval_if<
|
|
archetypes::has_access<
|
|
AccessCategory, archetypes::writable_iterator_t
|
|
>
|
|
, remove_const<Value>
|
|
, add_const<Value>
|
|
>::type
|
|
, typename access::reference
|
|
>::type iterator_category;
|
|
|
|
// Needed for some broken libraries (see below)
|
|
typedef boost::iterator<
|
|
iterator_category
|
|
, Value
|
|
, typename traversal_archetype_base<
|
|
Value, AccessCategory, TraversalCategory
|
|
>::difference_type
|
|
, typename access::pointer
|
|
, typename access::reference
|
|
> workaround_iterator_base;
|
|
};
|
|
}
|
|
|
|
template <class Value, class AccessCategory, class TraversalCategory>
|
|
struct iterator_archetype
|
|
: public detail::iterator_archetype_base<Value, AccessCategory, TraversalCategory>
|
|
|
|
// These broken libraries require derivation from std::iterator
|
|
// (or related magic) in order to handle iter_swap and other
|
|
// iterator operations
|
|
# if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, < 310) \
|
|
|| BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(0x20101))
|
|
, public detail::iterator_archetype_base<
|
|
Value, AccessCategory, TraversalCategory
|
|
>::workaround_iterator_base
|
|
# endif
|
|
{
|
|
// Derivation from std::iterator above caused references to nested
|
|
// types to be ambiguous, so now we have to redeclare them all
|
|
// here.
|
|
# if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, < 310) \
|
|
|| BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(0x20101))
|
|
|
|
typedef detail::iterator_archetype_base<
|
|
Value,AccessCategory,TraversalCategory
|
|
> base;
|
|
|
|
typedef typename base::value_type value_type;
|
|
typedef typename base::reference reference;
|
|
typedef typename base::pointer pointer;
|
|
typedef typename base::difference_type difference_type;
|
|
typedef typename base::iterator_category iterator_category;
|
|
# endif
|
|
|
|
iterator_archetype() { }
|
|
iterator_archetype(iterator_archetype const& x)
|
|
: detail::iterator_archetype_base<
|
|
Value
|
|
, AccessCategory
|
|
, TraversalCategory
|
|
>(x)
|
|
{}
|
|
|
|
iterator_archetype& operator=(iterator_archetype const&)
|
|
{ return *this; }
|
|
|
|
# if 0
|
|
// Optional conversion from mutable
|
|
iterator_archetype(
|
|
iterator_archetype<
|
|
typename detail::convertible_type<Value>::type
|
|
, AccessCategory
|
|
, TraversalCategory> const&
|
|
);
|
|
# endif
|
|
};
|
|
|
|
} // namespace iterators
|
|
|
|
// Backward compatibility names
|
|
namespace iterator_archetypes = iterators::archetypes;
|
|
using iterators::access_archetype;
|
|
using iterators::traversal_archetype;
|
|
using iterators::iterator_archetype;
|
|
using iterators::undefined;
|
|
using iterators::iterator_access_archetype_impl;
|
|
using iterators::traversal_archetype_base;
|
|
|
|
} // namespace boost
|
|
|
|
#endif // BOOST_ITERATOR_ARCHETYPES_HPP
|