// (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/aux_/msvc_eti_base.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 { | |
template <class Value, class AccessCategory> | |
struct access_archetype; | |
template <class Derived, class Value, class AccessCategory, class TraversalCategory> | |
struct traversal_archetype; | |
namespace iterator_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::aux::msvc_eti_base< | |
typename mpl::eval_if< | |
is_convertible<TraversalCategory, random_access_traversal_tag> | |
, mpl::eval_if< | |
iterator_archetypes::has_access< | |
AccessCategory | |
, iterator_archetypes::writable_iterator_t | |
> | |
, mpl::identity<writable_operator_brackets<Value> > | |
, mpl::if_< | |
iterator_archetypes::has_access< | |
AccessCategory | |
, iterator_archetypes::readable_iterator_t | |
> | |
, readable_operator_brackets<Value> | |
, no_operator_brackets | |
> | |
> | |
, mpl::identity<no_operator_brackets> | |
>::type | |
>::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_ | |
: mpl::aux::msvc_eti_base< | |
typename traversal_archetype_impl<TraversalCategory>::template archetype<Derived,Value> | |
>::type | |
{ | |
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; } | |
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) | |
// doesn't seem to pick up != from equality_comparable | |
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; } | |
#endif | |
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 | |
: mpl::aux::msvc_eti_base< | |
typename iterator_access_archetype_impl< | |
AccessCategory | |
>::template archetype<Value> | |
>::type | |
{ | |
}; | |
template <> | |
struct iterator_access_archetype_impl< | |
iterator_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< | |
iterator_archetypes::writable_iterator_t | |
> | |
{ | |
template <class Value> | |
struct archetype | |
{ | |
# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) | |
BOOST_STATIC_ASSERT(!is_const<Value>::value); | |
# endif | |
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< | |
iterator_archetypes::readable_writable_iterator_t | |
> | |
{ | |
template <class Value> | |
struct archetype | |
: public virtual iterator_access_archetype< | |
Value, iterator_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<iterator_archetypes::readable_lvalue_iterator_t> | |
{ | |
template <class Value> | |
struct archetype | |
: public virtual iterator_access_archetype< | |
Value, iterator_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<iterator_archetypes::writable_lvalue_iterator_t> | |
{ | |
template <class Value> | |
struct archetype | |
: public virtual iterator_access_archetype< | |
Value, iterator_archetypes::readable_lvalue_iterator_t | |
> | |
{ | |
# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) | |
BOOST_STATIC_ASSERT((!is_const<Value>::value)); | |
# endif | |
}; | |
}; | |
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< | |
iterator_archetypes::has_access< | |
AccessCategory, iterator_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 boost | |
#endif // BOOST_ITERATOR_ARCHETYPES_HPP |