Removed access category tags from iterator library, made corresponding

changes elsewhere.

boost/iterator and libs/iterator/test were updated from
branch "simplify"


[SVN r20905]
This commit is contained in:
Dave Abrahams
2003-11-22 01:18:37 +00:00
parent 522195fd64
commit f18906ac6b
31 changed files with 1501 additions and 1838 deletions

View File

@ -15,7 +15,12 @@
namespace boost { namespace boost {
template <class Incrementable, class Category, class Difference> class counting_iterator; template <
class Incrementable
, class CategoryOrTraversal
, class Difference
>
class counting_iterator;
namespace detail namespace detail
{ {
@ -67,35 +72,38 @@ namespace detail
}; };
BOOST_STATIC_ASSERT(is_numeric<int>::value); BOOST_STATIC_ASSERT(is_numeric<int>::value);
template <class Incrementable, class Category, class Difference>
template <class Incrementable, class CategoryOrTraversal, class Difference>
struct counting_iterator_base struct counting_iterator_base
{ {
typedef typename mpl::apply_if< typedef typename detail::ia_dflt_help<
is_same<Category, use_default> CategoryOrTraversal
, mpl::apply_if< , mpl::apply_if<
is_numeric<Incrementable> is_numeric<Incrementable>
, mpl::identity<std::random_access_iterator_tag> , mpl::identity<random_access_traversal_tag>
, BOOST_ITERATOR_CATEGORY<Incrementable> , iterator_traversal<Incrementable>
> >
, mpl::identity<Category> >::type traversal;
>::type category;
typedef typename mpl::apply_if< typedef typename detail::ia_dflt_help<
is_same<Difference, use_default> Difference
, mpl::apply_if< , mpl::apply_if<
is_numeric<Incrementable> is_numeric<Incrementable>
, numeric_difference<Incrementable> , numeric_difference<Incrementable>
, iterator_difference<Incrementable> , iterator_difference<Incrementable>
> >
, mpl::identity<Difference>
>::type difference; >::type difference;
typedef iterator_adaptor< typedef iterator_adaptor<
counting_iterator<Incrementable, Category, Difference> // self counting_iterator<Incrementable, CategoryOrTraversal, Difference> // self
, Incrementable // Base , Incrementable // Base
, Incrementable // value_type , Incrementable // Value
, category # ifndef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY
, Incrementable const& // reference const // MSVC won't strip this. Instead we enable Thomas'
// criterion (see boost/iterator/detail/facade_iterator_category.hpp)
# endif
, traversal
, Incrementable const& // reference
, difference , difference
> type; > type;
}; };
@ -128,11 +136,20 @@ namespace detail
}; };
} }
template <class Incrementable, class Category = use_default, class Difference = use_default> template <
class Incrementable
, class CategoryOrTraversal = use_default
, class Difference = use_default
>
class counting_iterator class counting_iterator
: public detail::counting_iterator_base<Incrementable, Category, Difference>::type : public detail::counting_iterator_base<
Incrementable, CategoryOrTraversal, Difference
>::type
{ {
typedef typename detail::counting_iterator_base<Incrementable, Category, Difference>::type super_t; typedef typename detail::counting_iterator_base<
Incrementable, CategoryOrTraversal, Difference
>::type super_t;
friend class iterator_core_access; friend class iterator_core_access;
public: public:

View File

@ -1,360 +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/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
//
struct readable_iterator_tag
{
typedef std::input_iterator_tag max_category;
};
struct writable_iterator_tag
{
typedef std::output_iterator_tag max_category;
};
struct swappable_iterator_tag
{
typedef detail::null_category_tag max_category;
};
struct readable_writable_iterator_tag
: virtual readable_iterator_tag
, virtual writable_iterator_tag
, virtual swappable_iterator_tag
{
typedef detail::input_output_iterator_tag max_category;
};
struct readable_lvalue_iterator_tag
: virtual readable_iterator_tag
{
typedef std::random_access_iterator_tag max_category;
};
struct writable_lvalue_iterator_tag
: virtual public readable_writable_iterator_tag
, virtual public readable_lvalue_iterator_tag
{
typedef std::random_access_iterator_tag max_category;
};
//
// 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
{
//
// 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
template <class Tag, class Known, class Else>
struct known_tag
: mpl::apply_if<is_tag<Known,Tag>, mpl::identity<Known>, Else>
{};
template <class Tag>
struct max_known_traversal_tag
: known_tag<
Tag, random_access_traversal_tag
, known_tag<
Tag, bidirectional_traversal_tag
, known_tag<
Tag, forward_traversal_tag
, known_tag<
Tag, single_pass_traversal_tag
, known_tag<
Tag, incrementable_traversal_tag
, error_iterator_tag
>
>
>
>
>
{};
// 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_tag<
Tag, writable_lvalue_iterator_tag
, known_tag<
Tag, readable_lvalue_iterator_tag
, known_tag<
Tag, readable_writable_iterator_tag
, known_tag<
Tag, writable_iterator_tag
, known_tag<
Tag, readable_iterator_tag
, mpl::apply_if<
is_tag<Tag, swappable_iterator_tag>
, 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
//
// Tag classification for use in iterator_adaptor
//
template <class Tag>
struct is_access_tag
: mpl::or_<
is_tag<readable_iterator_tag, Tag>
, mpl::or_<
is_tag<writable_iterator_tag, Tag>
, is_tag<swappable_iterator_tag, Tag>
>
>
{};
template <class Tag>
struct is_traversal_tag
: is_tag<incrementable_traversal_tag, Tag>
{};
} // namespace detail
} // namespace boost
#include <boost/iterator/detail/config_undef.hpp>
#endif // BOOST_ITERATOR_DETAIL_CATEGORIES_HPP

View File

@ -18,7 +18,66 @@
#include <boost/config.hpp> // for prior #include <boost/config.hpp> // for prior
#include <boost/detail/workaround.hpp> #include <boost/detail/workaround.hpp>
#define BOOST_ITERATOR_CONFIG_DEF // if you get an error here, you have nested config_def #inclusion. #ifdef BOOST_ITERATOR_CONFIG_DEF
# error you have nested config_def #inclusion.
#else
# define BOOST_ITERATOR_CONFIG_DEF
#endif
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
|| BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x531))
// Recall that in general, compilers without partial specialization
// can't strip constness. Consider counting_iterator, which normally
// passes a const Value to iterator_facade. As a result, any code
// which makes a std::vector of the iterator's value_type will fail
// when its allocator declares functions overloaded on reference and
// const_reference (the same type).
//
// Furthermore, Borland 5.5.1 drops constness in enough ways that we
// end up using a proxy for operator[] when we otherwise shouldn't.
// Using reference constness gives it an extra hint that it can
// return the value_type from operator[] directly, but is not
// strictly neccessary. Not sure how best to resolve this one.
# define BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY 1
#endif
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) \
|| BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x531)) \
|| (BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, <= 700) && defined(_MSC_VER))
# define BOOST_NO_LVALUE_RETURN_DETECTION
# if 0 // test code
struct v {};
typedef char (&no)[3];
template <class T>
no foo(T const&, ...);
template <class T>
char foo(T&, int);
struct value_iterator
{
v operator*() const;
};
template <class T>
struct lvalue_deref_helper
{
static T& x;
enum { value = (sizeof(foo(*x,0)) == 1) };
};
int z2[(lvalue_deref_helper<v*>::value == 1) ? 1 : -1];
int z[(lvalue_deref_helper<value_iterator>::value) == 1 ? -1 : 1 ];
# endif
#endif
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) \ #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) \
|| BOOST_WORKAROUND(__GNUC__, <= 2 && __GNUC_MINOR__ <= 95) \ || BOOST_WORKAROUND(__GNUC__, <= 2 && __GNUC_MINOR__ <= 95) \

View File

@ -18,6 +18,7 @@
#undef BOOST_NO_IS_CONVERTIBLE_TEMPLATE #undef BOOST_NO_IS_CONVERTIBLE_TEMPLATE
#undef BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY #undef BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY
#undef BOOST_ARG_DEPENDENT_TYPENAME #undef BOOST_ARG_DEPENDENT_TYPENAME
#undef BOOST_NO_LVALUE_RETURN_DETECTION
#ifdef BOOST_ITERATOR_CONFIG_DEF #ifdef BOOST_ITERATOR_CONFIG_DEF
# undef BOOST_ITERATOR_CONFIG_DEF # undef BOOST_ITERATOR_CONFIG_DEF

View File

@ -0,0 +1,214 @@
// Copyright David Abrahams 2003. Use, modification and distribution is
// subject to 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 FACADE_ITERATOR_CATEGORY_DWA20031118_HPP
# define FACADE_ITERATOR_CATEGORY_DWA20031118_HPP
# include <boost/iterator/iterator_categories.hpp>
# include <boost/static_assert.hpp>
# include <boost/mpl/or.hpp> // used in iterator_tag inheritance logic
# include <boost/mpl/and.hpp>
# include <boost/mpl/if.hpp>
# include <boost/mpl/apply_if.hpp>
# include <boost/mpl/identity.hpp>
# include <boost/type_traits/is_same.hpp>
# include <boost/type_traits/is_const.hpp>
# include <boost/type_traits/is_reference.hpp>
# include <boost/type_traits/is_convertible.hpp>
# include <boost/type_traits/is_same.hpp>
# include <boost/iterator/detail/config_def.hpp> // try to keep this last
# ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY
# include <boost/python/detail/indirect_traits.hpp>
# endif
//
// iterator_category deduction for iterator_facade
//
// forward declaration
namespace boost { struct use_default; }
namespace boost { namespace detail {
struct input_output_iterator_tag
: std::input_iterator_tag
{
// Using inheritance for only input_iterator_tag helps to avoid
// ambiguities when a stdlib implementation dispatches on a
// function which is overloaded on both input_iterator_tag and
// output_iterator_tag, as STLPort does, in its __valid_range
// function. I claim it's better to avoid the ambiguity in these
// cases.
operator std::output_iterator_tag() const
{
return std::output_iterator_tag();
}
};
//
// True iff the user has explicitly disabled writability of this
// iterator. Pass the iterator_facade's Value parameter and its
// nested ::reference type.
//
template <class ValueParam, class Reference>
struct iterator_writability_disabled
# ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY // Adding Thomas' logic?
: mpl::or_<
is_const<Reference>
, python::detail::is_reference_to_const<Reference>
, is_const<ValueParam>
>
# else
: is_const<ValueParam>
# endif
{};
//
// Convert an iterator_facade's traversal category, Value parameter,
// and ::reference type to an appropriate old-style category.
//
// If writability has been disabled per the above metafunction, 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 Traversal, class ValueParam, class Reference>
struct iterator_facade_default_category
: mpl::apply_if<
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
>
>
, typename mpl::apply_if<
mpl::and_<
is_convertible<Traversal, single_pass_traversal_tag>
, mpl::or_< // check for readability
is_same<ValueParam,use_default>
, is_convertible<Reference, ValueParam>
>
>
, mpl::if_<
iterator_writability_disabled<ValueParam,Reference>
, std::input_iterator_tag
, input_output_iterator_tag
>
, mpl::identity<std::output_iterator_tag>
>
>
{
};
// True iff T is convertible to an old-style iterator category.
template <class T>
struct is_iterator_category
: mpl::or_<
is_convertible<T,std::input_iterator_tag>
, is_convertible<T,std::output_iterator_tag>
>
{
};
template <class T>
struct is_iterator_traversal
: is_convertible<T,incrementable_traversal_tag>
{};
//
// A composite iterator_category tag convertible to Category (a pure
// old-style category) and Traversal (a pure traversal tag).
// Traversal must be a strict increase of the traversal power given by
// Category.
//
template <class Category, class Traversal>
struct iterator_category_with_traversal
: Category, Traversal
{
# if 0
// Because of limitations on multiple user-defined conversions,
// this should be a good test of whether convertibility is enough
// in the spec, or whether we need to specify inheritance.
operator Category() const { return Category(); }
operator Traversal() const { return Traversal(); }
# endif
# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
// Make sure this isn't used to build any categories where
// convertibility to Traversal is redundant. Should just use the
// Category element in that case.
BOOST_STATIC_ASSERT(
!(is_convertible<
typename iterator_category_to_traversal<Category>::type
, Traversal
>::value));
BOOST_STATIC_ASSERT(is_iterator_category<Category>::value);
BOOST_STATIC_ASSERT(!is_iterator_category<Traversal>::value);
BOOST_STATIC_ASSERT(!is_iterator_traversal<Category>::value);
BOOST_STATIC_ASSERT(is_iterator_traversal<Traversal>::value);
# endif
};
// Computes an iterator_category tag whose traversal is Traversal and
// which is appropriate for an iterator
template <class Traversal, class ValueParam, class Reference>
struct facade_iterator_category_impl
{
# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
BOOST_STATIC_ASSERT(!is_iterator_category<Traversal>::value);
# endif
typedef typename iterator_facade_default_category<
Traversal,ValueParam,Reference
>::type category;
typedef typename mpl::if_<
is_same<
Traversal
, typename iterator_category_to_traversal<category>::type
>
, category
, iterator_category_with_traversal<category,Traversal>
>::type type;
};
//
// Compute an iterator_category for iterator_facade
//
template <class CategoryOrTraversal, class ValueParam, class Reference>
struct facade_iterator_category
: mpl::apply_if<
is_iterator_category<CategoryOrTraversal>
, mpl::identity<CategoryOrTraversal> // old-style categories are fine as-is
, facade_iterator_category_impl<CategoryOrTraversal,ValueParam,Reference>
>
{
};
}} // namespace boost::detail
# include <boost/iterator/detail/config_undef.hpp>
#endif // FACADE_ITERATOR_CATEGORY_DWA20031118_HPP

View File

@ -0,0 +1,98 @@
// Copyright David Abrahams 2003. Use, modification and distribution is
// subject to 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 MINIMUM_CATEGORY_DWA20031119_HPP
# define MINIMUM_CATEGORY_DWA20031119_HPP
# include <boost/type_traits/is_convertible.hpp>
# include <boost/type_traits/is_same.hpp>
# include <boost/mpl/aux_/lambda_support.hpp>
namespace boost { namespace detail {
//
// 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 <bool GreaterEqual, bool LessEqual>
struct minimum_category_impl;
template <class T1, class T2>
struct error_not_related_by_convertibility;
template <>
struct minimum_category_impl<true,false>
{
template <class T1, class T2> struct apply
{
typedef T2 type;
};
};
template <>
struct minimum_category_impl<false,true>
{
template <class T1, class T2> struct apply
{
typedef T1 type;
};
};
template <>
struct minimum_category_impl<true,true>
{
template <class T1, class T2> struct apply
{
BOOST_STATIC_ASSERT((is_same<T1,T2>::value));
typedef T1 type;
};
};
template <>
struct minimum_category_impl<false,false>
{
template <class T1, class T2> struct apply
: error_not_related_by_convertibility<T1,T2>
{
};
};
template <class T1 = mpl::_1, class T2 = mpl::_2>
struct minimum_category
{
typedef minimum_category_impl<
::boost::is_convertible<T1,T2>::value
, ::boost::is_convertible<T2,T1>::value
> outer;
typedef typename outer::template apply<T1,T2> inner;
typedef typename inner::type type;
BOOST_MPL_AUX_LAMBDA_SUPPORT(2,minimum_category,(T1,T2))
};
template <>
struct minimum_category<mpl::_1,mpl::_2>
{
template <class T1, class T2>
struct apply : minimum_category<T1,T2>
{};
};
# if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
template <>
struct minimum_category<int,int>
{
typedef int type;
};
# endif
}} // namespace boost::detail
#endif // MINIMUM_CATEGORY_DWA20031119_HPP

View File

@ -13,28 +13,42 @@
#include <boost/iterator/iterator_adaptor.hpp> #include <boost/iterator/iterator_adaptor.hpp>
#include <boost/iterator/iterator_categories.hpp> #include <boost/iterator/iterator_categories.hpp>
#include <boost/type_traits/is_class.hpp>
#include <boost/static_assert.hpp>
namespace boost namespace boost
{ {
template <class Predicate, class Iterator>
class filter_iterator;
namespace detail
{
template <class Predicate, class Iterator>
struct filter_iterator_base
{
typedef iterator_adaptor<
filter_iterator<Predicate, Iterator>
, Iterator
, use_default
, typename mpl::if_<
is_convertible<
typename iterator_traversal<Iterator>::type
, bidirectional_traversal_tag
>
, forward_traversal_tag
, use_default
>::type
> type;
};
}
template <class Predicate, class Iterator> template <class Predicate, class Iterator>
class filter_iterator class filter_iterator
: public iterator_adaptor< : public detail::filter_iterator_base<Predicate, Iterator>::type
filter_iterator<Predicate, Iterator>, Iterator
, use_default
, typename detail::minimum_category<
bidirectional_traversal_tag
, typename traversal_category<Iterator>::type
>::type
>
{ {
typedef iterator_adaptor< typedef typename detail::filter_iterator_base<
filter_iterator<Predicate, Iterator>, Iterator Predicate, Iterator
, use_default >::type super_t;
, typename detail::minimum_category<
bidirectional_traversal_tag
, typename traversal_category<Iterator>::type
>::type
> super_t;
friend class iterator_core_access; friend class iterator_core_access;

View File

@ -4,16 +4,19 @@
#ifndef IS_LVALUE_ITERATOR_DWA2003112_HPP #ifndef IS_LVALUE_ITERATOR_DWA2003112_HPP
# define IS_LVALUE_ITERATOR_DWA2003112_HPP # define IS_LVALUE_ITERATOR_DWA2003112_HPP
#include <boost/mpl/bool.hpp>
#include <boost/detail/iterator.hpp>
#include <boost/iterator.hpp> #include <boost/iterator.hpp>
#include <boost/type_traits/detail/bool_trait_def.hpp> #include <boost/detail/workaround.hpp>
#include <boost/detail/iterator.hpp>
#include <boost/iterator/detail/any_conversion_eater.hpp> #include <boost/iterator/detail/any_conversion_eater.hpp>
// should be the last #include // should be the last #includes
#include <boost/type_traits/detail/bool_trait_def.hpp>
#include <boost/iterator/detail/config_def.hpp> #include <boost/iterator/detail/config_def.hpp>
#ifndef BOOST_NO_IS_CONVERTIBLE
namespace boost { namespace boost {
namespace detail namespace detail
@ -122,7 +125,7 @@ namespace detail
{}; {};
template <class It> template <class It>
struct is_mutable_lvalue_iterator_impl struct is_non_const_lvalue_iterator_impl
: is_lvalue_iterator_impl< : is_lvalue_iterator_impl<
BOOST_DEDUCED_TYPENAME boost::detail::iterator_traits<It>::value_type BOOST_DEDUCED_TYPENAME boost::detail::iterator_traits<It>::value_type
>::template rebind<It> >::template rebind<It>
@ -135,10 +138,13 @@ BOOST_TT_AUX_BOOL_TRAIT_DEF1(
is_lvalue_iterator,T,::boost::detail::is_readable_lvalue_iterator_impl<T>::value) is_lvalue_iterator,T,::boost::detail::is_readable_lvalue_iterator_impl<T>::value)
BOOST_TT_AUX_BOOL_TRAIT_DEF1( BOOST_TT_AUX_BOOL_TRAIT_DEF1(
is_mutable_lvalue_iterator,T,::boost::detail::is_mutable_lvalue_iterator_impl<T>::value) is_non_const_lvalue_iterator,T,::boost::detail::is_non_const_lvalue_iterator_impl<T>::value)
} // namespace boost } // namespace boost
#endif
#include <boost/iterator/detail/config_undef.hpp> #include <boost/iterator/detail/config_undef.hpp>
#include <boost/type_traits/detail/bool_trait_undef.hpp>
#endif // IS_LVALUE_ITERATOR_DWA2003112_HPP #endif // IS_LVALUE_ITERATOR_DWA2003112_HPP

View File

@ -13,6 +13,8 @@
// should be the last #include // should be the last #include
#include <boost/iterator/detail/config_def.hpp> #include <boost/iterator/detail/config_def.hpp>
#ifndef BOOST_NO_IS_CONVERTIBLE
namespace boost { namespace boost {
namespace detail namespace detail
@ -99,6 +101,8 @@ BOOST_TT_AUX_BOOL_TRAIT_DEF1(
} // namespace boost } // namespace boost
#endif
#include <boost/iterator/detail/config_undef.hpp> #include <boost/iterator/detail/config_undef.hpp>
#endif // IS_READABLE_ITERATOR_DWA2003112_HPP #endif // IS_READABLE_ITERATOR_DWA2003112_HPP

View File

@ -26,12 +26,32 @@
#include <boost/type_traits/is_same.hpp> #include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_convertible.hpp> #include <boost/type_traits/is_convertible.hpp>
#ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY
# include <boost/type_traits/remove_reference.hpp>
#else
# include <boost/type_traits/add_reference.hpp>
#endif
#include <boost/iterator/detail/config_def.hpp> #include <boost/iterator/detail/config_def.hpp>
#include <boost/iterator/iterator_traits.hpp> #include <boost/iterator/iterator_traits.hpp>
namespace boost 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 namespace detail
{ {
@ -142,63 +162,51 @@ namespace boost
class Derived class Derived
, class Base , class Base
, class Value , class Value
, class Category , class Traversal
, class Reference , class Reference
, class Difference , class Difference
> >
struct iterator_adaptor_base struct iterator_adaptor_base
{ {
private: // intermediate results
typedef typename mpl::apply_if<
mpl::or_<
is_same<Category, use_default>
, mpl::or_<
is_access_tag<Category>
, is_traversal_tag<Category>
>
>
, BOOST_ITERATOR_CATEGORY<Base>
, mpl::identity<Category>
>::type category;
typedef typename detail::ia_dflt_help<
Reference
, mpl::apply_if<
is_same<Value, use_default>
, iterator_reference<Base>
, mpl::identity<Value&>
>
>::type reference;
public: // return type
typedef iterator_facade< typedef iterator_facade<
Derived Derived
# ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY
, typename detail::ia_dflt_help<
Value
, mpl::apply_if<
is_same<Reference,use_default>
, iterator_value<Base>
, remove_reference<Reference>
>
>::type
# else
, typename detail::ia_dflt_help< , typename detail::ia_dflt_help<
Value, iterator_value<Base> Value, iterator_value<Base>
>::type >::type
# endif
, typename mpl::apply_if<
is_access_tag<Category> , typename detail::ia_dflt_help<
, mpl::identity<Category> Traversal
, access_category_tag<category, reference> , iterator_traversal<Base>
>::type >::type
, typename detail::ia_dflt_help<
Reference
, mpl::apply_if<
is_same<Value,use_default>
, iterator_reference<Base>
, add_reference<Value>
>
>::type
, typename mpl::apply_if<
is_traversal_tag<Category>
, mpl::identity<Category>
, traversal_category_tag<category>
>::type
, reference
, typename detail::ia_dflt_help< , typename detail::ia_dflt_help<
Difference, iterator_difference<Base> Difference, iterator_difference<Base>
>::type >::type
> >
type; type;
}; };
template <class T> int static_assert_convertible_to(T);
} }
// //
@ -215,8 +223,8 @@ namespace boost
// const. If const, a conforming compiler strips constness for the // const. If const, a conforming compiler strips constness for the
// value_type. If not supplied, iterator_traits<Base>::value_type is used // value_type. If not supplied, iterator_traits<Base>::value_type is used
// //
// Category - the iterator_category of the resulting iterator. If not // Category - the traversal category of the resulting iterator. If not
// supplied, iterator_traits<Base>::iterator_category is used. // supplied, iterator_traversal<Base>::type is used.
// //
// Reference - the reference type of the resulting iterator, and in // Reference - the reference type of the resulting iterator, and in
// particular, the result type of operator*(). If not supplied but // particular, the result type of operator*(). If not supplied but
@ -230,19 +238,19 @@ namespace boost
class Derived class Derived
, class Base , class Base
, class Value = use_default , class Value = use_default
, class Category = use_default , class Traversal = use_default
, class Reference = use_default , class Reference = use_default
, class Difference = use_default , class Difference = use_default
> >
class iterator_adaptor class iterator_adaptor
: public detail::iterator_adaptor_base< : public detail::iterator_adaptor_base<
Derived, Base, Value, Category, Reference, Difference Derived, Base, Value, Traversal, Reference, Difference
>::type >::type
{ {
friend class iterator_core_access; friend class iterator_core_access;
typedef typename detail::iterator_adaptor_base< typedef typename detail::iterator_adaptor_base<
Derived, Base, Value, Category, Reference, Difference Derived, Base, Value, Traversal, Reference, Difference
>::type super_t; >::type super_t;
public: public:
@ -287,17 +295,18 @@ namespace boost
// ); // );
return m_iterator == x.base(); 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) \
typedef int assertion[sizeof(detail::static_assert_convertible_to<cat>(my_traversal()))];
// BOOST_STATIC_ASSERT((is_convertible<my_traversal,cat>::value));
void advance(typename super_t::difference_type n) void advance(typename super_t::difference_type n)
{ {
# if !BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) // seems to get instantiated incorrectly BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(random_access_traversal_tag)
BOOST_STATIC_ASSERT(
(detail::is_tag<
random_access_traversal_tag
, BOOST_ARG_DEPENDENT_TYPENAME super_t::iterator_category::traversal
>::value)
);
# endif
m_iterator += n; m_iterator += n;
} }
@ -305,14 +314,7 @@ namespace boost
void decrement() void decrement()
{ {
# if !BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) // seems to get instantiated incorrectly BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(bidirectional_traversal_tag)
BOOST_STATIC_ASSERT(
(detail::is_tag<
bidirectional_traversal_tag
, BOOST_ARG_DEPENDENT_TYPENAME super_t::iterator_category::traversal
>::value)
);
# endif
--m_iterator; --m_iterator;
} }
@ -322,12 +324,7 @@ namespace boost
typename super_t::difference_type distance_to( typename super_t::difference_type distance_to(
iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& y) const iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& y) const
{ {
BOOST_STATIC_ASSERT( BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(random_access_traversal_tag)
(detail::is_tag<
random_access_traversal_tag
, BOOST_ARG_DEPENDENT_TYPENAME super_t::iterator_category::traversal
>::value)
);
// Maybe readd with same_distance // Maybe readd with same_distance
// BOOST_STATIC_ASSERT( // BOOST_STATIC_ASSERT(
// (detail::same_category_and_difference<Derived,OtherDerived>::value) // (detail::same_category_and_difference<Derived,OtherDerived>::value)
@ -335,6 +332,8 @@ namespace boost
return y.base() - m_iterator; return y.base() - m_iterator;
} }
# undef BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL
private: // data members private: // data members
Base m_iterator; Base m_iterator;
}; };

View File

@ -8,341 +8,449 @@
#define BOOST_ITERATOR_ARCHETYPES_HPP #define BOOST_ITERATOR_ARCHETYPES_HPP
#include <boost/iterator/iterator_categories.hpp> #include <boost/iterator/iterator_categories.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/and.hpp>
#include <boost/operators.hpp> #include <boost/operators.hpp>
#include <boost/static_assert.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/is_const.hpp>
#include <boost/type_traits/add_const.hpp>
#include <boost/type_traits/remove_const.hpp> #include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/remove_cv.hpp> #include <boost/type_traits/remove_cv.hpp>
#include <boost/mpl/aux_/msvc_eti_base.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/apply_if.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/identity.hpp>
#include <cstddef> #include <cstddef>
namespace boost 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
};
template <class Value, class AccessCategory> // Not quite tags, since dispatching wouldn't work.
struct access_archetype; 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 Value, class AccessCategory, class TraversalCategory> template <class Derived, class Base>
struct traversal_archetype; struct has_access
: mpl::equal_to<
mpl::bitand_<Derived,Base>
, Base
>
{};
}
namespace detail { namespace detail
{
template <class T> template <class T>
struct assign_proxy struct assign_proxy
{ {
assign_proxy& operator=(T); assign_proxy& operator=(T);
}; };
template <class T> template <class T>
struct read_write_proxy : struct read_proxy
assign_proxy<T> {
{
operator T(); operator T();
}; };
template <class T> template <class T>
struct arrow_proxy struct read_write_proxy
{ : assign_proxy<T>
, read_proxy<T>
{
};
template <class T>
struct arrow_proxy
{
T const* operator->() const; T const* operator->() const;
}; };
struct no_operator_brackets {}; struct no_operator_brackets {};
template <class ValueType> template <class ValueType>
struct readable_operator_brackets struct readable_operator_brackets
{ {
ValueType operator[](std::ptrdiff_t n) const; read_proxy<ValueType> operator[](std::ptrdiff_t n) const;
}; };
template <class ValueType> template <class ValueType>
struct writable_operator_brackets struct writable_operator_brackets
{ {
read_write_proxy<ValueType> operator[](std::ptrdiff_t n) const; read_write_proxy<ValueType> operator[](std::ptrdiff_t n) const;
}; };
template <class Value, class AccessCategory, class TraversalCategory> template <class Value, class AccessCategory, class TraversalCategory>
struct operator_brackets : struct operator_brackets
mpl::if_< is_tag<random_access_traversal_tag, TraversalCategory>, : mpl::aux::msvc_eti_base<
mpl::if_< is_tag<writable_iterator_tag, AccessCategory>, typename mpl::apply_if<
writable_operator_brackets< Value >, is_convertible<TraversalCategory, random_access_traversal_tag>
mpl::if_< is_tag<readable_iterator_tag, AccessCategory>, , mpl::apply_if<
readable_operator_brackets<Value>, iterator_archetypes::has_access<
no_operator_brackets > >, AccessCategory
no_operator_brackets >::type , 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;
};
template <class TraversalCategory> template <class Derived, class Value, class TraversalCategory>
struct traversal_archetype_impl struct traversal_archetype_
{ : mpl::aux::msvc_eti_base<
template <class Derived,class Value> struct archetype; typename traversal_archetype_impl<TraversalCategory>::template archetype<Derived,Value>
}; >::type
{};
template <class Derived, class Value, class TraversalCategory> template <>
struct traversal_archetype_ struct traversal_archetype_impl<incrementable_traversal_tag>
: mpl::aux::msvc_eti_base< {
typename traversal_archetype_impl<TraversalCategory>::template archetype<Derived,Value> template<class Derived, class Value>
>::type struct archetype
{}; {
typedef void difference_type;
template <> Derived& operator++();
struct traversal_archetype_impl<incrementable_traversal_tag> Derived operator++(int) const;
{ };
template<class Derived, class Value> };
struct archetype
{
typedef void difference_type;
Derived& operator++(); template <>
Derived operator++(int) const; 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>
{
};
};
template <> template <class Derived, class Value>
struct traversal_archetype_impl<single_pass_traversal_tag> bool operator==(traversal_archetype_<Derived, Value, single_pass_traversal_tag> const&,
{ traversal_archetype_<Derived, Value, single_pass_traversal_tag> const&);
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>
{
};
};
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&);
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
// doesn't seem to pick up != from equality_comparable // doesn't seem to pick up != from equality_comparable
template <class Derived, class Value> template <class Derived, class Value>
bool operator!=(traversal_archetype_<Derived, Value, single_pass_traversal_tag> const&, bool operator!=(traversal_archetype_<Derived, Value, single_pass_traversal_tag> const&,
traversal_archetype_<Derived, Value, single_pass_traversal_tag> const&); traversal_archetype_<Derived, Value, single_pass_traversal_tag> const&);
#endif #endif
template <> template <>
struct traversal_archetype_impl<forward_traversal_tag> struct traversal_archetype_impl<forward_traversal_tag>
{ {
template<class Derived, class Value> template<class Derived, class Value>
struct archetype struct archetype
: public traversal_archetype_<Derived, Value, single_pass_traversal_tag> : public traversal_archetype_<Derived, Value, single_pass_traversal_tag>
{ {
typedef std::ptrdiff_t difference_type; typedef std::ptrdiff_t difference_type;
}; };
}; };
template <> template <>
struct traversal_archetype_impl<bidirectional_traversal_tag> struct traversal_archetype_impl<bidirectional_traversal_tag>
{ {
template<class Derived, class Value> template<class Derived, class Value>
struct archetype struct archetype
: public traversal_archetype_<Derived, Value, forward_traversal_tag> : public traversal_archetype_<Derived, Value, forward_traversal_tag>
{ {
Derived& operator--(); Derived& operator--();
Derived operator--(int) const; Derived operator--(int) const;
}; };
}; };
template <> template <>
struct traversal_archetype_impl<random_access_traversal_tag> struct traversal_archetype_impl<random_access_traversal_tag>
{ {
template<class Derived, class Value> template<class Derived, class Value>
struct archetype struct archetype
: public partially_ordered<traversal_archetype_<Derived, Value, random_access_traversal_tag> >, : public partially_ordered<traversal_archetype_<Derived, Value, random_access_traversal_tag> >,
public traversal_archetype_<Derived, Value, bidirectional_traversal_tag> public traversal_archetype_<Derived, Value, bidirectional_traversal_tag>
{ {
Derived& operator+=(std::ptrdiff_t); Derived& operator+=(std::ptrdiff_t);
Derived& operator-=(std::ptrdiff_t); Derived& operator-=(std::ptrdiff_t);
}; };
}; };
template <class Derived, class Value> template <class Derived, class Value>
Derived& operator+(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&, Derived& operator+(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
std::ptrdiff_t); std::ptrdiff_t);
template <class Derived, class Value> template <class Derived, class Value>
Derived& operator+(std::ptrdiff_t, Derived& operator+(std::ptrdiff_t,
traversal_archetype_<Derived, Value, random_access_traversal_tag> const&); traversal_archetype_<Derived, Value, random_access_traversal_tag> const&);
template <class Derived, class Value> template <class Derived, class Value>
Derived& operator-(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&, Derived& operator-(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
std::ptrdiff_t); std::ptrdiff_t);
template <class Derived, class Value> template <class Derived, class Value>
std::ptrdiff_t operator-(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&, std::ptrdiff_t operator-(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
traversal_archetype_<Derived, Value, random_access_traversal_tag> const&); traversal_archetype_<Derived, Value, random_access_traversal_tag> const&);
template <class Derived, class Value> template <class Derived, class Value>
bool operator<(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&, bool operator<(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
traversal_archetype_<Derived, Value, random_access_traversal_tag> const&); traversal_archetype_<Derived, Value, random_access_traversal_tag> const&);
struct bogus_type; 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> template <class Value>
struct convertible_type struct archetype
: mpl::if_< is_const<Value>, {
typename remove_const<Value>::type, typedef typename remove_cv<Value>::type value_type;
bogus_type > typedef Value reference;
{}; typedef Value* pointer;
} // namespace detail value_type operator*() const;
detail::arrow_proxy<Value> operator->() const;
};
};
template <class> struct undefined; template <>
struct iterator_access_archetype_impl<
template <class AccessCategory> iterator_archetypes::writable_iterator_t
struct access_archetype_impl >
{ {
template <class Value> struct archetype; template <class Value>
}; struct archetype
{
template <class Value, class AccessCategory>
struct access_archetype
: mpl::aux::msvc_eti_base<
typename access_archetype_impl<AccessCategory>::template archetype<Value>
>::type
{
};
template <>
struct access_archetype_impl<readable_iterator_tag>
{
template <class Value>
struct archetype
{
typedef typename remove_cv<Value>::type value_type;
typedef Value reference;
typedef Value* pointer;
value_type operator*() const;
detail::arrow_proxy<Value> operator->() const;
};
};
template <>
struct access_archetype_impl<writable_iterator_tag>
{
template <class Value>
struct archetype
{
# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) # if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
BOOST_STATIC_ASSERT(!is_const<Value>::value); BOOST_STATIC_ASSERT(!is_const<Value>::value);
# endif # endif
typedef void value_type; typedef void value_type;
typedef void reference; typedef void reference;
typedef void pointer; typedef void pointer;
detail::assign_proxy<Value> operator*() const; detail::assign_proxy<Value> operator*() const;
}; };
}; };
template <> template <>
struct access_archetype_impl<readable_writable_iterator_tag> struct iterator_access_archetype_impl<
{ iterator_archetypes::readable_writable_iterator_t
template <class Value> >
struct archetype {
: public virtual access_archetype<Value, readable_iterator_tag> template <class Value>
{ struct archetype
typedef detail::read_write_proxy<Value> reference; : public virtual iterator_access_archetype<
Value, iterator_archetypes::readable_iterator_t
detail::read_write_proxy<Value> operator*() const;
};
};
template <>
struct access_archetype_impl<readable_lvalue_iterator_tag>
{
template <class Value>
struct archetype
: public virtual access_archetype<Value, readable_iterator_tag>
{
typedef Value& reference;
Value& operator*() const;
Value* operator->() const;
};
};
template <>
struct access_archetype_impl<writable_lvalue_iterator_tag>
{
template <class Value>
struct archetype
: public virtual access_archetype<Value, readable_lvalue_iterator_tag>
{
# 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
> >
{ {
}; typedef detail::read_write_proxy<Value> reference;
template <class Value, class AccessCategory, class TraversalCategory> detail::read_write_proxy<Value> operator*() const;
struct iterator_archetype };
: public traversal_archetype_base<Value, AccessCategory, TraversalCategory> };
, public access_archetype<Value, AccessCategory>
// These broken libraries require derivation from std::iterator template <>
// (or related magic) in order to handle iter_swap and other struct iterator_access_archetype_impl<iterator_archetypes::readable_lvalue_iterator_t>
// iterator operations {
# if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, < 310) \ template <class Value>
|| BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(0x20101)) struct archetype
, public std::iterator< : public virtual iterator_access_archetype<
iterator_tag<AccessCategory,TraversalCategory> Value, iterator_archetypes::readable_iterator_t
, typename access_archetype<Value, AccessCategory>::value_type >
, typename traversal_archetype_base< {
Value, AccessCategory, TraversalCategory typedef Value& reference;
>::difference_type
> Value& operator*() const;
Value* operator->() const;
};
};
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 # 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>
{ {
// Derivation from std::iterator above caused ambiguity, so now typedef iterator_access_archetype<Value, AccessCategory> access;
// we have to declare all the types here.
typedef typename detail::facade_iterator_category<
TraversalCategory
, typename mpl::apply_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) \ # if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, < 310) \
|| BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(0x20101)) || BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(0x20101))
typedef typename access_archetype<Value, AccessCategory>::value_type value_type; , public detail::iterator_archetype_base<
Value, AccessCategory, TraversalCategory
typedef typename access_archetype<Value, AccessCategory>::pointer pointer; >::workaround_iterator_base
# endif
typedef typename access_archetype<Value, AccessCategory>::reference reference; {
// Derivation from std::iterator above caused references to nested
typedef typename traversal_archetype_base< // types to be ambiguous, so now we have to redeclare them all
Value, AccessCategory, TraversalCategory // here.
>::difference_type difference_type; # 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 # endif
typedef iterator_tag<AccessCategory, TraversalCategory> iterator_category;
iterator_archetype(); iterator_archetype();
iterator_archetype(iterator_archetype const&); iterator_archetype(iterator_archetype const&);
iterator_archetype& operator=(iterator_archetype const&); iterator_archetype& operator=(iterator_archetype const&);
// Optional conversion from mutable // Optional conversion from mutable
// iterator_archetype(iterator_archetype<typename detail::convertible_type<Value>::type, AccessCategory, TraversalCategory> const&); // iterator_archetype(iterator_archetype<typename detail::convertible_type<Value>::type, AccessCategory, TraversalCategory> const&);
}; };
} // namespace boost } // namespace boost

View File

@ -4,425 +4,159 @@
// "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/apply_if.hpp>
# include <boost/mpl/identity.hpp>
#include <boost/detail/iterator.hpp>
#include <boost/detail/workaround.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_convertible.hpp>
#include <boost/iterator/detail/config_def.hpp> // must be last #include # include <boost/static_assert.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
// Helper metafunction for std_category below //
template <class Cat, class Tag, class Next> struct incrementable_traversal_tag {};
struct match_tag
: mpl::apply_if<is_tag<Tag, Cat>, mpl::identity<Tag>, Next>
{
};
// 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
: mpl::identity<readable_iterator_tag> {};
};
template <>
struct std_to_new_tags<std::output_iterator_tag>
{
typedef incrementable_traversal_tag type;
template <class Reference>
struct apply
: mpl::identity<writable_iterator_tag> {};
};
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>
, boost::readable_lvalue_iterator_tag
, boost::writable_lvalue_iterator_tag
>
{};
};
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<
typename std_category<Category>::type
>
{
};
template <typename Category>
struct iter_category_to_traversal
: std_to_new_tags<
typename std_category<Category>::type
>
{};
template <typename Category, typename Reference>
struct iter_category_to_access
: mpl::apply1<
iter_category_to_traversal<Category>
, Reference
>
{};
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
// Deal with ETI
template <> struct iter_category_to_access<int, int> {};
template <> struct iter_category_to_traversal<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 { struct single_pass_traversal_tag
: incrementable_traversal_tag {};
template <class NewCategoryTag>
struct get_traversal_category {
typedef typename NewCategoryTag::traversal type;
};
// Remove all writability from the given access tag. This
// functionality is part of new_category_to_access in order to
// support deduction of the proper default access category for
// iterator_adaptor; when the reference type is a reference to
// constant we must strip writability.
template <class AccessTag>
struct remove_access_writability
: mpl::apply_if<
is_tag<writable_lvalue_iterator_tag, AccessTag>
, mpl::identity<readable_lvalue_iterator_tag>
, mpl::apply_if<
is_tag<readable_writable_iterator_tag, AccessTag>
, mpl::identity<readable_iterator_tag>
, mpl::if_<
is_tag<writable_iterator_tag, AccessTag>
// Is this OK? I think it may correct be for all
// legitimate cases, because at this point the
// iterator is not readable, so it could not have
// been any more than writable + swappable.
, swappable_iterator_tag
, AccessTag
>
>
>
{};
template <class NewCategoryTag, class Reference> struct forward_traversal_tag
struct new_category_to_access : single_pass_traversal_tag {};
: mpl::apply_if<
python::detail::is_reference_to_const<Reference> struct bidirectional_traversal_tag
, remove_access_writability<typename NewCategoryTag::access> : forward_traversal_tag {};
, mpl::identity<typename NewCategoryTag::access>
> struct random_access_traversal_tag
{}; : bidirectional_traversal_tag {};
template <class CategoryTag, class Reference> namespace detail
struct access_category_tag {
: mpl::apply_if< //
is_new_iterator_tag<CategoryTag> // Convert a "strictly old-style" iterator category to a traversal
, new_category_to_access<CategoryTag, Reference> // tag. This is broken out into a separate metafunction to reduce
, iter_category_to_access<CategoryTag, Reference> // the cost of instantiating iterator_category_to_traversal, below,
// for new-style types.
//
template <class Cat>
struct old_category_to_traversal
: mpl::apply_if<
is_convertible<Cat,std::random_access_iterator_tag>
, mpl::identity<random_access_traversal_tag>
, mpl::apply_if<
is_convertible<Cat,std::bidirectional_iterator_tag>
, mpl::identity<bidirectional_traversal_tag>
, mpl::apply_if<
is_convertible<Cat,std::forward_iterator_tag>
, mpl::identity<forward_traversal_tag>
, mpl::apply_if<
is_convertible<Cat,std::input_iterator_tag>
, mpl::identity<single_pass_traversal_tag>
, mpl::apply_if<
is_convertible<Cat,std::output_iterator_tag>
, mpl::identity<incrementable_traversal_tag>
, void
>
>
>
> >
{ >
};
template <class CategoryTag>
struct traversal_category_tag
: mpl::apply_if<
is_new_iterator_tag<CategoryTag>
, get_traversal_category<CategoryTag>
, iter_category_to_traversal<CategoryTag>
>
{
};
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
// Deal with ETI
template <> struct access_category_tag<int, int> { typedef void type; };
template <> struct traversal_category_tag<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
// specialization for this special case. Otherwise we get
// input_output_iterator_tag, because the standard hierarchy has a
// sudden anomalous distinction between readability and
// writability at the level of input iterator/output iterator.
template <>
struct iterator_tag_base<
readable_lvalue_iterator_tag,single_pass_traversal_tag>
{
typedef std::input_iterator_tag type;
};
} // namespace detail
template <class Iterator>
struct access_category
: detail::access_category_tag<
typename detail::iterator_traits<Iterator>::iterator_category
, typename detail::iterator_traits<Iterator>::reference>
{}; {};
template <class Iterator> # if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
struct traversal_category template <>
: detail::traversal_category_tag< struct old_category_to_traversal<int>
typename detail::iterator_traits<Iterator>::iterator_category {
typedef int type;
};
# endif
template <class Traversal>
struct pure_traversal_tag
: mpl::apply_if<
is_convertible<Traversal,random_access_traversal_tag>
, mpl::identity<random_access_traversal_tag>
, mpl::apply_if<
is_convertible<Traversal,bidirectional_traversal_tag>
, mpl::identity<bidirectional_traversal_tag>
, mpl::apply_if<
is_convertible<Traversal,forward_traversal_tag>
, mpl::identity<forward_traversal_tag>
, mpl::apply_if<
is_convertible<Traversal,single_pass_traversal_tag>
, mpl::identity<single_pass_traversal_tag>
, mpl::apply_if<
is_convertible<Traversal,incrementable_traversal_tag>
, mpl::identity<incrementable_traversal_tag>
, void
>
>
>
>
> >
{ {
}; };
# if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
template <>
struct pure_traversal_tag<int>
{
typedef int type;
};
# endif
} // namespace detail
//
// Convert an iterator category into a traversal tag
//
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_category_to_traversal<Cat>
>
{};
// 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>
, readable_lvalue_iterator_tag
, writable_lvalue_iterator_tag>
{
};
template <typename T>
struct traversal_category<T*>
{
typedef random_access_traversal_tag type;
};
# endif
template <class AccessTag, class TraversalTag>
struct iterator_tag
: detail::iterator_tag_base<
typename detail::max_known_access_tag<AccessTag>::type
, typename detail::max_known_traversal_tag<TraversalTag>::type
>::type
{
typedef AccessTag access;
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 <class R, class T> template <>
struct is_boost_iterator_tag<iterator_tag<R,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 <class R, class U>
static yes test(mpl::identity<iterator_tag<R,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

View File

@ -15,16 +15,20 @@
#include <boost/concept_check.hpp> #include <boost/concept_check.hpp>
#include <boost/iterator/iterator_categories.hpp> #include <boost/iterator/iterator_categories.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/and.hpp>
#include <boost/static_assert.hpp>
// Use boost::detail::iterator_traits to work around some MSVC/Dinkumware problems. // Use boost::detail::iterator_traits to work around some MSVC/Dinkumware problems.
#include <boost/detail/iterator.hpp> #include <boost/detail/iterator.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/or.hpp>
#include <boost/static_assert.hpp>
// Use boost/limits to work around missing limits headers on some compilers // Use boost/limits to work around missing limits headers on some compilers
#include <boost/limits.hpp> #include <boost/limits.hpp>
@ -56,7 +60,6 @@ namespace boost_concepts {
public: public:
typedef BOOST_DEDUCED_TYPENAME ::boost::detail::iterator_traits<Iterator>::value_type value_type; typedef BOOST_DEDUCED_TYPENAME ::boost::detail::iterator_traits<Iterator>::value_type value_type;
typedef BOOST_DEDUCED_TYPENAME ::boost::detail::iterator_traits<Iterator>::reference reference; typedef BOOST_DEDUCED_TYPENAME ::boost::detail::iterator_traits<Iterator>::reference reference;
typedef BOOST_DEDUCED_TYPENAME ::boost::access_category<Iterator>::type access_category;
void constraints() { void constraints() {
boost::function_requires< boost::SGIAssignableConcept<Iterator> >(); boost::function_requires< boost::SGIAssignableConcept<Iterator> >();
@ -64,8 +67,6 @@ namespace boost_concepts {
boost::function_requires< boost::function_requires<
boost::DefaultConstructibleConcept<Iterator> >(); boost::DefaultConstructibleConcept<Iterator> >();
BOOST_STATIC_ASSERT((boost::detail::is_tag<boost::readable_iterator_tag, access_category>::value));
reference r = *i; // or perhaps read(x) reference r = *i; // or perhaps read(x)
value_type v(r); value_type v(r);
boost::ignore_unused_variable_warning(v); boost::ignore_unused_variable_warning(v);
@ -73,19 +74,19 @@ namespace boost_concepts {
Iterator i; Iterator i;
}; };
template <typename Iterator, typename ValueType> template <
typename Iterator
, typename ValueType = typename boost::detail::iterator_traits<Iterator>::value_type
>
class WritableIteratorConcept { class WritableIteratorConcept {
public: public:
typedef typename boost::access_category<Iterator>::type access_category;
void constraints() { void constraints() {
boost::function_requires< boost::SGIAssignableConcept<Iterator> >(); boost::function_requires< boost::SGIAssignableConcept<Iterator> >();
boost::function_requires< boost::EqualityComparableConcept<Iterator> >(); boost::function_requires< boost::EqualityComparableConcept<Iterator> >();
boost::function_requires< boost::function_requires<
boost::DefaultConstructibleConcept<Iterator> >(); boost::DefaultConstructibleConcept<Iterator> >();
BOOST_STATIC_ASSERT((boost::detail::is_tag<boost::writable_iterator_tag, access_category>::value));
*i = v; // a good alternative could be something like write(x, v) *i = v; // a good alternative could be something like write(x, v)
} }
ValueType v; ValueType v;
@ -95,11 +96,8 @@ namespace boost_concepts {
template <typename Iterator> template <typename Iterator>
class SwappableIteratorConcept { class SwappableIteratorConcept {
public: public:
typedef typename boost::access_category<Iterator>::type access_category;
void constraints() { void constraints() {
BOOST_STATIC_ASSERT((boost::detail::is_tag<boost::swappable_iterator_tag, access_category>::value));
std::iter_swap(i1, i2); std::iter_swap(i1, i2);
} }
Iterator i1; Iterator i1;
@ -107,25 +105,25 @@ namespace boost_concepts {
}; };
template <typename Iterator> template <typename Iterator>
class ReadableLvalueIteratorConcept { class ReadableLvalueIteratorConcept
public: {
typedef typename boost::detail::iterator_traits<Iterator>::value_type value_type; public:
typedef typename boost::detail::iterator_traits<Iterator>::reference reference; typedef typename boost::detail::iterator_traits<Iterator>::value_type value_type;
typedef typename boost::access_category<Iterator>::type access_category; typedef typename boost::detail::iterator_traits<Iterator>::reference reference;
void constraints() { void constraints()
boost::function_requires< ReadableIteratorConcept<Iterator> >(); {
boost::function_requires< ReadableIteratorConcept<Iterator> >();
BOOST_STATIC_ASSERT((boost::detail::is_tag<boost::readable_lvalue_iterator_tag, access_category>::value)); typedef boost::mpl::or_<
boost::is_same<reference, value_type&>
typedef boost::mpl::or_< , boost::is_same<reference, value_type const&>
boost::is_same<reference, value_type&>, > correct_reference;
boost::is_same<reference, value_type const&> > correct_reference;
BOOST_STATIC_ASSERT(correct_reference::value); BOOST_STATIC_ASSERT(correct_reference::value);
reference v = *i; reference v = *i;
boost::ignore_unused_variable_warning(v); boost::ignore_unused_variable_warning(v);
} }
Iterator i; Iterator i;
}; };
@ -135,7 +133,6 @@ namespace boost_concepts {
public: public:
typedef typename boost::detail::iterator_traits<Iterator>::value_type value_type; typedef typename boost::detail::iterator_traits<Iterator>::value_type value_type;
typedef typename boost::detail::iterator_traits<Iterator>::reference reference; typedef typename boost::detail::iterator_traits<Iterator>::reference reference;
typedef typename boost::access_category<Iterator>::type access_category;
void constraints() { void constraints() {
boost::function_requires< boost::function_requires<
@ -145,7 +142,6 @@ namespace boost_concepts {
boost::function_requires< boost::function_requires<
SwappableIteratorConcept<Iterator> >(); SwappableIteratorConcept<Iterator> >();
BOOST_STATIC_ASSERT((boost::detail::is_tag<boost::writable_lvalue_iterator_tag, access_category>::value));
BOOST_STATIC_ASSERT((boost::is_same<reference, value_type&>::value)); BOOST_STATIC_ASSERT((boost::is_same<reference, value_type&>::value));
} }
@ -157,14 +153,19 @@ namespace boost_concepts {
template <typename Iterator> template <typename Iterator>
class IncrementableIteratorConcept { class IncrementableIteratorConcept {
public: public:
typedef typename boost::traversal_category<Iterator>::type traversal_category; typedef typename boost::iterator_traversal<Iterator>::type traversal_category;
void constraints() { void constraints() {
boost::function_requires< boost::SGIAssignableConcept<Iterator> >(); boost::function_requires< boost::SGIAssignableConcept<Iterator> >();
boost::function_requires< boost::function_requires<
boost::DefaultConstructibleConcept<Iterator> >(); boost::DefaultConstructibleConcept<Iterator> >();
BOOST_STATIC_ASSERT((boost::detail::is_tag<boost::incrementable_traversal_tag, traversal_category>::value)); BOOST_STATIC_ASSERT(
(boost::is_convertible<
traversal_category
, boost::incrementable_traversal_tag
>::value
));
++i; ++i;
(void)i++; (void)i++;
@ -175,21 +176,26 @@ namespace boost_concepts {
template <typename Iterator> template <typename Iterator>
class SinglePassIteratorConcept { class SinglePassIteratorConcept {
public: public:
typedef typename boost::traversal_category<Iterator>::type traversal_category; typedef typename boost::iterator_traversal<Iterator>::type traversal_category;
typedef typename boost::detail::iterator_traits<Iterator>::difference_type difference_type; typedef typename boost::detail::iterator_traits<Iterator>::difference_type difference_type;
void constraints() { void constraints() {
boost::function_requires< IncrementableIteratorConcept<Iterator> >(); boost::function_requires< IncrementableIteratorConcept<Iterator> >();
boost::function_requires< boost::EqualityComparableConcept<Iterator> >(); boost::function_requires< boost::EqualityComparableConcept<Iterator> >();
BOOST_STATIC_ASSERT((boost::detail::is_tag<boost::single_pass_traversal_tag, traversal_category>::value)); BOOST_STATIC_ASSERT(
(boost::is_convertible<
traversal_category
, boost::single_pass_traversal_tag
>::value
));
} }
}; };
template <typename Iterator> template <typename Iterator>
class ForwardTraversalConcept { class ForwardTraversalConcept {
public: public:
typedef typename boost::traversal_category<Iterator>::type traversal_category; typedef typename boost::iterator_traversal<Iterator>::type traversal_category;
typedef typename boost::detail::iterator_traits<Iterator>::difference_type difference_type; typedef typename boost::detail::iterator_traits<Iterator>::difference_type difference_type;
void constraints() { void constraints() {
@ -201,19 +207,29 @@ namespace boost_concepts {
> difference_type_is_signed_integral; > difference_type_is_signed_integral;
BOOST_STATIC_ASSERT(difference_type_is_signed_integral::value); BOOST_STATIC_ASSERT(difference_type_is_signed_integral::value);
BOOST_STATIC_ASSERT((boost::detail::is_tag<boost::forward_traversal_tag, traversal_category>::value)); BOOST_STATIC_ASSERT(
(boost::is_convertible<
traversal_category
, boost::forward_traversal_tag
>::value
));
} }
}; };
template <typename Iterator> template <typename Iterator>
class BidirectionalTraversalConcept { class BidirectionalTraversalConcept {
public: public:
typedef typename boost::traversal_category<Iterator>::type traversal_category; typedef typename boost::iterator_traversal<Iterator>::type traversal_category;
void constraints() { void constraints() {
boost::function_requires< ForwardTraversalConcept<Iterator> >(); boost::function_requires< ForwardTraversalConcept<Iterator> >();
BOOST_STATIC_ASSERT((boost::detail::is_tag<boost::bidirectional_traversal_tag, traversal_category>::value)); BOOST_STATIC_ASSERT(
(boost::is_convertible<
traversal_category
, boost::bidirectional_traversal_tag
>::value
));
--i; --i;
(void)i--; (void)i--;
@ -224,14 +240,19 @@ namespace boost_concepts {
template <typename Iterator> template <typename Iterator>
class RandomAccessTraversalConcept { class RandomAccessTraversalConcept {
public: public:
typedef typename boost::traversal_category<Iterator>::type traversal_category; typedef typename boost::iterator_traversal<Iterator>::type traversal_category;
typedef typename boost::detail::iterator_traits<Iterator>::difference_type typedef typename boost::detail::iterator_traits<Iterator>::difference_type
difference_type; difference_type;
void constraints() { void constraints() {
boost::function_requires< BidirectionalTraversalConcept<Iterator> >(); boost::function_requires< BidirectionalTraversalConcept<Iterator> >();
BOOST_STATIC_ASSERT((boost::detail::is_tag<boost::random_access_traversal_tag, traversal_category>::value)); BOOST_STATIC_ASSERT(
(boost::is_convertible<
traversal_category
, boost::random_access_traversal_tag
>::value
));
i += n; i += n;
i = i + n; i = i + n;
@ -326,11 +347,11 @@ namespace detail
class InteroperableConcept class InteroperableConcept
{ {
public: public:
typedef typename boost::traversal_category<Iterator>::type traversal_category; typedef typename boost::iterator_traversal<Iterator>::type traversal_category;
typedef typename boost::detail::iterator_traits<Iterator>::difference_type typedef typename boost::detail::iterator_traits<Iterator>::difference_type
difference_type; difference_type;
typedef typename boost::traversal_category<ConstIterator>::type typedef typename boost::iterator_traversal<ConstIterator>::type
const_traversal_category; const_traversal_category;
typedef typename boost::detail::iterator_traits<ConstIterator>::difference_type typedef typename boost::detail::iterator_traits<ConstIterator>::difference_type
const_difference_type; const_difference_type;

View File

@ -12,15 +12,17 @@
#include <boost/static_assert.hpp> #include <boost/static_assert.hpp>
#include <boost/iterator.hpp> #include <boost/iterator.hpp>
#include <boost/iterator/iterator_categories.hpp>
#include <boost/iterator/interoperable.hpp> #include <boost/iterator/interoperable.hpp>
#include <boost/iterator/detail/facade_iterator_category.hpp>
#include <boost/iterator/detail/enable_if.hpp> #include <boost/iterator/detail/enable_if.hpp>
#include <boost/type_traits/is_same.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/is_convertible.hpp> #include <boost/type_traits/is_convertible.hpp>
#include <boost/iterator/iterator_traits.hpp>
#include <boost/mpl/apply_if.hpp> #include <boost/mpl/apply_if.hpp>
#include <boost/mpl/or.hpp> #include <boost/mpl/or.hpp>
@ -30,21 +32,7 @@ namespace boost
{ {
// This forward declaration is required for the friend declaration // This forward declaration is required for the friend declaration
// in iterator_core_access // in iterator_core_access
template <class I, class V, class AC, class TC, class R, class D> class iterator_facade; template <class I, class V, class TC, class R, class D> class iterator_facade;
// 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 namespace detail
{ {
@ -75,59 +63,30 @@ namespace boost
#endif #endif
}; };
// //
// Add const qualification for iterators which are not writable // Generates associated types for an iterator_facade with the
// // given parameters.
template<class Value, class AccessCategory>
struct const_qualified_ref :
mpl::if_< is_tag< writable_iterator_tag, AccessCategory >,
Value&,
Value const& >
{};
// The apparent duplication here works around a Borland problem
template<class Value, class AccessCategory>
struct const_qualified_ptr :
mpl::if_< is_tag< writable_iterator_tag, AccessCategory >,
Value*,
Value const* >
{};
//
// Generates the associated types for an iterator_facade with the
// given parameters. Additionally generates a 'base' type for
// compiler/library combinations which require user-defined
// iterators to inherit from std::iterator.
// //
template < template <
class Value class ValueParam
, class AccessCategory , class CategoryOrTraversal
, class TraversalCategory , class Reference
, class Reference
, class Difference , class Difference
> >
struct iterator_facade_types struct iterator_facade_types
{ {
typedef iterator_tag<AccessCategory, TraversalCategory> iterator_category; typedef typename facade_iterator_category<
CategoryOrTraversal, ValueParam, Reference
typedef typename remove_cv<Value>::type value_type; >::type iterator_category;
typedef Difference difference_type; typedef typename remove_const<ValueParam>::type value_type;
typedef typename const_qualified_ptr<Value, AccessCategory>::type pointer; typedef typename mpl::apply_if<
detail::iterator_writability_disabled<ValueParam,Reference>
// The use_default support is needed for iterator_adaptor. , add_pointer<typename add_const<value_type>::type>
// For practical reasons iterator_adaptor needs to specify , add_pointer<value_type>
// a fixed number of template arguments of iterator_facade. >::type pointer;
// So use_default is its way to say: "What I really mean
// is your default parameter".
typedef typename mpl::if_<
is_same<Reference, use_default>
, typename const_qualified_ref<Value, AccessCategory>::type
, Reference
>::type reference;
# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ # if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
&& (BOOST_WORKAROUND(_STLPORT_VERSION, BOOST_TESTED_AT(0x452)) \ && (BOOST_WORKAROUND(_STLPORT_VERSION, BOOST_TESTED_AT(0x452)) \
|| BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, BOOST_TESTED_AT(310))) \ || BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, BOOST_TESTED_AT(310))) \
@ -141,7 +100,7 @@ namespace boost
# define BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE 1 # define BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE 1
typedef typedef
iterator<iterator_category, value_type, difference_type, pointer, reference> iterator<iterator_category, value_type, Difference, pointer, Reference>
base; base;
# endif # endif
}; };
@ -205,10 +164,10 @@ namespace boost
public: public:
operator_brackets_proxy(Iterator const& iter) operator_brackets_proxy(Iterator const& iter)
: m_iter(iter) : m_iter(iter)
{} {}
operator reference() operator reference() const
{ {
return *m_iter; return *m_iter;
} }
@ -223,28 +182,24 @@ namespace boost
Iterator m_iter; Iterator m_iter;
}; };
template <class Iterator, class ValueType, class Category, class Reference> template <class Iterator, class Value, class Reference>
struct operator_brackets_result struct operator_brackets_result
{ {
typedef typename access_category_tag<Category,Reference>::type access_category;
typedef is_tag<writable_iterator_tag, access_category> use_proxy;
typedef typename mpl::if_< typedef typename mpl::if_<
use_proxy iterator_writability_disabled<Value,Reference>
, Value
, operator_brackets_proxy<Iterator> , operator_brackets_proxy<Iterator>
, ValueType
>::type type; >::type type;
}; };
template <class Iterator> template <class Iterator>
operator_brackets_proxy<Iterator> make_operator_brackets_result(Iterator const& iter, mpl::true_) operator_brackets_proxy<Iterator> make_operator_brackets_result(Iterator const& iter, mpl::false_)
{ {
return operator_brackets_proxy<Iterator>(iter); return operator_brackets_proxy<Iterator>(iter);
} }
template <class Iterator> template <class Iterator>
typename Iterator::value_type make_operator_brackets_result(Iterator const& iter, mpl::false_) typename Iterator::value_type make_operator_brackets_result(Iterator const& iter, mpl::true_)
{ {
return *iter; return *iter;
} }
@ -253,20 +208,20 @@ namespace boost
// Macros which describe the declarations of binary operators // Macros which describe the declarations of binary operators
# define BOOST_ITERATOR_FACADE_INTEROP_HEAD(prefix, op, result_type) \ # define BOOST_ITERATOR_FACADE_INTEROP_HEAD(prefix, op, result_type) \
template < \ template < \
class Derived1, class V1, class AC1, class TC1, class R1, class D1 \ class Derived1, class V1, class TC1, class R1, class D1 \
, class Derived2, class V2, class AC2, class TC2, class R2, class D2 \ , class Derived2, class V2, class TC2, class R2, class D2 \
> \ > \
prefix typename detail::enable_if_interoperable< \ prefix typename detail::enable_if_interoperable< \
Derived1, Derived2, result_type \ Derived1, Derived2, result_type \
>::type \ >::type \
operator op( \ operator op( \
iterator_facade<Derived1, V1, AC1, TC1, R1, D1> const& lhs \ iterator_facade<Derived1, V1, TC1, R1, D1> const& lhs \
, iterator_facade<Derived2, V2, AC2, TC2, R2, D2> const& rhs) , iterator_facade<Derived2, V2, TC2, R2, D2> const& rhs)
# define BOOST_ITERATOR_FACADE_PLUS_HEAD(prefix,args) \ # define BOOST_ITERATOR_FACADE_PLUS_HEAD(prefix,args) \
template <class Derived, class V, class AC, class TC, class R, class D> \ template <class Derived, class V, class TC, class R, class D> \
prefix Derived operator+ args prefix Derived operator+ args
// //
@ -286,8 +241,8 @@ namespace boost
// to work in the absence of member template friends. // to work in the absence of member template friends.
public: public:
# else # else
template <class I, class V, class AC, class TC, class R, class D> friend class iterator_facade; template <class I, class V, class TC, class R, class D> friend class iterator_facade;
# define BOOST_ITERATOR_FACADE_RELATION(op) \ # define BOOST_ITERATOR_FACADE_RELATION(op) \
BOOST_ITERATOR_FACADE_INTEROP_HEAD(friend,op, bool); BOOST_ITERATOR_FACADE_INTEROP_HEAD(friend,op, bool);
@ -306,8 +261,8 @@ namespace boost
; ;
BOOST_ITERATOR_FACADE_PLUS_HEAD( BOOST_ITERATOR_FACADE_PLUS_HEAD(
friend friend
, (iterator_facade<Derived, V, AC, TC, R, D> const& , (iterator_facade<Derived, V, TC, R, D> const&
, typename Derived::difference_type) , typename Derived::difference_type)
) )
; ;
@ -315,7 +270,7 @@ namespace boost
BOOST_ITERATOR_FACADE_PLUS_HEAD( BOOST_ITERATOR_FACADE_PLUS_HEAD(
friend friend
, (typename Derived::difference_type , (typename Derived::difference_type
, iterator_facade<Derived, V, AC, TC, R, D> const&) , iterator_facade<Derived, V, TC, R, D> const&)
) )
; ;
@ -370,26 +325,21 @@ namespace boost
template < template <
class Derived // The derived iterator type being constructed class Derived // The derived iterator type being constructed
, class Value , class Value
, class AccessCategory , class CategoryOrTraversal
, class TraversalCategory , class Reference = Value&
, class Reference = BOOST_DEDUCED_TYPENAME detail::const_qualified_ref<Value, AccessCategory>::type
, class Difference = std::ptrdiff_t , class Difference = std::ptrdiff_t
> >
class iterator_facade class iterator_facade
# ifdef BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE # ifdef BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE
: public detail::iterator_facade_types< : public detail::iterator_facade_types<
Value, AccessCategory, TraversalCategory, Reference, Difference Value, CategoryOrTraversal, Reference, Difference
>::base >::base
# undef BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE # undef BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE
# endif # endif
{ {
private: private:
typedef typename
detail::iterator_facade_types<Value, AccessCategory, TraversalCategory, Reference, Difference>
types;
// //
// Curiously Recursive Template interface. // Curiously Recurring Template interface.
// //
typedef Derived derived_t; typedef Derived derived_t;
@ -403,13 +353,17 @@ namespace boost
return static_cast<Derived const&>(*this); return static_cast<Derived const&>(*this);
} }
typedef detail::iterator_facade_types<
Value, CategoryOrTraversal, Reference, Difference
> associated_types;
public: public:
typedef typename types::value_type value_type; typedef typename associated_types::value_type value_type;
typedef typename types::reference reference; typedef Reference reference;
typedef typename types::difference_type difference_type; typedef Difference difference_type;
typedef typename types::pointer pointer; typedef typename associated_types::pointer pointer;
typedef typename types::iterator_category iterator_category; typedef typename associated_types::iterator_category iterator_category;
reference operator*() const reference operator*() const
{ {
@ -429,15 +383,17 @@ namespace boost
, pointer , pointer
>::make(*this->derived()); >::make(*this->derived());
} }
typename detail::operator_brackets_result<Derived,value_type,iterator_category,reference>::type typename detail::operator_brackets_result<Derived,Value,Reference>::type
operator[](difference_type n) const operator[](difference_type n) const
{ {
typedef typename typedef detail::iterator_writability_disabled<Value,Reference>
detail::operator_brackets_result<Derived,value_type,iterator_category,reference>::use_proxy not_writable;
use_proxy;
return detail::make_operator_brackets_result<Derived>(
return detail::make_operator_brackets_result<Derived>(this->derived() + n, use_proxy()); this->derived() + n
, not_writable()
);
} }
Derived& operator++() Derived& operator++()
@ -615,13 +571,13 @@ namespace boost
} }
BOOST_ITERATOR_FACADE_PLUS(( BOOST_ITERATOR_FACADE_PLUS((
iterator_facade<Derived, V, AC, TC, R, D> const& i iterator_facade<Derived, V, TC, R, D> const& i
, typename Derived::difference_type n , typename Derived::difference_type n
)) ))
BOOST_ITERATOR_FACADE_PLUS(( BOOST_ITERATOR_FACADE_PLUS((
typename Derived::difference_type n typename Derived::difference_type n
, iterator_facade<Derived, V, AC, TC, R, D> const& i , iterator_facade<Derived, V, TC, R, D> const& i
)) ))
# undef BOOST_ITERATOR_FACADE_PLUS # undef BOOST_ITERATOR_FACADE_PLUS
# undef BOOST_ITERATOR_FACADE_PLUS_HEAD # undef BOOST_ITERATOR_FACADE_PLUS_HEAD

View File

@ -24,15 +24,13 @@
# include <boost/concept_archetype.hpp> // for detail::dummy_constructor # include <boost/concept_archetype.hpp> // for detail::dummy_constructor
# include <boost/detail/iterator.hpp> # include <boost/detail/iterator.hpp>
# include <boost/pending/iterator_tests.hpp> # include <boost/pending/iterator_tests.hpp>
# include <boost/iterator/is_readable_iterator.hpp>
# include <boost/iterator/is_lvalue_iterator.hpp>
# include <boost/iterator/detail/config_def.hpp>
namespace boost { namespace boost {
void is_readable(readable_iterator_tag) { }
void is_writable(writable_iterator_tag) { }
void is_swappable(swappable_iterator_tag) { }
void is_constant_lvalue(readable_lvalue_iterator_tag) { }
void is_mutable_lvalue(writable_lvalue_iterator_tag) { }
// Preconditions: *i == v // Preconditions: *i == v
template <class Iterator, class T> template <class Iterator, class T>
void readable_iterator_test(const Iterator i1, T v) void readable_iterator_test(const Iterator i1, T v)
@ -45,8 +43,12 @@ void readable_iterator_test(const Iterator i1, T v)
T v2 = r2; T v2 = r2;
assert(v1 == v); assert(v1 == v);
assert(v2 == v); assert(v2 == v);
typedef typename access_category<Iterator>::type result_category;
is_readable(result_category()); # if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
// I think we don't really need this as it checks the same things as
// the above code.
BOOST_STATIC_ASSERT(is_readable_iterator<Iterator>::value);
# endif
} }
template <class Iterator, class T> template <class Iterator, class T>
@ -54,7 +56,6 @@ void writable_iterator_test(Iterator i, T v)
{ {
Iterator i2(i); // Copy Constructible Iterator i2(i); // Copy Constructible
*i2 = v; *i2 = v;
is_writable(typename access_category<Iterator>::type());
} }
template <class Iterator> template <class Iterator>
@ -65,8 +66,6 @@ void swappable_iterator_test(Iterator i, Iterator j)
iter_swap(i2, j2); iter_swap(i2, j2);
typename detail::iterator_traits<Iterator>::value_type ai = *i, aj = *j; typename detail::iterator_traits<Iterator>::value_type ai = *i, aj = *j;
assert(bi == aj && bj == ai); assert(bi == aj && bj == ai);
typedef typename access_category<Iterator>::type result_category;
is_swappable(result_category());
} }
template <class Iterator, class T> template <class Iterator, class T>
@ -78,12 +77,14 @@ void constant_lvalue_iterator_test(Iterator i, T v1)
BOOST_STATIC_ASSERT((is_same<const value_type&, reference>::value)); BOOST_STATIC_ASSERT((is_same<const value_type&, reference>::value));
const T& v2 = *i2; const T& v2 = *i2;
assert(v1 == v2); assert(v1 == v2);
typedef typename access_category<Iterator>::type result_category; # ifndef BOOST_NO_LVALUE_RETURN_DETECTION
is_constant_lvalue(result_category()); BOOST_STATIC_ASSERT(is_lvalue_iterator<Iterator>::value);
BOOST_STATIC_ASSERT(!is_non_const_lvalue_iterator<Iterator>::value);
# endif
} }
template <class Iterator, class T> template <class Iterator, class T>
void mutable_lvalue_iterator_test(Iterator i, T v1, T v2) void non_const_lvalue_iterator_test(Iterator i, T v1, T v2)
{ {
Iterator i2(i); Iterator i2(i);
typedef typename detail::iterator_traits<Iterator>::value_type value_type; typedef typename detail::iterator_traits<Iterator>::value_type value_type;
@ -91,11 +92,17 @@ void mutable_lvalue_iterator_test(Iterator i, T v1, T v2)
BOOST_STATIC_ASSERT((is_same<value_type&, reference>::value)); BOOST_STATIC_ASSERT((is_same<value_type&, reference>::value));
T& v3 = *i2; T& v3 = *i2;
assert(v1 == v3); assert(v1 == v3);
// A non-const lvalue iterator is not neccessarily writable, but we
// are assuming the value_type is assignable here
*i = v2; *i = v2;
T& v4 = *i2; T& v4 = *i2;
assert(v2 == v4); assert(v2 == v4);
typedef typename access_category<Iterator>::type result_category; # ifndef BOOST_NO_LVALUE_RETURN_DETECTION
is_mutable_lvalue(result_category()); BOOST_STATIC_ASSERT(is_lvalue_iterator<Iterator>::value);
BOOST_STATIC_ASSERT(is_non_const_lvalue_iterator<Iterator>::value);
# endif
} }
template <class Iterator, class T> template <class Iterator, class T>
@ -159,7 +166,6 @@ void bidirectional_readable_iterator_test(Iterator i, T v1, T v2)
readable_iterator_test(i2, v2); readable_iterator_test(i2, v2);
} }
// random access // random access
// Preconditions: [i,i+N) is a valid range // Preconditions: [i,i+N) is a valid range
template <class Iterator, class TrueVals> template <class Iterator, class TrueVals>
@ -169,10 +175,12 @@ void random_access_readable_iterator_test(Iterator i, int N, TrueVals vals)
const Iterator j = i; const Iterator j = i;
int c; int c;
for (c = 0; c < N-1; ++c) { for (c = 0; c < N-1; ++c)
{
assert(i == j + c); assert(i == j + c);
assert(*i == vals[c]); assert(*i == vals[c]);
assert(*i == j[c]); typename detail::iterator_traits<Iterator>::value_type x = j[c];
assert(*i == x);
assert(*i == *(j + c)); assert(*i == *(j + c));
assert(*i == *(c + j)); assert(*i == *(c + j));
++i; ++i;
@ -183,10 +191,12 @@ void random_access_readable_iterator_test(Iterator i, int N, TrueVals vals)
} }
Iterator k = j + N - 1; Iterator k = j + N - 1;
for (c = 0; c < N-1; ++c) { for (c = 0; c < N-1; ++c)
{
assert(i == k - c); assert(i == k - c);
assert(*i == vals[N - 1 - c]); assert(*i == vals[N - 1 - c]);
assert(*i == j[N - 1 - c]); typename detail::iterator_traits<Iterator>::value_type x = j[N - 1 - c];
assert(*i == x);
Iterator q = k - c; Iterator q = k - c;
assert(*i == *q); assert(*i == *q);
assert(i > j); assert(i > j);
@ -197,8 +207,8 @@ void random_access_readable_iterator_test(Iterator i, int N, TrueVals vals)
} }
} }
// #if 0'd code snipped; see CVS v 1.4 if you need it back
} // namespace boost } // namespace boost
# include <boost/iterator/detail/config_undef.hpp>
#endif // BOOST_NEW_ITERATOR_TESTS_HPP #endif // BOOST_NEW_ITERATOR_TESTS_HPP

View File

@ -24,6 +24,8 @@
#include <boost/type_traits/remove_const.hpp> #include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/remove_reference.hpp> #include <boost/type_traits/remove_reference.hpp>
#include <boost/iterator/detail/config_def.hpp>
namespace boost namespace boost
{ {
template <class UnaryFunction, class Iterator, class Reference = use_default, class Value = use_default> template <class UnaryFunction, class Iterator, class Reference = use_default, class Value = use_default>
@ -46,53 +48,38 @@ namespace boost
}; };
#endif #endif
// Given the transform iterator's transformation and iterator, this // Compute the iterator_adaptor instantiation to be used for transform_iterator
// is the type used as its traits.
template <class UnaryFunction, class Iterator, class Reference, class Value> template <class UnaryFunction, class Iterator, class Reference, class Value>
struct transform_iterator_base struct transform_iterator_base
{ {
private: private:
// By default, dereferencing the iterator yields the same as
// the function. Do we need to adjust the way
// function_object_result is computed for the standard
// proposal (e.g. using Doug's result_of)?
typedef typename ia_dflt_help<
Reference
, function_object_result<UnaryFunction>
>::type reference;
// transform_iterator does not support writable/swappable iterators // To get the default for Value: remove any reference on the
#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) // result type, but retain any constness to signal
BOOST_STATIC_ASSERT((is_tag< readable_iterator_tag, typename access_category<Iterator>::type >::value)); // non-writability. Note that if we adopt Thomas' suggestion
#endif // to key non-writability *only* on the Reference argument,
// we'd need to strip constness here as well.
typedef typename mpl::apply_if< typedef typename ia_dflt_help<
is_same< Reference, use_default > Value
, function_object_result<UnaryFunction> , remove_reference<reference>
, mpl::identity<Reference> >::type cv_value_type;
>::type result_type;
typedef typename mpl::if_< public:
is_same< Value, use_default > typedef iterator_adaptor<
, typename remove_reference< result_type >::type transform_iterator<UnaryFunction, Iterator, Reference, Value>
, Value , Iterator
>::type cv_value_type; , cv_value_type
, use_default // Leave the traversal category alone
typedef typename mpl::if_< , reference
is_reference< result_type > > type;
, typename mpl::if_<
is_const< cv_value_type >
, readable_lvalue_iterator_tag
, writable_lvalue_iterator_tag
>::type
, readable_iterator_tag
>::type maximum_access_tag;
typedef typename minimum_category<
maximum_access_tag
, typename access_category<Iterator>::type
>::type access_category;
public:
typedef iterator_adaptor<
transform_iterator<UnaryFunction, Iterator, Reference, Value>
, Iterator
, cv_value_type
, access_category
, result_type
> type;
}; };
} }
@ -150,12 +137,16 @@ namespace boost
return transform_iterator<UnaryFunction, Iterator>(it, fun); return transform_iterator<UnaryFunction, Iterator>(it, fun);
} }
// Version which allows explicit specification of the UnaryFunction
// type.
//
// This generator is not provided if UnaryFunction is a function
// pointer type, because it's too dangerous: the default-constructed
// function pointer in the iterator be 0, leading to a runtime
// crash.
template <class UnaryFunction, class Iterator> template <class UnaryFunction, class Iterator>
// don't provide this generator if UnaryFunction is a
// function pointer type. Too dangerous. We should probably
// find a cheaper test than is_class<>
typename iterators::enable_if< typename iterators::enable_if<
is_class<UnaryFunction> is_class<UnaryFunction> // We should probably find a cheaper test than is_class<>
, transform_iterator<UnaryFunction, Iterator> , transform_iterator<UnaryFunction, Iterator>
>::type >::type
make_transform_iterator(Iterator it) make_transform_iterator(Iterator it)
@ -174,4 +165,6 @@ namespace boost
} // namespace boost } // namespace boost
#include <boost/iterator/detail/config_undef.hpp>
#endif // BOOST_TRANSFORM_ITERATOR_23022003THW_HPP #endif // BOOST_TRANSFORM_ITERATOR_23022003THW_HPP

View File

@ -28,6 +28,8 @@
#include <boost/iterator/iterator_categories.hpp> #include <boost/iterator/iterator_categories.hpp>
#include <boost/detail/iterator.hpp> #include <boost/detail/iterator.hpp>
#include <boost/iterator/detail/minimum_category.hpp>
#include <boost/tuple/tuple.hpp> #include <boost/tuple/tuple.hpp>
#if BOOST_WORKAROUND(__GNUC__, == 2) || BOOST_WORKAROUND(__MWERKS__, <= 0x2407) #if BOOST_WORKAROUND(__GNUC__, == 2) || BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
@ -259,16 +261,17 @@ namespace boost {
) )
{ {
typedef typename tuple_meta_transform< typedef typename tuple_meta_transform<
typename Tuple::tail_type BOOST_DEDUCED_TYPENAME Tuple::tail_type
, Fun , Fun
>::type transformed_tail_type; >::type transformed_tail_type;
return tuples::cons< return tuples::cons<
typename mpl::apply1<Fun, typename Tuple::head_type>::type BOOST_DEDUCED_TYPENAME mpl::apply1<
Fun, BOOST_DEDUCED_TYPENAME Tuple::head_type
>::type
, transformed_tail_type , transformed_tail_type
>( >(
f(boost::tuples::get<0>(t)), f(boost::tuples::get<0>(t)), tuple_transform(t.get_tail(), f)
tuple_transform(t.get_tail(), f)
); );
} }
@ -380,12 +383,12 @@ namespace boost {
{ {
typedef typename tuple_impl_specific::tuple_meta_transform< typedef typename tuple_impl_specific::tuple_meta_transform<
IteratorTuple IteratorTuple
, traversal_category<mpl::_1> , iterator_traversal<>
>::type tuple_of_traversal_tags; >::type tuple_of_traversal_tags;
typedef typename tuple_impl_specific::tuple_meta_accumulate< typedef typename tuple_impl_specific::tuple_meta_accumulate<
tuple_of_traversal_tags tuple_of_traversal_tags
, minimum_category<mpl::_1,mpl::_2> , minimum_category<>
, random_access_traversal_tag , random_access_traversal_tag
>::type type; >::type type;
}; };
@ -398,31 +401,6 @@ namespace boost {
}; };
#endif #endif
template<typename Iterator>
struct iterator_is_readable
: is_tag<
readable_iterator_tag
, typename access_category<Iterator>::type
>
{
BOOST_MPL_AUX_LAMBDA_SUPPORT(1, iterator_is_readable, (Iterator))
};
# ifdef BOOST_MPL_NO_FULL_LAMBDA_SUPPORT
// Hack because BOOST_MPL_AUX_LAMBDA_SUPPORT doesn't seem to work
// out well. Instantiating the nested apply template also
// requires instantiating iterator_traits on the
// placeholder. Instead we just specialize it as a metafunction
// class.
template <>
struct iterator_is_readable<mpl::_1>
{
template <class T>
struct apply : iterator_is_readable<T>
{};
};
# endif
// We need to call tuple_meta_accumulate with mpl::and_ as the // We need to call tuple_meta_accumulate with mpl::and_ as the
// accumulating functor. To this end, we need to wrap it into // accumulating functor. To this end, we need to wrap it into
// a struct that has exactly two arguments (that is, template // a struct that has exactly two arguments (that is, template
@ -446,28 +424,6 @@ namespace boost {
}; };
# endif # endif
// Metafunction to assert that all iterators in a tuple are
// readable.
//
// Probably not worth it, IMO. Why not a writable zip_iterator
// anyway? -- dwa.
//
template<typename IteratorTuple>
struct all_iterators_in_tuple_readable
{
typedef typename tuple_impl_specific::tuple_meta_transform<
IteratorTuple,
iterator_is_readable<mpl::_1>
>::type tuple_of_readability_bools;
typedef typename tuple_impl_specific::tuple_meta_accumulate<
tuple_of_readability_bools,
and_with_two_args<mpl::_1,mpl::_2>
, mpl::bool_<true>
>::type type;
};
/////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////
// //
// Class zip_iterator_base // Class zip_iterator_base
@ -479,14 +435,6 @@ namespace boost {
struct zip_iterator_base struct zip_iterator_base
{ {
private: private:
#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
// seems to give vc7's parser fits, and vc6 needs help here too
BOOST_STATIC_ASSERT(
detail::all_iterators_in_tuple_readable<
IteratorTuple
>::type::value
);
#endif
// Reference type is the type of the tuple obtained from the // Reference type is the type of the tuple obtained from the
// iterators' reference types. // iterators' reference types.
typedef typename typedef typename
@ -506,11 +454,6 @@ namespace boost {
detail::minimum_traversal_category_in_iterator_tuple< detail::minimum_traversal_category_in_iterator_tuple<
IteratorTuple IteratorTuple
>::type traversal_category; >::type traversal_category;
// Access category is readable_iterator_tag. It has been
// asserted that all iterators in the tuple are readable.
typedef readable_iterator_tag access_category;
public: public:
// The iterator facade type from which the zip iterator will // The iterator facade type from which the zip iterator will
@ -518,7 +461,6 @@ namespace boost {
typedef iterator_facade< typedef iterator_facade<
zip_iterator<IteratorTuple>, zip_iterator<IteratorTuple>,
value_type, value_type,
access_category,
traversal_category, traversal_category,
reference, reference,
difference_type difference_type
@ -616,7 +558,7 @@ namespace boost {
{ {
detail::tuple_impl_specific::tuple_for_each( detail::tuple_impl_specific::tuple_for_each(
m_iterator_tuple, m_iterator_tuple,
detail::advance_iterator<typename super_t::difference_type>(n) detail::advance_iterator<BOOST_DEDUCED_TYPENAME super_t::difference_type>(n)
); );
} }
// Incrementing a zip iterator means to increment all iterators in // Incrementing a zip iterator means to increment all iterators in

View File

@ -18,6 +18,8 @@ test-suite iterator
# compilation problems. # compilation problems.
[ run is_convertible_fail.cpp ] [ run is_convertible_fail.cpp ]
[ run zip_iterator_test.cpp ]
# These tests should work for just about everything. # These tests should work for just about everything.
[ compile is_lvalue_iterator.cpp ] [ compile is_lvalue_iterator.cpp ]
[ compile is_readable_iterator.cpp ] [ compile is_readable_iterator.cpp ]
@ -34,8 +36,6 @@ test-suite iterator
[ run counting_iterator_test.cpp ] [ run counting_iterator_test.cpp ]
[ run permutation_iterator_test.cpp : : : # <stlport-iostream>on [ run permutation_iterator_test.cpp : : : # <stlport-iostream>on
] ]
[ compile iterator_categories.cpp ]
[ run zip_iterator_test.cpp ]
[ run ../../utility/iterator_adaptor_examples.cpp ] [ run ../../utility/iterator_adaptor_examples.cpp ]
[ run ../../utility/counting_iterator_example.cpp ] [ run ../../utility/counting_iterator_example.cpp ]

View File

@ -5,15 +5,16 @@
// to its suitability for any purpose. // to its suitability for any purpose.
#include <boost/iterator/iterator_concepts.hpp> #include <boost/iterator/iterator_concepts.hpp>
#include <boost/iterator/iterator_categories.hpp>
#include <boost/operators.hpp> #include <boost/operators.hpp>
#include <boost/static_assert.hpp> // remove
#include <boost/detail/workaround.hpp> struct new_random_access
#include "static_assert_same.hpp" // remove : std::random_access_iterator_tag
, boost::random_access_traversal_tag
{};
struct new_iterator struct new_iterator
: public boost::iterator< boost::iterator_tag< : public boost::iterator< new_random_access, int >
boost::writable_lvalue_iterator_tag
, boost::random_access_traversal_tag>, int>
{ {
int& operator*() const { return *m_x; } int& operator*() const { return *m_x; }
new_iterator& operator++() { return *this; } new_iterator& operator++() { return *this; }
@ -52,103 +53,13 @@ struct old_iterator
}; };
old_iterator operator+(std::ptrdiff_t, old_iterator x) { return x; } old_iterator operator+(std::ptrdiff_t, old_iterator x) { return x; }
struct my_writable_lvalue_iterator_tag
{
operator boost::writable_lvalue_iterator_tag() const;
};
struct my_single_pass_traversal_tag
{
operator boost::single_pass_traversal_tag() const;
};
void test_tag_convertibility()
{
// This set of tests is by no means complete.
// Test that this is an input/output iterator
#if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
{
typedef boost::iterator_tag<
boost::writable_lvalue_iterator_tag
, boost::single_pass_traversal_tag
> tag;
BOOST_STATIC_ASSERT((
boost::is_convertible<tag, std::output_iterator_tag>::value
));
BOOST_STATIC_ASSERT((
boost::is_convertible<tag, std::input_iterator_tag>::value
));
BOOST_STATIC_ASSERT((
!boost::is_convertible<tag, std::forward_iterator_tag>::value
));
}
// Test that it's possible to build new sub-tags without
// derivation. Convertibility should be enough
{
typedef boost::iterator_tag<
my_writable_lvalue_iterator_tag
, my_single_pass_traversal_tag
> tag;
BOOST_STATIC_ASSERT((
boost::is_convertible<tag, std::output_iterator_tag>::value
));
BOOST_STATIC_ASSERT((
boost::is_convertible<tag, std::input_iterator_tag>::value
));
BOOST_STATIC_ASSERT((
!boost::is_convertible<tag, std::forward_iterator_tag>::value
));
}
// Test that a single-pass readable lvalue iterator is only an
// input iterator. Requires special case handling in
// categories.hpp
{
typedef boost::iterator_tag<
boost::readable_lvalue_iterator_tag
, boost::single_pass_traversal_tag
> tag;
BOOST_STATIC_ASSERT((
boost::is_convertible<tag, std::input_iterator_tag>::value
));
BOOST_STATIC_ASSERT((
!boost::is_convertible<tag, std::output_iterator_tag>::value
));
BOOST_STATIC_ASSERT((
!boost::is_convertible<tag, std::forward_iterator_tag>::value
));
}
#endif
}
int int
main() main()
{ {
test_tag_convertibility(); boost::iterator_traversal<new_iterator>::type tc;
boost::random_access_traversal_tag derived = tc;
typedef boost::iterator_tag< boost::writable_lvalue_iterator_tag, boost::random_access_traversal_tag > tag; (void)derived;
// BOOST_STATIC_ASSERT((boost::detail::is_random_access_iterator<tag>::value));
int test = static_assert_same<tag::access, boost::writable_lvalue_iterator_tag>::value;
test = static_assert_same<tag::traversal, boost::random_access_traversal_tag>::value;
// BOOST_STATIC_ASSERT((boost::detail::is_random_access_iterator<new_iterator::iterator_category>::value));
test = static_assert_same<new_iterator::iterator_category::access, boost::writable_lvalue_iterator_tag>::value;
test = static_assert_same<new_iterator::iterator_category::traversal, boost::random_access_traversal_tag>::value;
typedef boost::traversal_category<new_iterator>::type traversal_category;
// BOOST_STATIC_ASSERT(boost::detail::has_traversal<new_iterator::iterator_category>::value);
BOOST_STATIC_ASSERT(boost::detail::is_new_iterator_tag<new_iterator::iterator_category>::value);
test = static_assert_same<traversal_category, boost::random_access_traversal_tag>::value;
(void)test;
boost::function_requires< boost::function_requires<
boost_concepts::WritableLvalueIteratorConcept<int*> >(); boost_concepts::WritableLvalueIteratorConcept<int*> >();
boost::function_requires< boost::function_requires<

View File

@ -286,7 +286,7 @@ int main()
# ifndef BOOST_NO_SLIST # ifndef BOOST_NO_SLIST
test_container<BOOST_STD_EXTENSION_NAMESPACE::slist<int> >(); test_container<BOOST_STD_EXTENSION_NAMESPACE::slist<int> >();
# endif # endif
// Also prove that we can handle raw pointers. // Also prove that we can handle raw pointers.
int array[2000]; int array[2000];
test(boost::make_counting_iterator(array), boost::make_counting_iterator(array+2000-1)); test(boost::make_counting_iterator(array), boost::make_counting_iterator(array+2000-1));

View File

@ -7,13 +7,12 @@
#include <boost/iterator/filter_iterator.hpp> #include <boost/iterator/filter_iterator.hpp>
#include <boost/iterator/reverse_iterator.hpp> #include <boost/iterator/reverse_iterator.hpp>
#include <boost/iterator/new_iterator_tests.hpp> #include <boost/iterator/new_iterator_tests.hpp>
#include <boost/type_traits/broken_compiler_spec.hpp> #include <boost/type_traits/is_convertible.hpp>
#include <deque> #include <deque>
#include <iostream> #include <iostream>
using boost::dummyT; using boost::dummyT;
BOOST_TT_BROKEN_COMPILER_SPEC(boost::dummyT)
struct one_or_four struct one_or_four
{ {
@ -38,12 +37,12 @@ int main()
filter_iter(one_or_four(), array, array+N) filter_iter(one_or_four(), array, array+N)
, dummyT(1), dummyT(4)); , dummyT(1), dummyT(4));
BOOST_STATIC_ASSERT(( BOOST_STATIC_ASSERT(
!boost::detail::is_tag< (!boost::is_convertible<
boost::random_access_traversal_tag boost::iterator_traversal<filter_iter>::type
, boost::traversal_category<filter_iter>::type , boost::random_access_traversal_tag
>::value >::value
)); ));
//# endif //# endif

View File

@ -46,8 +46,7 @@
struct my_iterator_tag : public std::random_access_iterator_tag { }; struct my_iterator_tag : public std::random_access_iterator_tag { };
using boost::dummyT; using boost::dummyT;
BOOST_TT_BROKEN_COMPILER_SPEC(boost::dummyT) BOOST_TT_BROKEN_COMPILER_SPEC(boost::shared_ptr<dummyT>)
BOOST_TT_BROKEN_COMPILER_SPEC(boost::shared_ptr<boost::dummyT>)
typedef std::vector<int> storage; typedef std::vector<int> storage;
typedef std::vector<int*> pointer_ra_container; typedef std::vector<int*> pointer_ra_container;

View File

@ -32,12 +32,15 @@ struct noncopyable_iterator : boost::iterator<std::forward_iterator_tag,boost::n
boost::noncopyable const& operator*() const; boost::noncopyable const& operator*() const;
}; };
struct proxy_iterator : boost::iterator<std::output_iterator_tag,v> template <class T>
struct proxy_iterator
: boost::iterator<std::output_iterator_tag,T>
{ {
typedef T value_type;
#if BOOST_WORKAROUND(__GNUC__, == 2) #if BOOST_WORKAROUND(__GNUC__, == 2)
typedef boost::iterator<std::input_iterator_tag,v> base; typedef boost::iterator<std::input_iterator_tag,value_type> base;
typedef base::iterator_category iterator_category; typedef base::iterator_category iterator_category;
typedef base::value_type value_type;
typedef base::difference_type difference_type; typedef base::difference_type difference_type;
typedef base::pointer pointer; typedef base::pointer pointer;
typedef base::reference reference; typedef base::reference reference;
@ -45,14 +48,43 @@ struct proxy_iterator : boost::iterator<std::output_iterator_tag,v>
struct proxy struct proxy
{ {
operator v&() const; operator value_type&() const;
proxy& operator=(v) const; proxy& operator=(value_type) const;
}; };
proxy operator*() const; proxy operator*() const;
}; };
BOOST_TT_BROKEN_COMPILER_SPEC(proxy_iterator::proxy) template <class T>
struct lvalue_iterator
{
typedef T value_type;
typedef T& reference;
typedef T difference_type;
typedef std::input_iterator_tag iterator_category;
typedef T* pointer;
T& operator*() const;
lvalue_iterator& operator++();
lvalue_iterator operator++(int);
};
template <class T>
struct constant_lvalue_iterator
{
typedef T value_type;
typedef T const& reference;
typedef T difference_type;
typedef std::input_iterator_tag iterator_category;
typedef T const* pointer;
T const& operator*() const;
constant_lvalue_iterator& operator++();
constant_lvalue_iterator operator++(int);
};
BOOST_TT_BROKEN_COMPILER_SPEC(proxy_iterator<v>::proxy)
BOOST_TT_BROKEN_COMPILER_SPEC(proxy_iterator<int>::proxy)
int main() int main()
{ {
@ -62,7 +94,8 @@ int main()
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<std::deque<v>::const_iterator>::value); BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<std::deque<v>::const_iterator>::value);
BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator<std::back_insert_iterator<std::deque<v> > >::value); BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator<std::back_insert_iterator<std::deque<v> > >::value);
BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator<std::ostream_iterator<v> >::value); BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator<std::ostream_iterator<v> >::value);
BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator<proxy_iterator>::value); BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator<proxy_iterator<v> >::value);
BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator<proxy_iterator<int> >::value);
#ifndef BOOST_NO_LVALUE_RETURN_DETECTION #ifndef BOOST_NO_LVALUE_RETURN_DETECTION
BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator<value_iterator>::value); BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator<value_iterator>::value);
#endif #endif
@ -70,18 +103,43 @@ int main()
// reference binding // reference binding
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<noncopyable_iterator>::value); BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<noncopyable_iterator>::value);
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<lvalue_iterator<v> >::value);
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<lvalue_iterator<int> >::value);
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<lvalue_iterator<char*> >::value);
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<lvalue_iterator<float> >::value);
BOOST_STATIC_ASSERT(boost::is_mutable_lvalue_iterator<v*>::value); BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<constant_lvalue_iterator<v> >::value);
BOOST_STATIC_ASSERT(!boost::is_mutable_lvalue_iterator<v const*>::value); BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<constant_lvalue_iterator<int> >::value);
BOOST_STATIC_ASSERT(boost::is_mutable_lvalue_iterator<std::deque<v>::iterator>::value); BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<constant_lvalue_iterator<char*> >::value);
BOOST_STATIC_ASSERT(!boost::is_mutable_lvalue_iterator<std::deque<v>::const_iterator>::value); BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<constant_lvalue_iterator<float> >::value);
BOOST_STATIC_ASSERT(!boost::is_mutable_lvalue_iterator<std::back_insert_iterator<std::deque<v> > >::value);
BOOST_STATIC_ASSERT(!boost::is_mutable_lvalue_iterator<std::ostream_iterator<v> >::value);
BOOST_STATIC_ASSERT(!boost::is_mutable_lvalue_iterator<proxy_iterator>::value);
BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator<v*>::value);
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<v const*>::value);
BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator<std::deque<v>::iterator>::value);
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<std::deque<v>::const_iterator>::value);
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<std::back_insert_iterator<std::deque<v> > >::value);
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<std::ostream_iterator<v> >::value);
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<proxy_iterator<v> >::value);
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<proxy_iterator<int> >::value);
#ifndef BOOST_NO_LVALUE_RETURN_DETECTION #ifndef BOOST_NO_LVALUE_RETURN_DETECTION
BOOST_STATIC_ASSERT(!boost::is_mutable_lvalue_iterator<value_iterator>::value); BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<value_iterator>::value);
#endif #endif
BOOST_STATIC_ASSERT(!boost::is_mutable_lvalue_iterator<noncopyable_iterator>::value); BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<noncopyable_iterator>::value);
BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator<lvalue_iterator<v> >::value);
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator<lvalue_iterator<int> >::value);
#endif
BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator<lvalue_iterator<char*> >::value);
BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator<lvalue_iterator<float> >::value);
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<constant_lvalue_iterator<v> >::value);
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<constant_lvalue_iterator<int> >::value);
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<constant_lvalue_iterator<char*> >::value);
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<constant_lvalue_iterator<float> >::value);
return 0; return 0;
} }

View File

@ -14,6 +14,10 @@
#include <numeric> #include <numeric>
#include <boost/iterator/iterator_adaptor.hpp> #include <boost/iterator/iterator_adaptor.hpp>
#if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
# include <boost/iterator/is_readable_iterator.hpp>
# include <boost/iterator/is_lvalue_iterator.hpp>
#endif
#include <boost/pending/iterator_tests.hpp> #include <boost/pending/iterator_tests.hpp>
# include <boost/type_traits/broken_compiler_spec.hpp> # include <boost/type_traits/broken_compiler_spec.hpp>
@ -26,7 +30,7 @@
#include "static_assert_same.hpp" #include "static_assert_same.hpp"
struct my_iterator_tag : public std::random_access_iterator_tag { }; #include <boost/iterator/detail/config_def.hpp>
using boost::dummyT; using boost::dummyT;
@ -83,7 +87,7 @@ struct ptr_iterator
ptr_iterator<V> ptr_iterator<V>
, V* , V*
, V , V
, std::random_access_iterator_tag , boost::random_access_traversal_tag
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
, V& , V&
#endif #endif
@ -94,7 +98,7 @@ private:
ptr_iterator<V> ptr_iterator<V>
, V* , V*
, V , V
, std::random_access_iterator_tag , boost::random_access_traversal_tag
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
, V& , V&
#endif #endif
@ -114,13 +118,13 @@ public:
}; };
// Non-functional iterator for category modification checking // Non-functional iterator for category modification checking
template <class Iter, class Category> template <class Iter, class Traversal>
struct modify_category struct modify_traversal
: boost::iterator_adaptor< : boost::iterator_adaptor<
modify_category<Iter, Category> modify_traversal<Iter, Traversal>
, Iter , Iter
, boost::use_default , boost::use_default
, Category , Traversal
> >
{}; {};
@ -179,6 +183,33 @@ struct constant_iterator
: base_t(it) {} : base_t(it) {}
}; };
char (& traversal2(boost::incrementable_traversal_tag) )[1];
char (& traversal2(boost::single_pass_traversal_tag ) )[2];
char (& traversal2(boost::forward_traversal_tag ) )[3];
char (& traversal2(boost::bidirectional_traversal_tag) )[4];
char (& traversal2(boost::random_access_traversal_tag) )[5];
template <class Cat>
struct traversal3
{
static typename boost::iterator_category_to_traversal<Cat>::type x;
BOOST_STATIC_CONSTANT(std::size_t, value = sizeof(traversal2(x)));
typedef char (&type)[value];
};
template <class Cat>
typename traversal3<Cat>::type traversal(Cat);
template <class Iter, class Trav>
int static_assert_traversal(Iter* = 0, Trav* = 0)
{
typedef typename boost::iterator_category_to_traversal<
BOOST_DEDUCED_TYPENAME Iter::iterator_category
>::type t2;
return static_assert_same<Trav,t2>::value;
}
int int
main() main()
{ {
@ -219,7 +250,17 @@ main()
typedef ptr_iterator<int const> Iter1; typedef ptr_iterator<int const> Iter1;
test = static_assert_same<Iter1::value_type, int>::value; test = static_assert_same<Iter1::value_type, int>::value;
test = static_assert_same<Iter1::reference, const int&>::value; test = static_assert_same<Iter1::reference, const int&>::value;
test = static_assert_same<Iter1::iterator_category::access, boost::readable_lvalue_iterator_tag>::value; test = static_assert_same<Iter1::pointer, const int*>::value;
#if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
BOOST_STATIC_ASSERT(boost::is_readable_iterator<Iter1>::value);
# ifndef BOOST_NO_LVALUE_RETURN_DETECTION
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<Iter1>::value);
# endif
#endif
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) // borland drops constness
test = static_assert_same<Iter1::pointer, int const*>::value;
#endif
} }
{ {
@ -229,19 +270,19 @@ main()
test = static_assert_same<Iter::value_type, int>::value; test = static_assert_same<Iter::value_type, int>::value;
test = static_assert_same<Iter::reference, int const&>::value; test = static_assert_same<Iter::reference, int const&>::value;
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) // borland drops constness
test = static_assert_same<Iter::pointer, int const*>::value; test = static_assert_same<Iter::pointer, int const*>::value;
#endif
test = static_assert_same<BaseIter::iterator_category::access, boost::writable_lvalue_iterator_tag>::value; #ifndef BOOST_NO_LVALUE_RETURN_DETECTION
test = static_assert_same<Iter::iterator_category::access, boost::readable_lvalue_iterator_tag>::value; BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator<BaseIter>::value);
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<Iter>::value);
// Test category modification #endif
typedef modify_category<BaseIter, boost::readable_iterator_tag> ReadableIter;
test = static_assert_same<ReadableIter::iterator_category::access, boost::readable_iterator_tag>::value; typedef modify_traversal<BaseIter, boost::incrementable_traversal_tag> IncrementableIter;
typedef modify_category<BaseIter, boost::incrementable_traversal_tag> IncrementableIter;
test = static_assert_same<BaseIter::iterator_category::traversal, boost::random_access_traversal_tag>::value;
test = static_assert_same<IncrementableIter::iterator_category::traversal, boost::incrementable_traversal_tag>::value;
static_assert_traversal<BaseIter,boost::random_access_traversal_tag>();
static_assert_traversal<IncrementableIter,boost::incrementable_traversal_tag>();
} }
// Test the iterator_adaptor // Test the iterator_adaptor

View File

@ -12,14 +12,15 @@
int main() int main()
{ {
{ typedef boost::iterator_archetype<
typedef boost::iterator_archetype<int, int
boost::writable_lvalue_iterator_tag, , boost::iterator_archetypes::writable_lvalue_iterator_t
boost::random_access_traversal_tag> iter; , boost::random_access_traversal_tag
> iter;
boost::function_requires< boost_concepts::WritableLvalueIteratorConcept<iter> >(); boost::function_requires< boost_concepts::WritableLvalueIteratorConcept<iter> >();
boost::function_requires< boost_concepts::RandomAccessTraversalConcept<iter> >(); boost::function_requires< boost_concepts::RandomAccessTraversalConcept<iter> >();
}
return 0; // keep msvc happy return 0; // keep msvc happy
} }

View File

@ -1,91 +0,0 @@
// Copyright David Abrahams 2003. Use, modification and distribution is
// subject to 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)
#include <boost/iterator/iterator_categories.hpp>
using namespace boost;
// Utility function which converts an iterator_category into a
// traversal tag
template <class C>
typename iterator_category_to_traversal<C>::type c2t(C)
{
typedef typename iterator_category_to_traversal<C>::type result;
return result();
}
struct v
{
v();
~v();
};
//
// Test conversions from iterator_tag<...> to old-style iterator categories
//
// These "solid" tag types ensure exact matching of iterator
// classification, because unlike the std:: iterator tags, they're not
// inter-convertible
struct output_iter {};
struct input_iter {};
struct input_output_iter {};
struct forward_iter {};
struct bidirectional_iter {};
struct random_access_iter{} ;
// Convert various old-style categories into "solid" tags.
input_iter cat(std::input_iterator_tag);
output_iter cat(std::output_iterator_tag);
input_output_iter cat(boost::detail::input_output_iterator_tag);
forward_iter cat(std::forward_iterator_tag);
bidirectional_iter cat(std::bidirectional_iterator_tag);
random_access_iter cat(std::random_access_iterator_tag);
random_access_iter x1 = cat(iterator_tag<v,v&,random_access_traversal_tag>());
random_access_iter x2 = cat(iterator_tag<v,v const&,random_access_traversal_tag>());
bidirectional_iter x3 = cat(iterator_tag<v,v const&,bidirectional_traversal_tag>());
forward_iter x4 = cat(iterator_tag<v,v const&,forward_traversal_tag>());
input_output_iter x5 = cat(iterator_tag<v,v,bidirectional_traversal_tag>());
input_iter x6 = cat(iterator_tag<v const,v,bidirectional_traversal_tag>());
output_iter x7 = cat(iterator_tag<v,v const&,incrementable_traversal_tag>());
//
// Test conversion from old-style iterator categories to traversal categories
//
// These "solid" tag types ensure exact matching of iterator
// classification, because unlike the traversal tags, they're not
// inter-convertible
struct incrementable_traversal {};
struct single_pass_traversal {};
struct forward_traversal {};
struct bidirectional_traversal {};
struct random_access_traversal {} ;
// Convert various traversal categories into "solid" tags
incrementable_traversal trav(incrementable_traversal_tag);
single_pass_traversal trav(single_pass_traversal_tag);
forward_traversal trav(forward_traversal_tag);
bidirectional_traversal trav(bidirectional_traversal_tag);
random_access_traversal trav(random_access_traversal_tag);
// Show that full types of tags that are already traversal categories
// are preserved
iterator_tag<v,v&,random_access_traversal_tag> yz1
= c2t(iterator_tag<v,v&,random_access_traversal_tag>());
// Test traversal extraction from both old-style and new-style tags
random_access_traversal yy1 = trav(c2t(iterator_tag<v,v&,random_access_traversal_tag>()));
bidirectional_traversal yy2 = trav(c2t(iterator_tag<v,v&,bidirectional_traversal_tag>()));
forward_traversal yy3 = trav(c2t(iterator_tag<v,v const&,forward_traversal_tag>()));
single_pass_traversal yy4 = trav(c2t(iterator_tag<v const,v,single_pass_traversal_tag>()));
incrementable_traversal yy5 = trav(c2t(iterator_tag<v,v const&,incrementable_traversal_tag>()));
random_access_traversal z1 = trav(c2t(std::random_access_iterator_tag()));
bidirectional_traversal z2 = trav(c2t(std::bidirectional_iterator_tag()));
forward_traversal z3 = trav(c2t(std::forward_iterator_tag()));
single_pass_traversal z4 = trav(c2t(std::input_iterator_tag()));
incrementable_traversal z5 = trav(c2t(std::output_iterator_tag()));

View File

@ -11,8 +11,6 @@
using boost::dummyT; using boost::dummyT;
BOOST_TT_BROKEN_COMPILER_SPEC(boost::dummyT)
// Test reverse iterator // Test reverse iterator
int main() int main()
{ {

View File

@ -10,13 +10,17 @@
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <class T, class U> template <class T, class U>
struct static_assert_same; struct static_assert_same_base;
template <class T> template <class T>
struct static_assert_same<T,T> struct static_assert_same_base<T,T>
{ {
enum { value = 1 }; enum { value = 1 };
}; };
template <class T, class U>
struct static_assert_same : static_assert_same_base<T,U> {};
#else #else
# include <boost/mpl/if.hpp> # include <boost/mpl/if.hpp>
# include <boost/mpl/bool.hpp> # include <boost/mpl/bool.hpp>

View File

@ -184,17 +184,14 @@ main()
for (int k2 = 0; k2 < N; ++k2) for (int k2 = 0; k2 < N; ++k2)
x[k2] = x[k2] * 2; x[k2] = x[k2] * 2;
boost::input_iterator_test(boost::make_transform_iterator(y, mult_2) boost::input_iterator_test(
, x[0] boost::make_transform_iterator(y, mult_2), x[0], x[1]);
, x[1]);
boost::input_iterator_test(boost::make_transform_iterator(&y[0], mult_2) boost::input_iterator_test(
, x[0] boost::make_transform_iterator(&y[0], mult_2), x[0], x[1]);
, x[1]);
boost::random_access_readable_iterator_test(boost::make_transform_iterator(y, mult_2) boost::random_access_readable_iterator_test(
, N boost::make_transform_iterator(y, mult_2), N, x);
, x);
} }
@ -213,25 +210,34 @@ main()
} }
std::copy(x, std::copy(
x + N, x
boost::make_transform_iterator((pair_t*)values, select_first())); , x + N
, boost::make_transform_iterator((pair_t*)values, select_first())
);
std::copy(y, std::copy(
y + N, y
boost::make_transform_iterator((pair_t*)values, select_second())); , y + N
, boost::make_transform_iterator((pair_t*)values, select_second())
);
boost::random_access_readable_iterator_test(boost::make_transform_iterator((pair_t*)values, value_select_first()), boost::random_access_readable_iterator_test(
N, boost::make_transform_iterator((pair_t*)values, value_select_first())
x); , N
, x
);
boost::random_access_readable_iterator_test(boost::make_transform_iterator((pair_t*)values, const_select_first()), boost::random_access_readable_iterator_test(
N, boost::make_transform_iterator((pair_t*)values, const_select_first())
x); , N, x
);
boost::constant_lvalue_iterator_test(boost::make_transform_iterator((pair_t*)values, const_select_first()), x[0]); boost::constant_lvalue_iterator_test(
boost::make_transform_iterator((pair_t*)values, const_select_first()), x[0]);
boost::mutable_lvalue_iterator_test(boost::make_transform_iterator((pair_t*)values, select_first()), x[0], 17); boost::non_const_lvalue_iterator_test(
boost::make_transform_iterator((pair_t*)values, select_first()), x[0], 17);
} }

View File

@ -5,9 +5,12 @@
// to its suitability for any purpose. // to its suitability for any purpose.
#include <boost/iterator/iterator_adaptor.hpp> #include <boost/iterator/iterator_adaptor.hpp>
#include <boost/static_assert.hpp> #include <boost/static_assert.hpp>
#include "static_assert_same.hpp" #include "static_assert_same.hpp"
#include <boost/type_traits/broken_compiler_spec.hpp> #include <boost/type_traits/broken_compiler_spec.hpp>
#include <boost/iterator/detail/minimum_category.hpp>
struct X { int a; }; struct X { int a; };
@ -40,29 +43,32 @@ void category_test()
using namespace boost::detail; using namespace boost::detail;
BOOST_STATIC_ASSERT(( BOOST_STATIC_ASSERT((
!is_tag< !boost::is_convertible<
input_output_iterator_tag
, std::input_iterator_tag>::value));
BOOST_STATIC_ASSERT((
!is_tag<
input_output_iterator_tag
, std::output_iterator_tag>::value));
BOOST_STATIC_ASSERT((
is_tag<
std::input_iterator_tag std::input_iterator_tag
, input_output_iterator_tag>::value)); , input_output_iterator_tag>::value));
BOOST_STATIC_ASSERT(( BOOST_STATIC_ASSERT((
is_tag< !boost::is_convertible<
std::output_iterator_tag std::output_iterator_tag
, input_output_iterator_tag>::value)); , input_output_iterator_tag>::value));
BOOST_STATIC_ASSERT(( BOOST_STATIC_ASSERT((
is_tag< boost::is_convertible<
input_output_iterator_tag input_output_iterator_tag
, std::forward_iterator_tag>::value)); , std::input_iterator_tag>::value));
BOOST_STATIC_ASSERT((
boost::is_convertible<
input_output_iterator_tag
, std::output_iterator_tag>::value));
#if 0 // This seems wrong; we're not advertising
// input_output_iterator_tag are we?
BOOST_STATIC_ASSERT((
boost::is_convertible<
std::forward_iterator_tag
, input_output_iterator_tag>::value));
#endif
int test = static_assert_min_cat< int test = static_assert_min_cat<
std::input_iterator_tag,input_output_iterator_tag, std::input_iterator_tag std::input_iterator_tag,input_output_iterator_tag, std::input_iterator_tag
@ -72,9 +78,11 @@ void category_test()
input_output_iterator_tag,std::input_iterator_tag, std::input_iterator_tag input_output_iterator_tag,std::input_iterator_tag, std::input_iterator_tag
>::value; >::value;
#if 0
test = static_assert_min_cat< test = static_assert_min_cat<
input_output_iterator_tag,std::forward_iterator_tag, input_output_iterator_tag input_output_iterator_tag,std::forward_iterator_tag, input_output_iterator_tag
>::value; >::value;
#endif
test = static_assert_min_cat< test = static_assert_min_cat<
std::input_iterator_tag,std::forward_iterator_tag, std::input_iterator_tag std::input_iterator_tag,std::forward_iterator_tag, std::input_iterator_tag
@ -84,29 +92,13 @@ void category_test()
std::input_iterator_tag,std::random_access_iterator_tag, std::input_iterator_tag std::input_iterator_tag,std::random_access_iterator_tag, std::input_iterator_tag
>::value; >::value;
#if 0 // This would be wrong: a random access iterator is not
// neccessarily writable, as is an output iterator.
test = static_assert_min_cat< test = static_assert_min_cat<
std::output_iterator_tag,std::random_access_iterator_tag, std::output_iterator_tag std::output_iterator_tag,std::random_access_iterator_tag, std::output_iterator_tag
>::value; >::value;
#endif
BOOST_STATIC_ASSERT((is_traversal_tag< incrementable_traversal_tag >::value));
BOOST_STATIC_ASSERT((is_traversal_tag< single_pass_traversal_tag >::value));
BOOST_STATIC_ASSERT((is_traversal_tag< forward_traversal_tag >::value));
BOOST_STATIC_ASSERT((is_traversal_tag< bidirectional_traversal_tag >::value));
BOOST_STATIC_ASSERT((is_traversal_tag< random_access_traversal_tag >::value));
BOOST_STATIC_ASSERT((!is_traversal_tag< std::input_iterator_tag >::value));
BOOST_STATIC_ASSERT((!is_traversal_tag< readable_iterator_tag >::value));
BOOST_STATIC_ASSERT((is_access_tag< readable_iterator_tag >::value));
BOOST_STATIC_ASSERT((is_access_tag< writable_iterator_tag >::value));
BOOST_STATIC_ASSERT((is_access_tag< swappable_iterator_tag >::value));
BOOST_STATIC_ASSERT((is_access_tag< readable_writable_iterator_tag >::value));
BOOST_STATIC_ASSERT((is_access_tag< readable_lvalue_iterator_tag >::value));
BOOST_STATIC_ASSERT((is_access_tag< writable_lvalue_iterator_tag >::value));
BOOST_STATIC_ASSERT((!is_access_tag< std::input_iterator_tag >::value));
BOOST_STATIC_ASSERT((!is_access_tag< incrementable_traversal_tag >::value));
(void)test; (void)test;
} }

View File

@ -48,32 +48,18 @@
#include <set> #include <set>
#include <boost/tuple/tuple.hpp> #include <boost/tuple/tuple.hpp>
#include <boost/iterator/transform_iterator.hpp> #include <boost/iterator/transform_iterator.hpp>
#include <boost/iterator/is_readable_iterator.hpp>
#include <boost/type_traits/is_same.hpp> #include <boost/type_traits/is_same.hpp>
#include <boost/detail/workaround.hpp> #include <boost/detail/workaround.hpp>
#include <stddef.h> #include <stddef.h>
// Uncomment to see static assert. template <class It>
// #define PROVOKE_STATIC_ASSERT struct pure_traversal
: boost::detail::pure_traversal_tag<
///////////////////////////////////////////////////////////////////////////// typename boost::iterator_traversal<It>::type
// >
// Fake iterator for testing zip iterator categories {};
//
/////////////////////////////////////////////////////////////////////////////
class fake_writable_iterator
{
public:
typedef int& reference;
typedef int value_type;
typedef int* pointer;
typedef ptrdiff_t difference_type;
typedef boost::iterator_tag<
boost::writable_iterator_tag,
boost::forward_traversal_tag
> iterator_category;
};
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// //
// Das Main Funktion // Das Main Funktion
@ -871,25 +857,15 @@ int main( void )
// The big iterator of the previous test has vector, list, and set iterators. // The big iterator of the previous test has vector, list, and set iterators.
// Therefore, it must be bidirectional, but not random access. // Therefore, it must be bidirectional, but not random access.
bool bBigItIsBidirectionalIterator = boost::is_same< bool bBigItIsBidirectionalIterator = boost::is_convertible<
boost::bidirectional_traversal_tag, boost::iterator_traversal<zip_it_12_type>::type
boost::traversal_category<zip_it_12_type>::type , boost::bidirectional_traversal_tag
>::value; >::value;
//
bool bBigItIsRandomAccessIterator = boost::is_same< bool bBigItIsRandomAccessIterator = boost::is_convertible<
boost::random_access_traversal_tag, boost::iterator_traversal<zip_it_12_type>::type
boost::traversal_category<zip_it_12_type>::type , boost::random_access_traversal_tag
>::value; >::value;
//
bool bBigItIsReadableIterator = boost::is_same<
boost::readable_iterator_tag,
boost::access_category<zip_it_12_type>::type
>::value;
//
bool bBigItIsReadableLValueIterator = boost::is_same<
boost::readable_lvalue_iterator_tag,
boost::access_category<zip_it_12_type>::type
>::value;
// A combining iterator with all vector iterators must have random access // A combining iterator with all vector iterators must have random access
// traversal. // traversal.
@ -901,63 +877,15 @@ int main( void )
> >
> all_vects_type; > all_vects_type;
bool bAllVectsIsRandomAccessIterator = boost::is_same< bool bAllVectsIsRandomAccessIterator = boost::is_convertible<
boost::random_access_traversal_tag, boost::iterator_traversal<all_vects_type>::type
boost::traversal_category<all_vects_type>::type , boost::random_access_traversal_tag
>::value; >::value;
//
bool bAllVectsIsReadableIterator = boost::is_same<
boost::readable_iterator_tag,
boost::access_category<all_vects_type>::type
>::value;
//
bool bAllVectsIsReadableLValueIterator = boost::is_same<
boost::readable_lvalue_iterator_tag,
boost::access_category<all_vects_type>::type
>::value;
// Test if the meta function all_iterators_readable, which is used
// for compile-time asserting, works.
//
bool bAllIteratorsReadable1 =
boost::detail::all_iterators_in_tuple_readable<
boost::tuples::tuple<
std::vector<int>::const_iterator,
std::set<double>::iterator
>
>::type::value;
bool bAllIteratorsReadable2 =
boost::detail::all_iterators_in_tuple_readable<
boost::tuples::tuple<
std::vector<int>::const_iterator,
fake_writable_iterator,
std::set<double>::iterator
>
>::type::value;
// Compile-time assert because of non-readable iterator.
//
#ifdef PROVOKE_STATIC_ASSERT
typedef boost::zip_iterator<
boost::tuples::tuple<
fake_writable_iterator
>
>no_compile_type;
no_compile_type no_compile;
#endif
// The big test. // The big test.
if( bBigItIsBidirectionalIterator && if( bBigItIsBidirectionalIterator &&
! bBigItIsRandomAccessIterator && ! bBigItIsRandomAccessIterator &&
bBigItIsReadableIterator && bAllVectsIsRandomAccessIterator
! bBigItIsReadableLValueIterator &&
bAllVectsIsRandomAccessIterator &&
! bAllVectsIsReadableLValueIterator &&
bAllVectsIsReadableIterator &&
bAllIteratorsReadable1 &&
! bAllIteratorsReadable2
) )
{ {
++num_successful_tests; ++num_successful_tests;
@ -977,6 +905,6 @@ int main( void )
<< "\nNumber of failed tests: " << static_cast<unsigned int>(num_failed_tests) << "\nNumber of failed tests: " << static_cast<unsigned int>(num_failed_tests)
<< std::endl; << std::endl;
return 0; return num_failed_tests;
} }