forked from boostorg/iterator
iterator_categories reformed, test added
[SVN r20829]
This commit is contained in:
@ -1,335 +1 @@
|
|||||||
// (C) Copyright Thomas Witt 2002. Permission to copy, use, modify,
|
#error obsolete
|
||||||
// sell and distribute this software is granted provided this
|
|
||||||
// copyright notice appears in all copies. This software is provided
|
|
||||||
// "as is" without express or implied warranty, and with no claim as
|
|
||||||
// to its suitability for any purpose.
|
|
||||||
|
|
||||||
#ifndef BOOST_ITERATOR_DETAIL_CATEGORIES_HPP
|
|
||||||
# define BOOST_ITERATOR_DETAIL_CATEGORIES_HPP
|
|
||||||
|
|
||||||
# include <boost/config.hpp>
|
|
||||||
# include <boost/iterator/detail/config_def.hpp>
|
|
||||||
|
|
||||||
# include <boost/detail/workaround.hpp>
|
|
||||||
|
|
||||||
# include <boost/type_traits/is_convertible.hpp>
|
|
||||||
# include <boost/type_traits/is_same.hpp>
|
|
||||||
|
|
||||||
# include <boost/mpl/if.hpp>
|
|
||||||
# include <boost/mpl/apply_if.hpp>
|
|
||||||
# include <boost/mpl/identity.hpp>
|
|
||||||
# include <boost/mpl/bool.hpp>
|
|
||||||
# include <boost/mpl/or.hpp>
|
|
||||||
# include <boost/mpl/and.hpp>
|
|
||||||
# include <boost/mpl/integral_c.hpp>
|
|
||||||
# include <boost/mpl/aux_/lambda_support.hpp>
|
|
||||||
|
|
||||||
# include <iterator>
|
|
||||||
|
|
||||||
namespace boost
|
|
||||||
{
|
|
||||||
|
|
||||||
// faked new old-style categories needed to make new->old mapping
|
|
||||||
// work
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
struct null_category_tag {};
|
|
||||||
struct input_output_iterator_tag : std::input_iterator_tag, std::output_iterator_tag {};
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Access Categories
|
|
||||||
//
|
|
||||||
enum iterator_access
|
|
||||||
{
|
|
||||||
readable_iterator = 1
|
|
||||||
, writable_iterator = 2
|
|
||||||
, swappable_iterator = 4
|
|
||||||
, lvalue_iterator = 8
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// Traversal Categories
|
|
||||||
//
|
|
||||||
struct incrementable_traversal_tag
|
|
||||||
{
|
|
||||||
typedef std::output_iterator_tag max_category;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct single_pass_traversal_tag
|
|
||||||
: incrementable_traversal_tag
|
|
||||||
{
|
|
||||||
typedef detail::input_output_iterator_tag max_category;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct forward_traversal_tag
|
|
||||||
: single_pass_traversal_tag
|
|
||||||
{
|
|
||||||
typedef std::forward_iterator_tag max_category;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct bidirectional_traversal_tag
|
|
||||||
: forward_traversal_tag
|
|
||||||
{
|
|
||||||
typedef std::bidirectional_iterator_tag max_category;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct random_access_traversal_tag
|
|
||||||
: bidirectional_traversal_tag
|
|
||||||
{
|
|
||||||
typedef std::random_access_iterator_tag max_category;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct error_iterator_tag { };
|
|
||||||
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
template <unsigned access>
|
|
||||||
struct access_c : mpl::integral_c<iterator_access,(iterator_access)access>
|
|
||||||
{};
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Tag detection meta functions
|
|
||||||
//
|
|
||||||
|
|
||||||
// I bet this is defined somewhere else. Let's wait and see.
|
|
||||||
struct error_type;
|
|
||||||
|
|
||||||
# ifndef BOOST_NO_IS_CONVERTIBLE
|
|
||||||
|
|
||||||
// True iff T is a tag "derived" from Tag
|
|
||||||
template <class Tag, class T>
|
|
||||||
struct is_tag
|
|
||||||
: mpl::or_<
|
|
||||||
is_convertible<T, Tag>
|
|
||||||
|
|
||||||
// Because we can't actually get forward_iterator_tag to
|
|
||||||
// derive from input_output_iterator_tag, we need this
|
|
||||||
// case.
|
|
||||||
, mpl::and_<
|
|
||||||
is_convertible<T,std::forward_iterator_tag>
|
|
||||||
, is_convertible<detail::input_output_iterator_tag,Tag>
|
|
||||||
>
|
|
||||||
>
|
|
||||||
{};
|
|
||||||
|
|
||||||
|
|
||||||
# else
|
|
||||||
template <class Tag, class T>
|
|
||||||
struct is_tag;
|
|
||||||
# endif
|
|
||||||
|
|
||||||
// Generate specializations which will allow us to find
|
|
||||||
// null_category_tag as a minimum old-style category for new-style
|
|
||||||
// iterators which don't have an actual old-style category. We
|
|
||||||
// need that so there is a valid base class for all new-style
|
|
||||||
// iterators.
|
|
||||||
# define BOOST_OLD_ITERATOR_CATEGORY(category) \
|
|
||||||
template <> \
|
|
||||||
struct is_tag <detail::null_category_tag, std::category> \
|
|
||||||
: mpl::true_ {};
|
|
||||||
|
|
||||||
BOOST_OLD_ITERATOR_CATEGORY(input_iterator_tag)
|
|
||||||
BOOST_OLD_ITERATOR_CATEGORY(output_iterator_tag)
|
|
||||||
BOOST_OLD_ITERATOR_CATEGORY(forward_iterator_tag)
|
|
||||||
BOOST_OLD_ITERATOR_CATEGORY(bidirectional_iterator_tag)
|
|
||||||
BOOST_OLD_ITERATOR_CATEGORY(random_access_iterator_tag)
|
|
||||||
# undef BOOST_OLD_ITERATOR_CATEGORY
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct is_tag<detail::input_output_iterator_tag,std::forward_iterator_tag>
|
|
||||||
: mpl::true_
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
|
||||||
template <class T>
|
|
||||||
struct is_tag<T,T> : mpl::true_
|
|
||||||
{};
|
|
||||||
|
|
||||||
# ifdef BOOST_NO_IS_CONVERTIBLE
|
|
||||||
// Workarounds for CWPro7 which can't detect derivation at
|
|
||||||
// compile-time.
|
|
||||||
|
|
||||||
// Fact of life: we can only detect tag refinement relationships
|
|
||||||
// among predefined tags.
|
|
||||||
//
|
|
||||||
// Algorithm:
|
|
||||||
// is_tag(T,U) ->
|
|
||||||
// T == U
|
|
||||||
// || (exists d in derived_from(T) such that is_tag(d, U))
|
|
||||||
//
|
|
||||||
// T == U case is handled above
|
|
||||||
|
|
||||||
// false by default
|
|
||||||
template <class Tag, class T>
|
|
||||||
struct is_tag_impl : mpl::false_
|
|
||||||
{};
|
|
||||||
|
|
||||||
// The generalized template dispatches to is_tag_impl because
|
|
||||||
// is_tag<T,T> and is_tag<some_tag,T> are equally specialized.
|
|
||||||
// This technique simulates making is_tag<T,T> more-specialized.
|
|
||||||
template <class Tag, class T>
|
|
||||||
struct is_tag
|
|
||||||
: is_tag_impl<Tag, T>
|
|
||||||
{};
|
|
||||||
|
|
||||||
# define BOOST_ITERATOR_DERIVED_TAG1(base, derived) \
|
|
||||||
BOOST_ITERATOR_DERIVED_TAG1_AUX(base, _, derived)
|
|
||||||
|
|
||||||
# define BOOST_ITERATOR_DERIVED_TAG1_AUX(base, underscore, derived) \
|
|
||||||
template<class T> \
|
|
||||||
struct is_tag_impl<base##underscore##tag, T> \
|
|
||||||
: is_tag<derived##underscore##tag, T> \
|
|
||||||
{ \
|
|
||||||
};
|
|
||||||
|
|
||||||
// Old-style tag relations
|
|
||||||
template<class T>
|
|
||||||
struct is_tag_impl<detail::null_category_tag, T>
|
|
||||||
: mpl::or_<
|
|
||||||
is_tag<std::output_iterator_tag, T>
|
|
||||||
, is_tag<std::input_iterator_tag, T>
|
|
||||||
>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
BOOST_ITERATOR_DERIVED_TAG1(std::output_iterator, detail::input_output_iterator)
|
|
||||||
BOOST_ITERATOR_DERIVED_TAG1(std::input_iterator, detail::input_output_iterator)
|
|
||||||
BOOST_ITERATOR_DERIVED_TAG1(detail::input_output_iterator, std::forward_iterator)
|
|
||||||
BOOST_ITERATOR_DERIVED_TAG1(std::forward_iterator, std::bidirectional_iterator)
|
|
||||||
BOOST_ITERATOR_DERIVED_TAG1(std::bidirectional_iterator, std::random_access_iterator)
|
|
||||||
|
|
||||||
// Access tag relations
|
|
||||||
BOOST_ITERATOR_DERIVED_TAG1(readable_lvalue_iterator, writable_lvalue_iterator)
|
|
||||||
BOOST_ITERATOR_DERIVED_TAG1(swappable_iterator, readable_writable_iterator)
|
|
||||||
BOOST_ITERATOR_DERIVED_TAG1(readable_writable_iterator, writable_lvalue_iterator)
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
struct is_tag_impl<readable_iterator_tag, T>
|
|
||||||
: mpl::or_<
|
|
||||||
is_tag<readable_lvalue_iterator_tag, T>
|
|
||||||
, is_tag<readable_writable_iterator_tag, T>
|
|
||||||
>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
BOOST_ITERATOR_DERIVED_TAG1(writable_iterator, readable_writable_iterator)
|
|
||||||
|
|
||||||
// Traversal tag relations
|
|
||||||
BOOST_ITERATOR_DERIVED_TAG1(bidirectional_traversal, random_access_traversal)
|
|
||||||
BOOST_ITERATOR_DERIVED_TAG1(forward_traversal, bidirectional_traversal)
|
|
||||||
BOOST_ITERATOR_DERIVED_TAG1(single_pass_traversal, forward_traversal)
|
|
||||||
BOOST_ITERATOR_DERIVED_TAG1(incrementable_traversal, single_pass_traversal)
|
|
||||||
|
|
||||||
# endif // BOOST_NO_IS_CONVERTIBLE workarounds
|
|
||||||
|
|
||||||
# endif // ndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
|
||||||
|
|
||||||
// If TraversalTag is convertible to Known, return it, otherwise
|
|
||||||
// return the result of invoking NullaryElse
|
|
||||||
template <class TraversalTag, class Known, class NullaryElse>
|
|
||||||
struct known_traversal_tag
|
|
||||||
: mpl::apply_if<
|
|
||||||
is_convertible<TraversalTag,Known>
|
|
||||||
, mpl::identity<Known>
|
|
||||||
, NullaryElse
|
|
||||||
>
|
|
||||||
{};
|
|
||||||
|
|
||||||
template <class Tag>
|
|
||||||
struct max_known_traversal_tag
|
|
||||||
: known_traversal_tag<
|
|
||||||
Tag, random_access_traversal_tag
|
|
||||||
, known_traversal_tag<
|
|
||||||
Tag, bidirectional_traversal_tag
|
|
||||||
, known_traversal_tag<
|
|
||||||
Tag, forward_traversal_tag
|
|
||||||
, known_traversal_tag<
|
|
||||||
Tag, single_pass_traversal_tag
|
|
||||||
, known_traversal_tag<
|
|
||||||
Tag, incrementable_traversal_tag
|
|
||||||
, error_iterator_tag
|
|
||||||
>
|
|
||||||
>
|
|
||||||
>
|
|
||||||
>
|
|
||||||
>
|
|
||||||
{};
|
|
||||||
|
|
||||||
template <class AccessTag, unsigned Known, class NullaryElse>
|
|
||||||
struct known_access_tag
|
|
||||||
: mpl::apply_if_c<
|
|
||||||
((AccessTag::value & Known) == Known)
|
|
||||||
, mpl::identity<access_c<Known> >
|
|
||||||
, NullaryElse
|
|
||||||
>
|
|
||||||
{};
|
|
||||||
|
|
||||||
|
|
||||||
// Doesn't cope with these odd combinations: readable+swappable,
|
|
||||||
// writable+swappable. That doesn't matter for the sake of
|
|
||||||
// new-style tag base computation, which is all it's used for
|
|
||||||
// anyway.
|
|
||||||
template <class Tag>
|
|
||||||
struct max_known_access_tag
|
|
||||||
: known_access_tag<
|
|
||||||
Tag, (writable_iterator|readable_iterator|swappable_iterator|lvalue_iterator)
|
|
||||||
, known_access_tag<
|
|
||||||
Tag, (readable_iterator|lvalue_iterator)
|
|
||||||
, known_access_tag<
|
|
||||||
Tag, (writable_iterator|readable_iterator|swappable_iterator)
|
|
||||||
, known_access_tag<
|
|
||||||
Tag, writable_iterator
|
|
||||||
, known_access_tag<
|
|
||||||
Tag, readable_iterator
|
|
||||||
, mpl::apply_if_c<
|
|
||||||
(swappable_iterator & Tag::value)
|
|
||||||
, mpl::identity<null_category_tag>
|
|
||||||
, error_iterator_tag
|
|
||||||
>
|
|
||||||
>
|
|
||||||
>
|
|
||||||
>
|
|
||||||
>
|
|
||||||
>
|
|
||||||
{};
|
|
||||||
|
|
||||||
//
|
|
||||||
// Returns the minimum category type or error_type
|
|
||||||
// if T1 and T2 are unrelated.
|
|
||||||
//
|
|
||||||
// For compilers not supporting is_convertible this only
|
|
||||||
// works with the new boost return and traversal category
|
|
||||||
// types. The exact boost _types_ are required. No derived types
|
|
||||||
// will work.
|
|
||||||
//
|
|
||||||
//
|
|
||||||
template <class T1, class T2>
|
|
||||||
struct minimum_category
|
|
||||||
: mpl::apply_if<
|
|
||||||
is_tag<T1,T2>
|
|
||||||
, mpl::identity<T1>
|
|
||||||
, mpl::if_<
|
|
||||||
is_tag<T2, T1>
|
|
||||||
, T2
|
|
||||||
, error_type
|
|
||||||
>
|
|
||||||
>
|
|
||||||
{
|
|
||||||
BOOST_MPL_AUX_LAMBDA_SUPPORT(2,minimum_category,(T1,T2))
|
|
||||||
};
|
|
||||||
|
|
||||||
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
|
|
||||||
// Deal with ETI
|
|
||||||
template <> struct minimum_category<int, int> { typedef minimum_category type; };
|
|
||||||
# endif
|
|
||||||
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
} // namespace boost
|
|
||||||
|
|
||||||
#include <boost/iterator/detail/config_undef.hpp>
|
|
||||||
|
|
||||||
#endif // BOOST_ITERATOR_DETAIL_CATEGORIES_HPP
|
|
||||||
|
@ -4,411 +4,195 @@
|
|||||||
// "as is" without express or implied warranty, and with no claim as
|
// "as is" without express or implied warranty, and with no claim as
|
||||||
// to its suitability for any purpose.
|
// to its suitability for any purpose.
|
||||||
|
|
||||||
// TODO:
|
|
||||||
// Add separate category tag for operator[].
|
|
||||||
|
|
||||||
#ifndef BOOST_ITERATOR_CATEGORIES_HPP
|
#ifndef BOOST_ITERATOR_CATEGORIES_HPP
|
||||||
#define BOOST_ITERATOR_CATEGORIES_HPP
|
# define BOOST_ITERATOR_CATEGORIES_HPP
|
||||||
|
|
||||||
#include <boost/config.hpp>
|
# include <boost/config.hpp>
|
||||||
#include <boost/iterator/detail/categories.hpp>
|
# include <boost/detail/iterator.hpp>
|
||||||
|
# include <boost/iterator/detail/config_def.hpp>
|
||||||
|
|
||||||
#include <boost/type_traits/conversion_traits.hpp>
|
# include <boost/detail/workaround.hpp>
|
||||||
#include <boost/type_traits/cv_traits.hpp>
|
|
||||||
|
|
||||||
#include <boost/python/detail/indirect_traits.hpp>
|
# include <boost/mpl/if.hpp>
|
||||||
|
# include <boost/mpl/and.hpp>
|
||||||
#include <boost/detail/iterator.hpp>
|
# include <boost/mpl/apply_if.hpp>
|
||||||
#include <boost/detail/workaround.hpp>
|
# include <boost/mpl/identity.hpp>
|
||||||
|
|
||||||
#include <boost/mpl/apply_if.hpp>
|
|
||||||
#include <boost/mpl/if.hpp>
|
|
||||||
#include <boost/mpl/bool.hpp>
|
|
||||||
#include <boost/mpl/aux_/has_xxx.hpp>
|
|
||||||
#include <boost/mpl/not.hpp>
|
|
||||||
#include <boost/mpl/or.hpp>
|
|
||||||
#include <boost/mpl/apply.hpp>
|
|
||||||
#include <boost/mpl/aux_/msvc_eti_base.hpp>
|
|
||||||
#ifdef BOOST_MPL_NO_FULL_LAMBDA_SUPPORT
|
|
||||||
# include <boost/mpl/placeholders.hpp>
|
# include <boost/mpl/placeholders.hpp>
|
||||||
#endif
|
# include <boost/mpl/aux_/lambda_support.hpp>
|
||||||
|
|
||||||
#include <iterator>
|
# include <boost/type_traits/is_reference.hpp>
|
||||||
|
# include <boost/type_traits/is_convertible.hpp>
|
||||||
#include <boost/iterator/detail/config_def.hpp> // must be last #include
|
# include <boost/type_traits/is_const.hpp>
|
||||||
|
|
||||||
#if BOOST_WORKAROUND(__MWERKS__, <=0x2407)
|
|
||||||
# define BOOST_NO_IS_CONVERTIBLE // "Convertible does not provide enough/is not working"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
|
|
||||||
namespace detail
|
//
|
||||||
|
// Traversal Categories
|
||||||
|
//
|
||||||
|
struct incrementable_traversal_tag {};
|
||||||
|
|
||||||
|
struct single_pass_traversal_tag
|
||||||
|
: incrementable_traversal_tag {};
|
||||||
|
|
||||||
|
struct forward_traversal_tag
|
||||||
|
: single_pass_traversal_tag {};
|
||||||
|
|
||||||
|
struct bidirectional_traversal_tag
|
||||||
|
: forward_traversal_tag {};
|
||||||
|
|
||||||
|
struct random_access_traversal_tag
|
||||||
|
: bidirectional_traversal_tag {};
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
struct input_output_iterator_tag
|
||||||
|
: std::input_iterator_tag, std::output_iterator_tag {};
|
||||||
|
|
||||||
|
template <class Value, class Reference, class Traversal>
|
||||||
|
struct old_iterator_category
|
||||||
{
|
{
|
||||||
// Helper metafunction for std_category below
|
typedef typename mpl::
|
||||||
template <class Cat, class Tag, class Next>
|
# if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
|
||||||
struct match_tag
|
if_
|
||||||
: mpl::apply_if<is_tag<Tag, Cat>, mpl::identity<Tag>, Next>
|
# else
|
||||||
{
|
apply_if
|
||||||
};
|
|
||||||
|
|
||||||
// Converts a possibly user-defined category tag to the
|
|
||||||
// most-derived standard tag which is a base of that tag.
|
|
||||||
template <class Category>
|
|
||||||
struct std_category
|
|
||||||
: match_tag<
|
|
||||||
Category, std::random_access_iterator_tag
|
|
||||||
, match_tag<Category, std::bidirectional_iterator_tag
|
|
||||||
, match_tag<Category, std::forward_iterator_tag
|
|
||||||
, match_tag<Category, std::input_iterator_tag
|
|
||||||
, match_tag<Category, std::output_iterator_tag
|
|
||||||
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
|
||||||
, mpl::identity<void>
|
|
||||||
# else
|
|
||||||
, void
|
|
||||||
# endif
|
|
||||||
>
|
|
||||||
>
|
|
||||||
>
|
|
||||||
>
|
|
||||||
>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
// std_to_new_tags --
|
|
||||||
//
|
|
||||||
// A metafunction which converts any standard tag into its
|
|
||||||
// corresponding new-style traversal tag.
|
|
||||||
//
|
|
||||||
// Also, instantiations are metafunction classes which convert a
|
|
||||||
// reference type into a corresponding new-style access tag.
|
|
||||||
template <class Category> struct std_to_new_tags
|
|
||||||
# if BOOST_WORKAROUND(BOOST_MSVC, == 1300) // handle ETI
|
|
||||||
{
|
|
||||||
typedef void type;
|
|
||||||
template <class T> struct apply { typedef void type; };
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
;
|
|
||||||
|
|
||||||
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) // handle ETI
|
|
||||||
template <> struct std_to_new_tags<int> {};
|
|
||||||
# endif
|
|
||||||
|
|
||||||
//
|
|
||||||
// Specializations for specific standard tags
|
|
||||||
//
|
|
||||||
template <>
|
|
||||||
struct std_to_new_tags<std::input_iterator_tag>
|
|
||||||
{
|
|
||||||
typedef single_pass_traversal_tag type;
|
|
||||||
|
|
||||||
template <class Reference>
|
|
||||||
struct apply
|
|
||||||
: access_c<readable_iterator> {};
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct std_to_new_tags<std::output_iterator_tag>
|
|
||||||
{
|
|
||||||
typedef incrementable_traversal_tag type;
|
|
||||||
|
|
||||||
template <class Reference>
|
|
||||||
struct apply
|
|
||||||
: access_c<writable_iterator> {};
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct std_to_new_tags<std::forward_iterator_tag>
|
|
||||||
{
|
|
||||||
typedef forward_traversal_tag type;
|
|
||||||
|
|
||||||
template <class Reference>
|
|
||||||
struct apply
|
|
||||||
: mpl::if_<
|
|
||||||
python::detail::is_reference_to_const<Reference>
|
|
||||||
, access_c<(readable_iterator|lvalue_iterator)>
|
|
||||||
, access_c<(readable_iterator|writable_iterator|lvalue_iterator)>
|
|
||||||
>
|
|
||||||
{};
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct std_to_new_tags<std::bidirectional_iterator_tag>
|
|
||||||
: std_to_new_tags<std::forward_iterator_tag>
|
|
||||||
{
|
|
||||||
typedef bidirectional_traversal_tag type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct std_to_new_tags<std::random_access_iterator_tag>
|
|
||||||
: std_to_new_tags<std::bidirectional_iterator_tag>
|
|
||||||
{
|
|
||||||
typedef random_access_traversal_tag type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class Category>
|
|
||||||
struct old_tag_converter
|
|
||||||
: std_to_new_tags<
|
|
||||||
// Take the category down to its most-refined known
|
|
||||||
// std::tag, in case of derivation/convertibility
|
|
||||||
typename std_category<Category>::type
|
|
||||||
>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class OldTag>
|
|
||||||
struct old_tag_to_traversal
|
|
||||||
: old_tag_converter<OldTag>
|
|
||||||
{};
|
|
||||||
|
|
||||||
|
|
||||||
template <typename Category, typename Reference>
|
|
||||||
struct old_tag_to_access
|
|
||||||
: mpl::apply1<
|
|
||||||
old_tag_converter<Category>
|
|
||||||
, Reference
|
|
||||||
>
|
|
||||||
{};
|
|
||||||
|
|
||||||
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
|
|
||||||
// Deal with ETI
|
|
||||||
template <> struct old_tag_to_access<int, int> {};
|
|
||||||
template <> struct old_tag_converter<int> {};
|
|
||||||
# endif
|
|
||||||
|
|
||||||
// A metafunction returning true iff T is boost::iterator_tag<R,U>
|
|
||||||
template <class T>
|
|
||||||
struct is_boost_iterator_tag;
|
|
||||||
|
|
||||||
#if BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
|
|
||||||
//
|
|
||||||
// has_xxx fails, so we have to use
|
|
||||||
// something less sophisticated.
|
|
||||||
//
|
|
||||||
// The solution depends on the fact that only
|
|
||||||
// std iterator categories work with is_xxx_iterator
|
|
||||||
// meta functions, as BOOST_NO_IS_CONVERTIBLE is
|
|
||||||
// defined for cwpro7.
|
|
||||||
//
|
|
||||||
template <class Tag>
|
|
||||||
struct is_new_iterator_tag
|
|
||||||
: mpl::not_<
|
|
||||||
mpl::or_<
|
|
||||||
is_tag<std::input_iterator_tag, Tag>
|
|
||||||
, is_tag<std::output_iterator_tag, Tag>
|
|
||||||
>
|
|
||||||
>
|
|
||||||
{};
|
|
||||||
|
|
||||||
#elif BOOST_WORKAROUND(__GNUC__, == 2 && __GNUC_MINOR__ == 95) \
|
|
||||||
|| BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
|
|
||||||
|
|
||||||
template <class Tag>
|
|
||||||
struct is_new_iterator_tag
|
|
||||||
: is_boost_iterator_tag<Tag>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
BOOST_MPL_HAS_XXX_TRAIT_DEF(traversal)
|
|
||||||
|
|
||||||
template <class Tag>
|
|
||||||
struct is_new_iterator_tag
|
|
||||||
: mpl::if_<
|
|
||||||
is_class<Tag>
|
|
||||||
, has_traversal<Tag>
|
|
||||||
, mpl::false_
|
|
||||||
>::type
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
template <class NewCategoryTag>
|
|
||||||
struct new_tag_to_traversal
|
|
||||||
{
|
|
||||||
typedef typename NewCategoryTag::traversal type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class NewCategoryTag>
|
|
||||||
struct new_tag_to_access
|
|
||||||
{
|
|
||||||
typedef typename NewCategoryTag::access_type type;
|
|
||||||
};
|
|
||||||
#if 0 // what was this all about?
|
|
||||||
template <class NewCategoryTag, class Reference>
|
|
||||||
struct new_tag_to_access
|
|
||||||
: mpl::apply_if<
|
|
||||||
python::detail::is_reference_to_const<Reference>
|
|
||||||
, remove_access_writability<typename NewCategoryTag::access>
|
|
||||||
, mpl::identity<typename NewCategoryTag::access>
|
|
||||||
>
|
|
||||||
{};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template <class CategoryTag, class Reference>
|
|
||||||
struct tag_access_category
|
|
||||||
: mpl::apply_if<
|
|
||||||
is_new_iterator_tag<CategoryTag>
|
|
||||||
, new_tag_to_access<CategoryTag>
|
|
||||||
, old_tag_to_access<CategoryTag, Reference>
|
|
||||||
>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class CategoryTag>
|
|
||||||
struct tag_traversal_category
|
|
||||||
: mpl::apply_if<
|
|
||||||
is_new_iterator_tag<CategoryTag>
|
|
||||||
, new_tag_to_traversal<CategoryTag>
|
|
||||||
, old_tag_to_traversal<CategoryTag>
|
|
||||||
>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
|
|
||||||
// Deal with ETI
|
|
||||||
template <> struct tag_access_category<int, int> { typedef void type; };
|
|
||||||
template <> struct tag_traversal_category<int> { typedef void type; };
|
|
||||||
# endif
|
|
||||||
|
|
||||||
// iterator_tag_base - a metafunction to compute the appropriate
|
|
||||||
// old-style tag (if any) to use as a base for a new-style tag.
|
|
||||||
template <class KnownAccessTag, class KnownTraversalTag>
|
|
||||||
struct iterator_tag_base
|
|
||||||
: minimum_category<
|
|
||||||
typename KnownAccessTag::max_category
|
|
||||||
, typename KnownTraversalTag::max_category
|
|
||||||
>
|
|
||||||
{};
|
|
||||||
|
|
||||||
# if BOOST_WORKAROUND(BOOST_MSVC,<=1200)
|
|
||||||
template <>
|
|
||||||
struct iterator_tag_base<int,int>
|
|
||||||
: mpl::false_ {}; // just using false_ so that the result will be
|
|
||||||
// a legal base class
|
|
||||||
# endif
|
# endif
|
||||||
|
<
|
||||||
|
mpl::and_<
|
||||||
|
is_reference<Reference>
|
||||||
|
, is_convertible<Traversal,forward_traversal_tag>
|
||||||
|
>
|
||||||
|
, mpl::apply_if<
|
||||||
|
is_convertible<Traversal,random_access_traversal_tag>
|
||||||
|
, mpl::identity<std::random_access_iterator_tag>
|
||||||
|
, mpl::if_<
|
||||||
|
is_convertible<Traversal,bidirectional_traversal_tag>
|
||||||
|
, std::bidirectional_iterator_tag
|
||||||
|
, std::forward_iterator_tag
|
||||||
|
>
|
||||||
|
>
|
||||||
|
# if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
|
||||||
|
::type
|
||||||
|
# endif
|
||||||
|
, typename mpl::apply_if<
|
||||||
|
mpl::and_<
|
||||||
|
is_convertible<Traversal, single_pass_traversal_tag>
|
||||||
|
, is_convertible<Reference, Value>
|
||||||
|
>
|
||||||
|
, mpl::if_<
|
||||||
|
is_const<Value>
|
||||||
|
, std::input_iterator_tag
|
||||||
|
, input_output_iterator_tag
|
||||||
|
>
|
||||||
|
, mpl::identity<std::output_iterator_tag>
|
||||||
|
>
|
||||||
|
# if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
|
||||||
|
::type
|
||||||
|
# endif
|
||||||
|
>::type type;
|
||||||
|
};
|
||||||
|
|
||||||
// specialization for this special case. Otherwise we get
|
//
|
||||||
// input_output_iterator_tag, because the standard hierarchy has a
|
// Convert a "strictly old-style" iterator category to a traversal
|
||||||
// sudden anomalous distinction between readability and
|
// tag. This is broken out into a separate metafunction to reduce
|
||||||
// writability at the level of input iterator/output iterator.
|
// the cost of instantiating iterator_category_to_traversal, below,
|
||||||
template <>
|
// for new-style types.
|
||||||
struct iterator_tag_base<
|
//
|
||||||
access_c<(readable_iterator|lvalue_iterator)>
|
template <class Cat>
|
||||||
, single_pass_traversal_tag
|
struct old_style_category_to_traversal
|
||||||
>
|
: mpl::apply_if<
|
||||||
{
|
is_convertible<Cat,std::random_access_iterator_tag>
|
||||||
typedef std::input_iterator_tag type;
|
, mpl::identity<random_access_traversal_tag>
|
||||||
};
|
, mpl::apply_if<
|
||||||
|
is_convertible<Cat,std::bidirectional_iterator_tag>
|
||||||
} // namespace detail
|
, mpl::identity<bidirectional_traversal_tag>
|
||||||
|
, mpl::apply_if<
|
||||||
template <class Iterator>
|
is_convertible<Cat,std::forward_iterator_tag>
|
||||||
struct access_category
|
, mpl::identity<forward_traversal_tag>
|
||||||
: detail::tag_access_category<
|
, mpl::apply_if<
|
||||||
typename detail::iterator_traits<Iterator>::iterator_category
|
is_convertible<Cat,std::input_iterator_tag>
|
||||||
, typename detail::iterator_traits<Iterator>::reference
|
, mpl::identity<single_pass_traversal_tag>
|
||||||
|
, mpl::apply_if<
|
||||||
|
is_convertible<Cat,std::output_iterator_tag>
|
||||||
|
, mpl::identity<incrementable_traversal_tag>
|
||||||
|
, void
|
||||||
|
>
|
||||||
|
>
|
||||||
|
>
|
||||||
|
>
|
||||||
>
|
>
|
||||||
{};
|
{};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
template <class Iterator>
|
|
||||||
struct traversal_category
|
//
|
||||||
: detail::tag_traversal_category<
|
// Convert an iterator category into a traversal tag
|
||||||
typename detail::iterator_traits<Iterator>::iterator_category
|
//
|
||||||
>
|
template <class Cat>
|
||||||
{
|
struct iterator_category_to_traversal
|
||||||
};
|
: mpl::apply_if< // if already convertible to a traversal tag, we're done.
|
||||||
|
is_convertible<Cat,incrementable_traversal_tag>
|
||||||
|
, mpl::identity<Cat>
|
||||||
|
, detail::old_style_category_to_traversal<Cat>
|
||||||
|
>
|
||||||
|
{};
|
||||||
|
|
||||||
|
//
|
||||||
|
// To be used for a new-style iterator's iterator_category; provides
|
||||||
|
// implicit conversion to the appropriate old-style iterator category.
|
||||||
|
//
|
||||||
|
// If Value is const the result will not be convertible to
|
||||||
|
// output_iterator_tag.
|
||||||
|
//
|
||||||
|
// Otherwise, if Traversal == single_pass_traversal_tag, the following
|
||||||
|
// conditions will result in a tag that is convertible both to
|
||||||
|
// input_iterator_tag and output_iterator_tag:
|
||||||
|
//
|
||||||
|
// 1. Reference is a reference to non-const
|
||||||
|
// 2. Reference is not a reference and is convertible to Value
|
||||||
|
//
|
||||||
|
template <class Value, class Reference, class Traversal>
|
||||||
|
struct iterator_tag
|
||||||
|
: detail::old_iterator_category<Value, Reference, Traversal>::type
|
||||||
|
{
|
||||||
|
operator Traversal() { return Traversal(); }
|
||||||
|
# if 0
|
||||||
|
typedef typename detail::old_iterator_category<
|
||||||
|
Value, Reference, Traversal
|
||||||
|
>::type old_category;
|
||||||
|
|
||||||
|
operator old_category() const { return old_category(); }
|
||||||
|
# endif
|
||||||
|
};
|
||||||
|
|
||||||
|
// Trait to get an iterator's traversal category
|
||||||
|
template <class Iterator = mpl::_1>
|
||||||
|
struct iterator_traversal
|
||||||
|
: iterator_category_to_traversal<
|
||||||
|
typename boost::detail::iterator_traits<Iterator>::iterator_category
|
||||||
|
>
|
||||||
|
{};
|
||||||
|
|
||||||
# ifdef BOOST_MPL_NO_FULL_LAMBDA_SUPPORT
|
# ifdef BOOST_MPL_NO_FULL_LAMBDA_SUPPORT
|
||||||
// Hack because BOOST_MPL_AUX_LAMBDA_SUPPORT doesn't seem to work
|
// Hack because BOOST_MPL_AUX_LAMBDA_SUPPORT doesn't seem to work
|
||||||
// out well. Instantiating the nested apply template also
|
// out well. Instantiating the nested apply template also
|
||||||
// requires instantiating iterator_traits on the
|
// requires instantiating iterator_traits on the
|
||||||
// placeholder. Instead we just specialize it as a metafunction
|
// placeholder. Instead we just specialize it as a metafunction
|
||||||
// class.
|
// class.
|
||||||
template <>
|
template <>
|
||||||
struct access_category<mpl::_1>
|
struct iterator_traversal<mpl::_1>
|
||||||
{
|
{
|
||||||
template <class T>
|
|
||||||
struct apply : access_category<T>
|
|
||||||
{};
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct traversal_category<mpl::_1>
|
|
||||||
{
|
|
||||||
template <class T>
|
|
||||||
struct apply : traversal_category<T>
|
|
||||||
{};
|
|
||||||
};
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct access_category<T*>
|
|
||||||
: mpl::if_<
|
|
||||||
is_const<T>
|
|
||||||
, detail::access_c<(readable_iterator|lvalue_iterator)>
|
|
||||||
, detail::access_c<(readable_iterator|writable_iterator|lvalue_iterator)>
|
|
||||||
>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct traversal_category<T*>
|
|
||||||
{
|
|
||||||
typedef random_access_traversal_tag type;
|
|
||||||
};
|
|
||||||
|
|
||||||
# endif
|
|
||||||
|
|
||||||
template <unsigned Access, class TraversalTag>
|
|
||||||
struct iterator_tag
|
|
||||||
: detail::iterator_tag_base<
|
|
||||||
typename detail::max_known_access_tag<detail::access_c<Access> >::type::value
|
|
||||||
, typename detail::max_known_traversal_tag<TraversalTag>::type
|
|
||||||
>::type
|
|
||||||
{
|
|
||||||
typedef detail::access_c<(Access & ~lvalue_iterator)> access_type;
|
|
||||||
BOOST_STATIC_CONSTANT(iterator_access, value = (iterator_access)(Access & ~lvalue_iterator));
|
|
||||||
typedef TraversalTag traversal;
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
|
||||||
template <class T>
|
template <class T>
|
||||||
struct is_boost_iterator_tag
|
struct apply : iterator_traversal<T>
|
||||||
: mpl::false_ {};
|
{};
|
||||||
|
};
|
||||||
template <unsigned A, class T>
|
template <>
|
||||||
struct is_boost_iterator_tag<iterator_tag<A,T> >
|
struct iterator_traversal<mpl::_>
|
||||||
: mpl::true_ {};
|
: iterator_traversal<mpl::_1>
|
||||||
# else
|
{};
|
||||||
template <class T>
|
|
||||||
struct is_boost_iterator_tag
|
|
||||||
{
|
|
||||||
typedef char (&yes)[1];
|
|
||||||
typedef char (&no)[2];
|
|
||||||
|
|
||||||
template <unsigned A, class U>
|
|
||||||
static yes test(mpl::identity<iterator_tag<A,U> >*);
|
|
||||||
static no test(...);
|
|
||||||
|
|
||||||
static mpl::identity<T>* inst;
|
|
||||||
BOOST_STATIC_CONSTANT(bool, value = sizeof(test(inst)) == sizeof(yes));
|
|
||||||
typedef mpl::bool_<value> type;
|
|
||||||
};
|
|
||||||
# endif
|
# endif
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace boost
|
} // namespace boost
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user