Many changes from Oxford

[SVN r1137]
This commit is contained in:
Dave Abrahams
2003-04-09 11:51:08 +00:00
parent 02c16f50a2
commit a846fe50d2
20 changed files with 1612 additions and 1032 deletions

View File

@@ -0,0 +1,194 @@
// Copyright David Abrahams 2003. Permission to copy, use,
// modify, 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 COUNTING_ITERATOR_DWA200348_HPP
# define COUNTING_ITERATOR_DWA200348_HPP
# include <boost/iterator/iterator_adaptor.hpp>
# include <boost/detail/numeric_traits.hpp>
# include <boost/mpl/bool.hpp>
# include <boost/mpl/if.hpp>
# include <boost/mpl/identity.hpp>
# include <boost/mpl/apply_if.hpp>
namespace boost {
template <class Incrementable, class Category, class Difference> class counting_iterator;
namespace detail
{
// Try to detect numeric types at compile time in ways compatible
// with the limitations of the compiler and library.
template <class T>
struct is_numeric_impl
{
// For a while, this wasn't true, but we rely on it below. This is a regression assert.
BOOST_STATIC_ASSERT(::boost::is_integral<char>::value);
# ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
# if defined(BOOST_HAS_LONG_LONG)
BOOST_STATIC_CONSTANT(
bool, value = (
std::numeric_limits<T>::is_specialized
| boost::is_same<T,long long>::value
| boost::is_same<T,unsigned long long>::value
));
# else
BOOST_STATIC_CONSTANT(bool, value = std::numeric_limits<T>::is_specialized);
# endif
# else
# if !defined(__BORLANDC__)
BOOST_STATIC_CONSTANT(
bool, value = (
boost::is_convertible<int,T>::value
&& boost::is_convertible<T,int>::value
));
# else
BOOST_STATIC_CONSTANT(bool, value = ::boost::is_arithmetic<T>::value);
# endif
# endif
};
template <class T>
struct is_numeric
: mpl::bool_<(::boost::detail::is_numeric_impl<T>::value)>
{};
template <class T>
struct numeric_difference
{
typedef typename boost::detail::numeric_traits<T>::difference_type type;
};
BOOST_STATIC_ASSERT(is_numeric<int>::value);
template <class Incrementable, class Category, class Difference>
struct counting_iterator_base
{
typedef typename mpl::apply_if<
is_same<Category, not_specified>
, mpl::apply_if<
is_numeric<Incrementable>
, mpl::identity<std::random_access_iterator_tag>
, BOOST_ITERATOR_CATEGORY<Incrementable>
>
, mpl::identity<Category>
>::type category;
typedef typename mpl::apply_if<
is_same<Difference, not_specified>
, mpl::apply_if<
is_numeric<Incrementable>
, numeric_difference<Incrementable>
, iterator_difference<Incrementable>
>
, mpl::identity<Difference>
>::type difference;
typedef iterator_adaptor<
counting_iterator<Incrementable, Category, Difference> // self
, Incrementable // Base
, Incrementable // value_type
, category
, Incrementable const& // reference
, Incrementable const* // pointer
, difference
> type;
};
// Template class distance_policy_select -- choose a policy for computing the
// distance between counting_iterators at compile-time based on whether or not
// the iterator wraps an integer or an iterator, using "poor man's partial
// specialization".
template <bool is_integer> struct distance_policy_select;
// A policy for wrapped iterators
template <class Difference, class Incrementable1, class Incrementable2>
struct iterator_distance
{
static Difference distance(Incrementable1 x, Incrementable2 y)
{
return boost::detail::distance(x, y);
}
};
// A policy for wrapped numbers
template <class Difference, class Incrementable1, class Incrementable2>
struct number_distance
{
static Difference distance(Incrementable1 x, Incrementable2 y)
{
return numeric_distance(x, y);
}
};
}
template <class Incrementable, class Category = not_specified, class Difference = not_specified>
class counting_iterator
: public detail::counting_iterator_base<Incrementable, Category, Difference>::type
{
typedef typename detail::counting_iterator_base<Incrementable, Category, Difference>::type super_t;
friend class iterator_core_access;
public:
typedef typename super_t::difference_type difference_type;
counting_iterator() { }
counting_iterator(counting_iterator const& rhs) : super_t(rhs.base()) {}
counting_iterator(Incrementable x)
: super_t(x)
{
}
# if 0
template<class OtherIncrementable>
counting_iterator(
counting_iterator<OtherIncrementable> const& t
, typename enable_if_convertible<OtherIncrementable, Incrementable>::type* = 0
)
: super_t(t.base())
{}
# endif
private:
typename super_t::reference dereference() const
{
return this->base_reference();
}
template <class OtherIncrementable>
difference_type
distance_to(counting_iterator<OtherIncrementable> const& y) const
{
typedef typename mpl::if_<
detail::is_numeric<Incrementable>
, detail::number_distance<difference_type, Incrementable, OtherIncrementable>
, detail::iterator_distance<difference_type, Incrementable, OtherIncrementable>
>::type d;
return d::distance(this->base(), y.base());
}
};
// Manufacture a counting iterator for an arbitrary incrementable type
template <class Incrementable>
inline counting_iterator<Incrementable>
make_counting_iterator(Incrementable x)
{
typedef counting_iterator<Incrementable> result_t;
return result_t(x);
}
} // namespace boost::iterator
#endif // COUNTING_ITERATOR_DWA200348_HPP

View File

@@ -13,42 +13,98 @@
#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 <iterator>
#if BOOST_WORKAROUND(__MWERKS__, <=0x2407)
# define BOOST_NO_IS_CONVERTIBLE // "Convertible does not provide enough/is not working"
#endif
namespace boost {
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;
};
//
// Categories
//
// !! Fix detection functions if categories
// are changed.
//
// Return Type Categories
struct readable_iterator_tag { };
struct writable_iterator_tag { };
struct swappable_iterator_tag :
virtual public readable_iterator_tag, // Not sure about this change -JGS
virtual public writable_iterator_tag { };
struct constant_lvalue_iterator_tag :
virtual public readable_iterator_tag { };
struct mutable_lvalue_iterator_tag :
virtual public swappable_iterator_tag,
virtual public constant_lvalue_iterator_tag { };
// Traversal Categories
struct input_traversal_tag { };
struct output_traversal_tag { };
struct forward_traversal_tag : virtual public input_traversal_tag,
virtual public output_traversal_tag { };
struct bidirectional_traversal_tag : virtual public forward_traversal_tag { };
struct random_access_traversal_tag : virtual public bidirectional_traversal_tag { };
//
struct incrementable_iterator_tag
{
typedef std::output_iterator_tag max_category;
};
struct single_pass_iterator_tag
: incrementable_iterator_tag
{
typedef detail::input_output_iterator_tag max_category;
};
struct forward_traversal_tag
: single_pass_iterator_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 { };
@@ -57,384 +113,162 @@ namespace boost {
//
// Tag detection meta functions
//
// Needed to work with compilers
// without working is_convertible
//
#ifndef BOOST_NO_IS_CONVERTIBLE
template <class Category>
struct is_input_iterator :
is_convertible<Category*, std::input_iterator_tag*>
{
};
template <class Category>
struct is_output_iterator :
is_convertible<Category*, std::output_iterator_tag*>
{
};
template <class Category>
struct is_forward_iterator :
is_convertible<Category*, std::forward_iterator_tag*>
{
};
template <class Category>
struct is_bidirectional_iterator :
is_convertible<Category*, std::bidirectional_iterator_tag*>
{
};
template <class Category>
struct is_random_access_iterator :
is_convertible<Category*, std::random_access_iterator_tag*>
{
};
template <class Category>
struct is_readable_iterator :
is_convertible<Category*, readable_iterator_tag*>
{ };
template <class Category>
struct is_writable_iterator :
is_convertible<Category*, writable_iterator_tag*>
{ };
template <class Category>
struct is_swappable_iterator :
is_convertible<Category*, swappable_iterator_tag*>
{ };
template <class Category>
struct is_constant_lvalue_iterator :
is_convertible<Category*, constant_lvalue_iterator_tag*>
{ };
template <class Category>
struct is_mutable_lvalue_iterator :
is_convertible<Category*, mutable_lvalue_iterator_tag*>
{ };
template <class Category>
struct is_input_traversal_iterator :
is_convertible<Category*, input_traversal_tag*>
{ };
template <class Category>
struct is_output_traversal_iterator :
is_convertible<Category*, output_traversal_tag*>
{ };
template <class Category>
struct is_forward_traversal_iterator :
is_convertible<Category*, forward_traversal_tag*>
{ };
template <class Category>
struct is_bidirectional_traversal_iterator :
is_convertible<Category*, bidirectional_traversal_tag*>
{ };
template <class Category>
struct is_random_access_traversal_iterator :
is_convertible<Category*, random_access_traversal_tag*>
{ };
#else
//
// We cannot detect the iterator category for custom
// tag types. For custom tag types false_ is returned
//
// As a result the std iterator category detection functions
// can't detect the iterator category of the new iterator_tag template.
//
//
// std iterator categories
//
template <class Category>
struct is_random_access_iterator :
mpl::false_
{};
template <>
struct is_random_access_iterator<std::random_access_iterator_tag> :
mpl::true_
{};
template <class Category>
struct is_bidirectional_iterator :
is_random_access_iterator< Category >
{};
template <>
struct is_bidirectional_iterator<std::bidirectional_iterator_tag> :
mpl::true_
{};
template <class Category>
struct is_forward_iterator :
is_bidirectional_iterator< Category >
{};
template <>
struct is_forward_iterator<std::forward_iterator_tag> :
mpl::true_
{};
template <class Category>
struct is_output_iterator :
is_forward_iterator< Category >
{};
template <>
struct is_output_iterator<std::output_iterator_tag> :
mpl::true_
{};
template <class Category>
struct is_input_iterator :
is_forward_iterator< Category >
{};
template <>
struct is_input_iterator<std::input_iterator_tag> :
mpl::true_
{};
//
// Return type
//
// The nested is_category template class are used for
// minimum category detection in iterator_adaptors.
// They are basically a poore mans is_derived replacement.
//
// A implementation may look like this
//
// template <class Cat1, class Cat2>
// struct min_cat
// : mpl::if_< is_return_category< Cat1 >::template is_category< Cat2 >,
// Cat1,
// mpl::if_< is_return_category<Cat2>::template is_category<Cat1>,
// Cat2,
// error_type
// >
// > {};
template <class Category>
struct is_mutable_lvalue_iterator :
mpl::false_
{
template <class T>
struct is_category
: boost::mpl::false_ {};
};
template <>
struct is_mutable_lvalue_iterator<mutable_lvalue_iterator_tag> :
mpl::true_
{
template <class Category>
struct is_category
: is_mutable_lvalue_iterator<Category> {};
};
template <class Category>
struct is_constant_lvalue_iterator :
is_mutable_lvalue_iterator<Category>
{};
template <>
struct is_constant_lvalue_iterator<constant_lvalue_iterator_tag> :
mpl::true_
{
template <class Category>
struct is_category
: is_constant_lvalue_iterator<Category> {};
};
template <class Category>
struct is_swappable_iterator :
is_constant_lvalue_iterator<Category>
{};
template <>
struct is_swappable_iterator<swappable_iterator_tag> :
mpl::true_
{
template <class Category>
struct is_category
: is_swappable_iterator<Category> {};
};
template <class Category>
struct is_readable_iterator :
mpl::if_< is_swappable_iterator<Category>,
is_swappable_iterator<Category>,
is_constant_lvalue_iterator<Category> >::type
{};
template <>
struct is_readable_iterator<readable_iterator_tag> :
mpl::true_
{
template <class Category>
struct is_category
: is_readable_iterator<Category> {};
};
template <class Category>
struct is_writable_iterator :
is_swappable_iterator<Category>
{};
template <>
struct is_writable_iterator<writable_iterator_tag> :
mpl::true_
{
template <class Category>
struct is_category
: is_writable_iterator<Category> {};
};
template <class Category>
struct is_return_category
: mpl::if_< is_writable_iterator<Category>,
is_writable_iterator<Category>,
is_readable_iterator<Category> >::type
{
};
//
// Traversal
//
template <class Category>
struct is_random_access_traversal_iterator :
mpl::false_
{
template <class T>
struct is_category
: boost::mpl::false_ {};
};
template <>
struct is_random_access_traversal_iterator<random_access_traversal_tag> :
mpl::true_
{
template <class Category>
struct is_category
: is_random_access_traversal_iterator<Category> {};
};
template <class Category>
struct is_bidirectional_traversal_iterator :
is_random_access_traversal_iterator< Category >
{};
template <>
struct is_bidirectional_traversal_iterator<bidirectional_traversal_tag> :
mpl::true_
{
template <class Category>
struct is_category
: is_bidirectional_traversal_iterator<Category> {};
};
template <class Category>
struct is_forward_traversal_iterator :
is_bidirectional_traversal_iterator< Category >
{};
template <>
struct is_forward_traversal_iterator<forward_traversal_tag> :
mpl::true_
{
template <class Category>
struct is_category
: is_forward_traversal_iterator<Category> {};
};
template <class Category>
struct is_input_traversal_iterator :
is_forward_traversal_iterator< Category >
{};
template <>
struct is_input_traversal_iterator<input_traversal_tag> :
mpl::true_
{
template <class Category>
struct is_category
: is_input_traversal_iterator<Category> {};
};
template <class Category>
struct is_output_traversal_iterator :
is_forward_traversal_iterator< Category >
{};
template <>
struct is_output_traversal_iterator<output_traversal_tag> :
mpl::true_
{
template <class Category>
struct is_category
: is_output_traversal_iterator<Category> {};
};
template <class Category>
struct is_traversal_category
: mpl::if_< is_input_traversal_iterator<Category>,
is_input_traversal_iterator<Category>,
is_output_traversal_iterator<Category> >::type
{};
#endif
//
// I bet this is defined somewhere else. Let's wait and see.
//
struct error_type;
#ifdef BOOST_NO_IS_CONVERTIBLE
template <class Cat1, class Cat2>
struct minimum_return_category
: mpl::if_< is_return_category< Cat1 >::template is_category< Cat2 >,
Cat1,
mpl::if_< is_return_category<Cat2>::template is_category<Cat1>,
Cat2,
error_type
>
> {};
template <class Cat1, class Cat2>
struct minimum_traversal_category
: mpl::if_< is_traversal_category< Cat1 >::template is_category< Cat2 >,
Cat1,
mpl::if_< is_traversal_category<Cat2>::template is_category<Cat1>,
Cat2,
error_type
>
> {};
template <class T1, class T2>
struct minimum_category_select
: mpl::if_< is_same< typename T1::type, error_type >,
T2,
T1 >
{};
#endif
#ifndef BOOST_NO_IS_CONVERTIBLE
template <class Base, class Derived>
struct is_base_or_same :
mpl::or_< is_same< Base, Derived >,
is_base_and_derived< Base, Derived > >
struct is_same_or_derived
# ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
: mpl::or_<
is_same<Base, Derived>
, is_base_and_derived<Base, Derived>
>
{};
# else
: is_base_and_derived<Base, Derived>
{};
template <class T> struct is_same_or_derived<T,T> : mpl::true_ {};
# endif
template <class Tag, class T>
struct is_tag
: mpl::or_<
# ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
is_same_or_derived<Tag, T>
# else
is_base_and_derived<Tag, T>
# endif
// Because we can't actually get forward_iterator_tag to
// derive from input_output_iterator_tag, we need this
// case.
, mpl::and_<
is_same_or_derived<Tag,detail::input_output_iterator_tag>
, is_same_or_derived<std::forward_iterator_tag,T>
>
>
{};
#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_iterator, forward_traversal)
BOOST_ITERATOR_DERIVED_TAG1(incrementable_iterator, single_pass_iterator)
# endif // BOOST_NO_IS_CONVERTIBLE workarounds
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION case
#endif
//
// Returns the minimum category type or error_type
// if T1 and T2 are unrelated.
@@ -446,19 +280,18 @@ namespace boost {
//
//
template <class T1, class T2>
struct minimum_category :
#ifndef BOOST_NO_IS_CONVERTIBLE
mpl::if_< is_base_or_same< T1, T2 >,
T1,
mpl::if_< is_base_or_same< T2, T1 >,
T2,
error_type > >
#else
minimum_category_select< minimum_return_category<T1, T2>,
minimum_traversal_category<T1, T2> >
#endif
struct minimum_category
: mpl::apply_if<
is_tag<T1,T2>
, mpl::identity<T1>
, mpl::if_<
is_tag<T2, T1>
, T2
, error_type
>
>
{};
} // namespace detail
} // namespace boost

View File

@@ -69,7 +69,7 @@ namespace boost
class Return>
struct enable_if
# if !defined(BOOST_NO_SFINAE) && !defined(BOOST_NO_IS_CONVERTIBLE)
: enabled<Cond::value>::template base<Return>
: enabled<(Cond::value)>::template base<Return>
# else
: mpl::identity<Return>
# endif

View File

@@ -15,20 +15,18 @@
namespace boost
{
namespace detail {
namespace detail
{
template <class Iterator>
struct filter_iterator_traits
: iterator_traits<Iterator>
struct filter_iterator_category
{
typedef iterator_tag<
typename return_category<Iterator>::type
, typename minimum_category<
forward_traversal_tag
, typename traversal_category<Iterator>::type
>::type
> iterator_category;
typedef iterator_tag<
typename access_category<Iterator>::type
, typename minimum_category<
forward_traversal_tag
, typename traversal_category<Iterator>::type
>::type
> type;
};
} // namespace detail
@@ -37,13 +35,15 @@ namespace boost
class filter_iterator
: public iterator_adaptor<
filter_iterator<Predicate, Iterator>, Iterator
, detail::filter_iterator_traits<Iterator>
, not_specified
, typename detail::filter_iterator_category<Iterator>::type
>
{
typedef iterator_adaptor<
filter_iterator<Predicate, Iterator>, Iterator
, detail::filter_iterator_traits<Iterator>
> super_t;
filter_iterator<Predicate, Iterator>, Iterator
, not_specified
, typename detail::filter_iterator_category<Iterator>::type
> super_t;
friend class iterator_core_access;

View File

@@ -13,6 +13,10 @@
#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/iterator/detail/config_def.hpp>
#include <boost/iterator/iterator_traits.hpp>
#include <boost/python/detail/indirect_traits.hpp>
#include <boost/mpl/not.hpp>
#ifdef BOOST_NO_MPL_AUX_HAS_XXX
# include <boost/shared_ptr.hpp>
@@ -23,6 +27,8 @@
namespace boost
{
template <class Iter, class Value, class Category, class Reference, class Pointer, class Difference>
struct indirect_iterator;
namespace detail
{
@@ -73,59 +79,103 @@ namespace boost
// Metafunction returning the nested element_type typedef
template <class T>
struct smart_pointer_traits
{
typedef typename remove_const<
typename T::element_type
>::type value_type;
struct smart_pointer_value : remove_const<typename T::element_type>
{};
typedef typename T::element_type& reference;
typedef typename T::element_type* pointer;
template <class T>
struct iterator_is_mutable
: mpl::not_<
boost::python::detail::is_reference_to_const<
typename iterator_reference<T>::type
>
>
{
};
template <class T>
struct not_int_impl
{
template <class U>
struct apply {
typedef T type;
};
};
template <>
struct not_int_impl<int> {};
template <class T, class U>
struct not_int
: not_int_impl<T>::template apply<U> {};
// If the Value parameter is unspecified, we use this metafunction
// to deduce the default types
template <class Iter>
struct indirect_defaults
: mpl::if_<
mpl::and_<
is_class<typename iterator_traits<Iter>::value_type>
, has_element_type<typename iterator_traits<Iter>::value_type>
>
, smart_pointer_traits<typename iterator_traits<Iter>::value_type>
, iterator_traits<typename iterator_traits<Iter>::value_type>
>::type
template <class Iter, class Value, class Category, class Reference, class Pointer, class Difference>
struct indirect_base
{
typedef typename iterator_traits<Iter>::iterator_category iterator_category;
typedef typename iterator_traits<Iter>::difference_type difference_type;
typedef typename iterator_value<Iter>::type dereferenceable;
typedef mpl::and_<
is_class<dereferenceable>
, has_element_type<dereferenceable>
> is_smart_ptr;
typedef typename mpl::apply_if<
is_smart_ptr
, smart_pointer_value<dereferenceable>
, iterator_value<dereferenceable>
>::type value_type;
typedef typename mpl::if_<
mpl::or_<
is_smart_ptr
, iterator_is_mutable<dereferenceable>
>
, value_type
, value_type const
>::type cv_value_type;
typedef iterator_adaptor<
indirect_iterator<Iter, Value, Category, Reference, Pointer, Difference>
, Iter
, cv_value_type
, Category
, Reference
, Pointer
, Difference
> type;
};
// The traits to use for indirect iterator, by default. Whatever
// is supplied gets passed through traits_iterator<...> so that it
// is ultimately derived from boost::iterator<...>
template <class Base, class Traits>
struct indirect_traits
: mpl::if_<
is_same<Traits,unspecified>
, indirect_defaults<Base>
, Traits
>::type
{
};
template <>
struct indirect_base<int, int, int, int, int, int> {};
} // namespace detail
template <class Iterator, class Traits = detail::unspecified>
class indirect_iterator :
public iterator_adaptor<
indirect_iterator<Iterator, Traits>
, Iterator
, detail::indirect_traits<Iterator,Traits> >
template <
class Iterator
, class Value = not_specified
, class Category = not_specified
, class Reference = not_specified
, class Pointer = not_specified
, class Difference = not_specified
>
class indirect_iterator
: public detail::indirect_base<
Iterator
, Value
, Category
, Reference
, Pointer
, Difference
>::type
{
typedef iterator_adaptor<
indirect_iterator<Iterator, Traits>
, Iterator
, detail::indirect_traits<Iterator,Traits>
> super_t;
typedef typename detail::indirect_base<
Iterator
, Value
, Category
, Reference
, Pointer
, Difference
>::type super_t;
friend class iterator_core_access;
@@ -145,7 +195,14 @@ namespace boost
{}
private:
typename super_t::reference dereference() const { return **this->base(); }
typename super_t::reference dereference() const
{
# if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
return const_cast<super_t::reference>(**this->base());
# else
return **this->base();
# endif
}
};

View File

@@ -17,16 +17,20 @@
#include <boost/iterator/detail/enable_if.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/not.hpp>
#include <boost/mpl/or.hpp>
#include <boost/python/detail/is_xxx.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/iterator/detail/config_def.hpp>
#include <boost/iterator/iterator_traits.hpp>
namespace boost
{
namespace detail
{
template <class Traits, class Other>
@@ -37,8 +41,8 @@ namespace boost
, typename Other::iterator_category
>
, is_same<
typename Traits::iterator_category
, typename Other::iterator_category
typename Traits::iterator_category // *** THIS IS A BUG!! ***
, typename Other::iterator_category // MAKE FAILING TEST BEFORE FIXING!!
>
>
{};
@@ -116,6 +120,7 @@ namespace boost
# endif
};
//
// iterator_traits_adaptor can be used to create new iterator traits by adapting
// the traits of a given iterator type. Together with iterator_adaptor it simplifies
@@ -123,68 +128,125 @@ namespace boost
// argument ordering is different from the std::iterator template, so that default
// arguments can be used effectivly.
//
template <
class Iterator
, class ValueType = typename detail::iterator_traits<Iterator>::value_type
, class Reference = ValueType&
, class Pointer = ValueType*
, class IteratorCategory = typename detail::iterator_traits<Iterator>::iterator_category
, class DifferenceType = typename detail::iterator_traits<Iterator>::difference_type
>
struct iterator_traits_adaptor
: iterator<
IteratorCategory
, ValueType
, DifferenceType
, Pointer
, Reference
>
// The ordering changed slightly with respect to former versions of iterator_adaptor
// The idea is that when the user needs to fiddle with the reference type
// it is highly likely that the iterator category has to be adjusted as well
//
// Value - if supplied, the value_type of the resulting iterator, unless
// const. If const, a conforming compiler strips constness for the
// value_type. If not supplied, iterator_traits<Base>::value_type is used
//
// Reference - the reference type of the resulting iterator, and in
// particular, the result type of operator*(). If not supplied but
// Value is supplied, Value& is used. Otherwise
// iterator_traits<Base>::reference is used.
//
// Pointer - the pointer type of the resulting iterator, and in
// particular, the result type of operator->(). If not
// supplied but Value is supplied, Value* is used. Otherwise
// iterator_traits<Base>::pointer is used.
//
// Category - the iterator_category of the resulting iterator. If not
// supplied, iterator_traits<Base>::iterator_category is used.
//
// Distance - the difference_type of the resulting iterator. If not
// supplied, iterator_traits<Base>::difference_type is used.
//
// TODO
// ? Automatic adjustment of category ?
//
namespace detail
{
};
template <class T, class Condition, class DefaultNullaryFn>
struct ia_dflt_help
: mpl::apply_if<
mpl::and_<
is_same<T, not_specified>
, Condition
>
, DefaultNullaryFn
, mpl::identity<T>
>
{
};
template <
class Derived
, class Base
, class Value
, class Category
, class Reference
, class Pointer
, class Difference
>
struct iterator_adaptor_base
{
typedef iterator_facade<
Derived
, typename detail::ia_dflt_help<Value , mpl::true_ , iterator_value<Base> >::type
, typename detail::ia_dflt_help<Category , mpl::true_ , BOOST_ITERATOR_CATEGORY<Base> >::type
, typename detail::ia_dflt_help<Reference , is_same<Value, not_specified> , iterator_reference<Base> >::type
, typename detail::ia_dflt_help<Pointer , is_same<Value, not_specified> , iterator_pointer<Base> >::type
, typename detail::ia_dflt_help<Difference , mpl::true_ , iterator_difference<Base> >::type
>
type;
};
}
//
//
//
template <
class Derived
, class Iterator
, class Traits = detail::iterator_traits<Iterator>
, class Base
, class Value = not_specified
, class Category = not_specified
, class Reference = not_specified
, class Pointer = not_specified
, class Difference = not_specified
>
class iterator_adaptor
: public iterator_facade<Derived,Traits>
: public detail::iterator_adaptor_base<
Derived, Base, Value, Category, Reference, Pointer, Difference
>::type
{
friend class iterator_core_access;
typedef typename detail::iterator_adaptor_base<
Derived, Base, Value, Category, Reference, Pointer, Difference
>::type super_t;
public:
iterator_adaptor() {}
explicit iterator_adaptor(Iterator iter)
explicit iterator_adaptor(Base iter)
: m_iterator(iter)
{
}
Iterator base() const
Base base() const
{ return m_iterator; }
protected:
// Core iterator interface for iterator_facade
//
typename Traits::reference dereference() const
typename super_t::reference dereference() const
{ return *m_iterator; }
template <
class OtherDerived, class OtherIterator, class OtherTraits
class OtherDerived, class OtherIterator, class V, class C, class R, class P, class D
>
bool equal(iterator_adaptor<OtherDerived,OtherIterator,OtherTraits> const& x) const
bool equal(iterator_adaptor<OtherDerived, OtherIterator, V, C, R, P, D> const& x) const
{
BOOST_STATIC_ASSERT(
(detail::same_category_and_difference<Traits,OtherTraits>::value)
(detail::same_category_and_difference<Derived,OtherDerived>::value)
);
return m_iterator == x.base();
}
void advance(typename Traits::difference_type n)
void advance(typename super_t::difference_type n)
{
m_iterator += n;
}
@@ -192,19 +254,24 @@ namespace boost
void increment() { ++m_iterator; }
void decrement() { --m_iterator; }
template <class OtherDerived, class OtherIterator, class OtherTraits>
typename Traits::difference_type distance_to(
iterator_adaptor<OtherDerived, OtherIterator, OtherTraits> const& y) const
template <
class OtherDerived, class OtherIterator, class V, class C, class R, class P, class D
>
typename super_t::difference_type distance_to(
iterator_adaptor<OtherDerived, OtherIterator, V, C, R, P, D> const& y) const
{
BOOST_STATIC_ASSERT(
(detail::same_category_and_difference<Traits,OtherTraits>::value)
(detail::same_category_and_difference<Derived,OtherDerived>::value)
);
return y.base() - m_iterator;
}
private: // data members
Iterator m_iterator;
// Needed for counting iterator
Base const& base_reference() const
{ return m_iterator; }
private: // data members
Base m_iterator;
};
} // namespace boost

View File

@@ -12,17 +12,23 @@
#include <boost/config.hpp>
#include <boost/iterator/detail/categories.hpp>
#include <boost/type_traits/conversion_traits.hpp>
#include <boost/type_traits/cv_traits.hpp>
#include <boost/python/detail/indirect_traits.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/and.hpp>
#include <boost/mpl/apply.hpp>
#include <iterator>
#if BOOST_WORKAROUND(__MWERKS__, <=0x2407)
@@ -33,60 +39,142 @@ namespace boost {
namespace detail
{
template <typename ValueType>
struct choose_lvalue_return
: mpl::if_<
is_const<ValueType>
, boost::constant_lvalue_iterator_tag
, boost::mutable_lvalue_iterator_tag>
{
};
template <typename Category, typename ValueType>
struct iter_category_to_return
: mpl::if_<
is_forward_iterator<Category>
, typename choose_lvalue_return<ValueType>::type
, typename mpl::if_<
is_input_iterator<Category>
, boost::readable_iterator_tag
, typename mpl::if_<
is_output_iterator<Category>
, boost::writable_iterator_tag
, boost::error_iterator_tag
>::type
>::type
>
// Helper metafunction for std_category below
template <class Cat, class Tag, class Next>
struct match_tag
: mpl::apply_if<is_tag<Tag, Cat>, mpl::identity<Tag>, Next>
{
};
template <typename Category>
struct iter_category_to_traversal
: mpl::if_<
is_random_access_iterator<Category>
, random_access_traversal_tag
, typename mpl::if_<
is_bidirectional_iterator<Category>
, bidirectional_traversal_tag
, typename mpl::if_<
is_forward_iterator<Category>
, forward_traversal_tag
, typename mpl::if_<
is_input_iterator<Category>
, input_traversal_tag
, output_traversal_tag
>::type
>::type
>::type
// 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_iterator_tag type;
template <class Reference>
struct apply
: mpl::identity<readable_iterator_tag> {};
};
template <>
struct std_to_new_tags<std::output_iterator_tag>
{
typedef incrementable_iterator_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
@@ -98,9 +186,13 @@ namespace boost {
// defined for cwpro7.
//
template <class Tag>
struct is_new_iterator_tag :
mpl::and_< mpl::not_< is_input_iterator<Tag> >,
mpl::not_< is_output_iterator<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) \
@@ -118,12 +210,11 @@ namespace boost {
template <class Tag>
struct is_new_iterator_tag
: //has_traversal<Tag>
mpl::if_<
is_class<Tag>
, has_traversal<Tag>
, mpl::false_
>::type
: mpl::if_<
is_class<Tag>
, has_traversal<Tag>
, mpl::false_
>::type
{
};
@@ -134,7 +225,7 @@ namespace boost {
namespace detail {
template <class NewCategoryTag>
struct get_return_category {
struct get_access_category {
typedef typename NewCategoryTag::returns type;
};
template <class NewCategoryTag>
@@ -142,51 +233,57 @@ namespace boost {
typedef typename NewCategoryTag::traversal type;
};
template <class CategoryTag, class Value>
struct return_category_tag
template <class CategoryTag, class Reference>
struct access_category_tag
: mpl::apply_if<
is_new_iterator_tag<CategoryTag>
, get_return_category<CategoryTag>
, iter_category_to_return<CategoryTag, Value>
is_new_iterator_tag<CategoryTag>
, get_access_category<CategoryTag>
, iter_category_to_access<CategoryTag, Reference>
>
{
};
template <class CategoryTag, class Value>
template <class CategoryTag>
struct traversal_category_tag
: mpl::apply_if<
is_new_iterator_tag<CategoryTag>
, get_traversal_category<CategoryTag>
, iter_category_to_traversal<CategoryTag>
>
: 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> {};
template <> struct traversal_category_tag<int> {};
# endif
} // namespace detail
template <class Iterator>
struct return_category
: detail::return_category_tag<
struct access_category
: detail::access_category_tag<
typename detail::iterator_traits<Iterator>::iterator_category
, typename detail::iterator_traits<Iterator>::value_type>
, typename detail::iterator_traits<Iterator>::reference>
{};
template <class Iterator>
struct traversal_category
: detail::traversal_category_tag<
: detail::traversal_category_tag<
typename detail::iterator_traits<Iterator>::iterator_category
, typename detail::iterator_traits<Iterator>::value_type>
>
{
};
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
template <typename T>
struct return_category<T*>
struct access_category<T*>
: mpl::if_<
is_const<T>
, constant_lvalue_iterator_tag
, mutable_lvalue_iterator_tag>
, readable_lvalue_iterator_tag
, writable_lvalue_iterator_tag>
{
};
@@ -198,50 +295,12 @@ namespace boost {
#endif
// TODO Fix this for BOOST_NO_IS_CONVERTIBLE
template <class RC, class TC>
struct cvt_iterator_category
: mpl::if_<
mpl::or_<
detail::is_mutable_lvalue_iterator<RC>
, detail::is_constant_lvalue_iterator<RC>
>
, typename mpl::if_<
detail::is_random_access_traversal_iterator<TC>
, std::random_access_iterator_tag
, typename mpl::if_<
detail::is_bidirectional_traversal_iterator<TC>
, std::bidirectional_iterator_tag
, typename mpl::if_<
detail::is_forward_traversal_iterator<TC>
, std::forward_iterator_tag
, error_iterator_tag
>::type
>::type
>::type
, typename mpl::if_<
mpl::and_<
detail::is_readable_iterator<RC>
, detail::is_input_traversal_iterator<TC>
>
, std::input_iterator_tag
, typename mpl::if_<
mpl::and_<
detail::is_writable_iterator<RC>
, detail::is_output_traversal_iterator<TC>
>
, std::output_iterator_tag
, error_iterator_tag
>::type
>::type
>
{
};
template <class ReturnTag, class TraversalTag>
struct iterator_tag : cvt_iterator_category<ReturnTag, TraversalTag>::type
struct iterator_tag
: detail::minimum_category<
typename ReturnTag::max_category
, typename TraversalTag::max_category
>
{
typedef ReturnTag returns;
typedef TraversalTag traversal;
@@ -264,11 +323,11 @@ namespace boost {
typedef char (&yes)[1];
typedef char (&no)[2];
template <class R, class T>
static yes test(iterator_tag<R,T> const&);
template <class R, class U>
static yes test(mpl::identity<iterator_tag<R,U> >*);
static no test(...);
static T inst;
static mpl::identity<T>* inst;
BOOST_STATIC_CONSTANT(bool, value = sizeof(test(inst)) == sizeof(yes));
typedef mpl::bool_<value> type;
};

View File

@@ -43,9 +43,9 @@ namespace boost_concepts {
template <typename Iterator>
class ReadableIteratorConcept {
public:
typedef typename boost::detail::iterator_traits<Iterator>::value_type value_type;
typedef typename boost::detail::iterator_traits<Iterator>::reference reference;
typedef typename boost::return_category<Iterator>::type return_category;
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::access_category<Iterator>::type access_category;
void constraints() {
boost::function_requires< boost::SGIAssignableConcept<Iterator> >();
@@ -53,7 +53,7 @@ namespace boost_concepts {
boost::function_requires<
boost::DefaultConstructibleConcept<Iterator> >();
static_assert_base_and_derived<boost::readable_iterator_tag, return_category>();
static_assert_base_and_derived<boost::readable_iterator_tag, access_category>();
reference r = *i; // or perhaps read(x)
value_type v(r);
@@ -65,7 +65,7 @@ namespace boost_concepts {
template <typename Iterator, typename ValueType>
class WritableIteratorConcept {
public:
typedef typename boost::return_category<Iterator>::type return_category;
typedef typename boost::access_category<Iterator>::type access_category;
void constraints() {
boost::function_requires< boost::SGIAssignableConcept<Iterator> >();
@@ -73,7 +73,7 @@ namespace boost_concepts {
boost::function_requires<
boost::DefaultConstructibleConcept<Iterator> >();
static_assert_base_and_derived<boost::writable_iterator_tag, return_category>();
static_assert_base_and_derived<boost::writable_iterator_tag, access_category>();
*i = v; // a good alternative could be something like write(x, v)
}
@@ -86,12 +86,12 @@ namespace boost_concepts {
public:
typedef typename boost::detail::iterator_traits<Iterator>::value_type value_type;
typedef typename boost::detail::iterator_traits<Iterator>::reference reference;
typedef typename boost::return_category<Iterator>::type return_category;
typedef typename boost::access_category<Iterator>::type access_category;
void constraints() {
boost::function_requires< ReadableIteratorConcept<Iterator> >();
static_assert_base_and_derived<boost::constant_lvalue_iterator_tag, return_category>();
static_assert_base_and_derived<boost::readable_lvalue_iterator_tag, access_category>();
BOOST_STATIC_ASSERT((boost::is_same<reference, const value_type&>::value));
@@ -106,14 +106,14 @@ namespace boost_concepts {
public:
typedef typename boost::detail::iterator_traits<Iterator>::value_type value_type;
typedef typename boost::detail::iterator_traits<Iterator>::reference reference;
typedef typename boost::return_category<Iterator>::type return_category;
typedef typename boost::access_category<Iterator>::type access_category;
void constraints() {
boost::function_requires< ReadableIteratorConcept<Iterator> >();
boost::function_requires<
WritableIteratorConcept<Iterator, value_type> >();
static_assert_base_and_derived<boost::mutable_lvalue_iterator_tag, return_category>();
static_assert_base_and_derived<boost::writable_lvalue_iterator_tag, access_category>();
BOOST_STATIC_ASSERT((boost::is_same<reference, value_type&>::value));
@@ -188,54 +188,56 @@ namespace boost_concepts {
//===========================================================================
// Iterator Interoperability Concept
namespace detail {
namespace detail
{
template <typename TraversalTag>
struct Operations;
template <typename TraversalTag>
struct Operations;
template <>
struct Operations<boost::input_traversal_tag>
{
template <>
struct Operations<boost::incrementable_iterator_tag>
{
template <typename Iterator1, typename Iterator2>
static void constraints(Iterator1 const& i1, Iterator2 const& i2)
{
i1 == i2;
i1 != i2;
i2 == i1;
i2 != i1;
// no interoperability constraints
}
};
};
template <>
struct Operations<boost::output_traversal_tag>
{
template <>
struct Operations<boost::single_pass_iterator_tag>
{
template <typename Iterator1, typename Iterator2>
static void constraints(Iterator1 const& i1, Iterator2 const& i2)
{
Operations<boost::input_traversal_tag>::constraints(i1, i2);
}
};
Operations<boost::incrementable_iterator_tag>(i1, i2);
i1 == i2;
i1 != i2;
template <>
struct Operations<boost::forward_traversal_tag>
{
i2 == i1;
i2 != i1;
}
};
template <>
struct Operations<boost::forward_traversal_tag>
{
template <typename Iterator1, typename Iterator2>
static void constraints(Iterator1 const& i1, Iterator2 const& i2)
{
Operations<boost::input_traversal_tag>::constraints(i1, i2);
Operations<boost::single_pass_iterator_tag>::constraints(i1, i2);
}
};
};
template <>
struct Operations<boost::bidirectional_traversal_tag>
{
template <>
struct Operations<boost::bidirectional_traversal_tag>
{
template <typename Iterator1, typename Iterator2>
static void constraints(Iterator1 const& i1, Iterator2 const& i2)
{
Operations<boost::forward_traversal_tag>::constraints(i1, i2);
Operations<boost::forward_traversal_tag>::constraints(i1, i2);
}
};
};
template <>
struct Operations<boost::random_access_traversal_tag>

View File

@@ -10,18 +10,25 @@
#define BOOST_ITERATOR_FACADE_23022003THW_HPP
#include <boost/static_assert.hpp>
#include <boost/iterator.hpp>
#include <boost/iterator/iterator_categories.hpp>
#include <boost/iterator/interoperable.hpp>
#include <boost/iterator/detail/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/iterator/iterator_traits.hpp>
#include <boost/iterator/detail/config_def.hpp>
#include <boost/mpl/apply_if.hpp>
namespace boost
{
struct not_specified;
namespace detail
{
@@ -53,19 +60,135 @@ namespace boost
// Generates the corresponding std::iterator specialization
// from the given iterator traits type
//
template <class Traits>
struct std_iterator_from_traits
: iterator<
typename Traits::iterator_category
, typename Traits::value_type
, typename Traits::difference_type
, typename Traits::pointer
, typename Traits::reference
>
template <class Value, class Category, class Reference, class Pointer, class Difference>
struct iterator_facade_base
{
typedef iterator<
Category
, typename remove_cv<Value>::type
, Difference
, typename mpl::if_<
is_same<Pointer, not_specified>
, Value*
, Pointer
>::type
, typename mpl::if_<
is_same<Reference, not_specified>
, Value&
, Reference
>::type
>
type;
};
// operator->() needs special support for input iterators to strictly meet the
// standard's requirements. If *i is not a reference type, we must still
// produce a (constant) lvalue to which a pointer can be formed. We do that by
// returning an instantiation of this special proxy class template.
template <class T>
struct operator_arrow_proxy
{
operator_arrow_proxy(const T& x) : m_value(x) {}
const T* operator->() const { return &m_value; }
// This function is needed for MWCW and BCC, which won't call operator->
// again automatically per 13.3.1.2 para 8
operator const T*() const { return &m_value; }
T m_value;
};
template <class Reference, class Pointer>
struct operator_arrow_pointer
{
operator_arrow_pointer(Reference x) : m_p(&x) {}
operator Pointer() const { return m_p; }
Pointer m_p;
};
template <class Value, class Category, class Reference, class Pointer>
struct operator_arrow_result
: mpl::if_<
is_tag<
readable_lvalue_iterator_tag
, typename access_category_tag<Category,Reference>::type
>
, operator_arrow_proxy<Value>
, Pointer
>
{
};
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
// Deal with ETI
template<>
struct operator_arrow_result<int, int, int, int>
{
typedef int type;
};
# endif
//
// Facade is actually an iterator. We require Facade here
// so that we do not have to go through iterator_traits
// to access the traits
//
template <class Iterator>
class index_operator_proxy
{
typedef typename Iterator::reference reference;
typedef typename Iterator::value_type value_type;
public:
index_operator_proxy(Iterator const& iter)
: m_iter(iter)
{}
operator reference()
{
return *m_iter;
}
index_operator_proxy& operator=(value_type const& val)
{
*m_iter = val;
return *this;
}
private:
Iterator m_iter;
};
template <class Iterator, class ValueType, class Category, class Reference>
struct index_operator_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_<
use_proxy
, index_operator_proxy<Iterator>
, ValueType
>::type type;
};
template <class Iterator>
index_operator_proxy<Iterator> make_index_operator_result(Iterator const& iter, mpl::true_)
{
return index_operator_proxy<Iterator>(iter);
}
template <class Iterator>
typename Iterator::value_type make_index_operator_result(Iterator const& iter, mpl::false_)
{
return *iter;
}
} // namespace detail
@@ -131,17 +254,24 @@ namespace boost
//
template <
class Derived
, class Traits
, class Value = not_specified
, class Category = not_specified
, class Reference = not_specified
, class Pointer = not_specified
, class Difference = not_specified
>
class iterator_facade
: public detail::std_iterator_from_traits<Traits>
: public detail::iterator_facade_base<Value, Category, Reference, Pointer, Difference>::type
{
typedef detail::std_iterator_from_traits<Traits> super_t;
private:
typedef iterator_facade<Derived, Value, Category, Reference, Pointer, Difference> self_t;
typedef typename
detail::iterator_facade_base<Value, Category, Reference, Pointer, Difference>::type
super_t;
public:
//
// CRT interface. There is no simple way to remove this
// from the public interface without template friends
// CRT interface.
//
typedef Derived derived_t;
@@ -155,10 +285,13 @@ namespace boost
return static_cast<Derived const&>(*this);
}
public:
typedef typename super_t::value_type value_type;
typedef typename super_t::reference reference;
typedef typename super_t::difference_type difference_type;
typedef typename super_t::pointer pointer;
typedef typename super_t::iterator_category iterator_category;
reference operator*() const
{
@@ -166,14 +299,32 @@ namespace boost
}
// Needs eventual help for input iterators
pointer operator->() const
typename detail::operator_arrow_result<
value_type
, iterator_category
, reference
, pointer
>::type
operator->() const
{
return &iterator_core_access::dereference(this->derived());
typedef typename detail::operator_arrow_result<
value_type
, iterator_category
, reference
, detail::operator_arrow_pointer<reference,pointer>
>::type result_t;
return result_t(*this->derived());
}
reference operator[](difference_type n) const
typename detail::index_operator_result<Derived,value_type,iterator_category,reference>::type
operator[](difference_type n) const
{
return *(*this + n);
typedef typename
detail::index_operator_result<Derived,value_type,iterator_category,reference>::use_proxy
use_proxy;
return detail::make_index_operator_result<Derived>(this->derived() + n, use_proxy());
}
Derived& operator++()
@@ -289,13 +440,16 @@ namespace boost
//
# define BOOST_ITERATOR_FACADE_INTEROP(op, result_type, condition, return_prefix, base_op) \
template <class Derived1, class Traits1, class Derived2, class Traits2> \
template < \
class Derived1, class V1, class C1, class R1, class P1, class D1 \
, class Derived2, class V2, class C2, class R2, class P2, class D2 \
> \
inline typename detail::enable_if_interoperable< \
Derived1, Derived2, result_type \
>::type \
operator op( \
iterator_facade<Derived1, Traits1> const& lhs \
, iterator_facade<Derived2, Traits2> const& rhs) \
iterator_facade<Derived1, V1, C1, R1, P1, D1> const& lhs \
, iterator_facade<Derived2, V2, C2, R2, P2, D2> const& rhs) \
{ \
/* For those compilers that do not support enable_if */ \
BOOST_STATIC_ASSERT(( \
@@ -303,8 +457,8 @@ namespace boost
&& condition \
)); \
return_prefix iterator_core_access::base_op( \
rhs.derived(), lhs.derived()); \
}
static_cast<Derived2 const&>(rhs), static_cast<Derived1 const&>(lhs)); \
}
# define BOOST_ITERATOR_FACADE_RELATION(op, return_prefix, base_op) \
BOOST_ITERATOR_FACADE_INTEROP( \
@@ -327,31 +481,31 @@ namespace boost
// operator- requires an additional part in the static assertion
BOOST_ITERATOR_FACADE_INTEROP(
-
, typename Traits1::difference_type
, typename Derived1::difference_type
, (is_same<
BOOST_ARG_DEP_TYPENAME Traits1::difference_type
, BOOST_ARG_DEP_TYPENAME Traits2::difference_type
BOOST_ARG_DEP_TYPENAME Derived1::difference_type
, BOOST_ARG_DEP_TYPENAME Derived2::difference_type
>::value)
, return
, distance_to )
# undef BOOST_ITERATOR_FACADE_INTEROP
# define BOOST_ITERATOR_FACADE_PLUS(args) \
template <class Derived, class Traits> \
inline Derived operator+ args \
{ \
Derived tmp(i.derived()); \
return tmp += n; \
# define BOOST_ITERATOR_FACADE_PLUS(args) \
template <class Derived, class V, class C, class R, class P, class D> \
inline Derived operator+ args \
{ \
Derived tmp(static_cast<Derived const&>(i)); \
return tmp += n; \
}
BOOST_ITERATOR_FACADE_PLUS((
iterator_facade<Derived, Traits> const& i
, typename Traits::difference_type n
iterator_facade<Derived, V, C, R, P, D> const& i
, typename Derived::difference_type n
))
BOOST_ITERATOR_FACADE_PLUS((
typename Traits::difference_type n
, iterator_facade<Derived, Traits> const& i
typename Derived::difference_type n
, iterator_facade<Derived, V, C, R, P, D> const& i
))
# undef BOOST_ITERATOR_FACADE_PLUS

View File

@@ -0,0 +1,93 @@
// Copyright David Abrahams 2003. Permission to copy, use,
// modify, 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 ITERATOR_TRAITS_DWA200347_HPP
# define ITERATOR_TRAITS_DWA200347_HPP
# include <boost/detail/iterator.hpp>
# include <boost/detail/workaround.hpp>
namespace boost {
// Unfortunately, g++ 2.95.x chokes when we define a class template
// iterator_category which has the same name as its
// std::iterator_category() function, probably due in part to the
// "std:: is visible globally" hack it uses. Use
// BOOST_ITERATOR_CATEGORY to write code that's portable to older
// GCCs.
# if BOOST_WORKAROUND(__GNUC__, <= 2)
# define BOOST_ITERATOR_CATEGORY iterator_category_
# else
# define BOOST_ITERATOR_CATEGORY iterator_category
# endif
template <class Iterator>
struct iterator_value
{
typedef typename detail::iterator_traits<Iterator>::value_type type;
};
template <class Iterator>
struct iterator_reference
{
typedef typename detail::iterator_traits<Iterator>::reference type;
};
template <class Iterator>
struct iterator_pointer
{
typedef typename detail::iterator_traits<Iterator>::pointer type;
};
template <class Iterator>
struct iterator_difference
{
typedef typename detail::iterator_traits<Iterator>::difference_type type;
};
template <class Iterator>
struct BOOST_ITERATOR_CATEGORY
{
typedef typename detail::iterator_traits<Iterator>::iterator_category type;
};
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
template <>
struct iterator_value<int>
{
typedef void type;
};
template <>
struct iterator_reference<int>
{
typedef void type;
};
template <>
struct iterator_pointer<int>
{
typedef void type;
};
template <>
struct iterator_difference<int>
{
typedef void type;
};
template <>
struct BOOST_ITERATOR_CATEGORY<int>
{
typedef void type;
};
# endif
} // namespace boost::iterator
#endif // ITERATOR_TRAITS_DWA200347_HPP

View File

@@ -30,8 +30,8 @@ namespace boost {
void is_readable(readable_iterator_tag) { }
void is_writable(writable_iterator_tag) { }
void is_swappable(swappable_iterator_tag) { }
void is_constant_lvalue(constant_lvalue_iterator_tag) { }
void is_mutable_lvalue(mutable_lvalue_iterator_tag) { }
void is_constant_lvalue(readable_lvalue_iterator_tag) { }
void is_mutable_lvalue(writable_lvalue_iterator_tag) { }
// Preconditions: *i == v
template <class Iterator, class T>
@@ -45,7 +45,7 @@ void readable_iterator_test(const Iterator i1, T v)
T v2 = r2;
assert(v1 == v);
assert(v2 == v);
typename return_category<Iterator>::type result_category;
typename access_category<Iterator>::type result_category;
is_readable(result_category);
}
@@ -54,7 +54,7 @@ void writable_iterator_test(Iterator i, T v)
{
Iterator i2(i); // Copy Constructible
*i2 = v;
is_writable(typename return_category<Iterator>::type());
is_writable(typename access_category<Iterator>::type());
}
template <class Iterator>
@@ -65,7 +65,7 @@ void swappable_iterator_test(Iterator i, Iterator j)
iter_swap(i2, j2);
typename detail::iterator_traits<Iterator>::value_type ai = *i, aj = *j;
assert(bi == aj && bj == ai);
typedef typename return_category<Iterator>::type result_category;
typedef typename access_category<Iterator>::type result_category;
is_swappable(result_category());
}
@@ -78,7 +78,7 @@ void constant_lvalue_iterator_test(Iterator i, T v1)
BOOST_STATIC_ASSERT((is_same<const value_type&, reference>::value));
const T& v2 = *i2;
assert(v1 == v2);
typedef typename return_category<Iterator>::type result_category;
typedef typename access_category<Iterator>::type result_category;
is_constant_lvalue(result_category());
}
@@ -94,7 +94,7 @@ void mutable_lvalue_iterator_test(Iterator i, T v1, T v2)
*i = v2;
T& v4 = *i2;
assert(v2 == v4);
typedef typename return_category<Iterator>::type result_category;
typedef typename access_category<Iterator>::type result_category;
is_mutable_lvalue(result_category());
}

View File

@@ -15,43 +15,36 @@
namespace boost
{
template <class AdaptableUnaryFunction, class Iterator>
class transform_iterator;
namespace detail
{
// Given the transform iterator's transformation and iterator, this
// is the type used as its traits.
template <class AdaptableUnaryFunction, class Iterator>
struct transform_iterator_traits
: iterator_traits_adaptor<
Iterator
struct transform_iterator_base
{
typedef iterator_adaptor<
transform_iterator<AdaptableUnaryFunction, Iterator>
, Iterator
, typename AdaptableUnaryFunction::result_type
, typename AdaptableUnaryFunction::result_type
, typename AdaptableUnaryFunction::result_type*
, iterator_tag<
readable_iterator_tag
, typename traversal_category<Iterator>::type
>
>
{
, typename AdaptableUnaryFunction::result_type
> type;
};
}
} // transform_iterator_traits
//
template <class AdaptableUnaryFunction, class Iterator>
class transform_iterator
: public iterator_adaptor<
transform_iterator<AdaptableUnaryFunction, Iterator>
, Iterator
, detail::transform_iterator_traits<AdaptableUnaryFunction,Iterator>
>
: public detail::transform_iterator_base<AdaptableUnaryFunction, Iterator>::type
{
typedef iterator_adaptor<
transform_iterator<AdaptableUnaryFunction, Iterator>
, Iterator
, detail::transform_iterator_traits<AdaptableUnaryFunction,Iterator>
> super_t;
typedef typename
detail::transform_iterator_base<AdaptableUnaryFunction, Iterator>::type
super_t;
friend class iterator_core_access;

View File

@@ -2,6 +2,7 @@ SEARCH on testing.jam = $(BOOST_BUILD_PATH) ;
include testing.jam ;
run concept_tests.cpp ;
run iterator_adaptor_cc.cpp ;
run counting_iterator_test.cpp ;
run transform_iterator_test.cpp ;
run indirect_iterator_test.cpp ;
run filter_iterator_test.cpp ;

View File

@@ -10,7 +10,7 @@
struct new_iterator
: public boost::iterator< boost::iterator_tag<
boost::mutable_lvalue_iterator_tag
boost::writable_lvalue_iterator_tag
, boost::random_access_traversal_tag>, int>
{
int& operator*() const { return *m_x; }
@@ -53,16 +53,14 @@ old_iterator operator+(std::ptrdiff_t, old_iterator x) { return x; }
int
main()
{
BOOST_STATIC_ASSERT( boost::detail::is_random_access_traversal_iterator<boost::random_access_traversal_tag>::value );
typedef boost::iterator_tag< boost::mutable_lvalue_iterator_tag, boost::random_access_traversal_tag > tag;
typedef boost::iterator_tag< boost::writable_lvalue_iterator_tag, boost::random_access_traversal_tag > tag;
// BOOST_STATIC_ASSERT((boost::detail::is_random_access_iterator<tag>::value));
BOOST_STATIC_ASSERT((boost::is_same<tag::returns, boost::mutable_lvalue_iterator_tag>::value));
BOOST_STATIC_ASSERT((boost::is_same<tag::returns, boost::writable_lvalue_iterator_tag>::value));
BOOST_STATIC_ASSERT((boost::is_same<tag::traversal, boost::random_access_traversal_tag>::value));
// BOOST_STATIC_ASSERT((boost::detail::is_random_access_iterator<new_iterator::iterator_category>::value));
BOOST_STATIC_ASSERT((boost::is_same<new_iterator::iterator_category::returns, boost::mutable_lvalue_iterator_tag>::value));
BOOST_STATIC_ASSERT((boost::is_same<new_iterator::iterator_category::returns, boost::writable_lvalue_iterator_tag>::value));
BOOST_STATIC_ASSERT((boost::is_same<new_iterator::iterator_category::traversal, boost::random_access_traversal_tag>::value));
typedef boost::traversal_category<new_iterator>::type traversal_category;

295
test/counting_iterator_test.cpp Executable file
View File

@@ -0,0 +1,295 @@
// (C) Copyright David Abrahams 2001. Permission to copy, use, modify, 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.
//
// See http://www.boost.org for most recent version including documentation.
//
// Revision History
// 16 Feb 2001 Added a missing const. Made the tests run (somewhat) with
// plain MSVC again. (David Abrahams)
// 11 Feb 2001 #if 0'd out use of counting_iterator on non-numeric types in
// MSVC without STLport, so that the other tests may proceed
// (David Abrahams)
// 04 Feb 2001 Added use of iterator_tests.hpp (David Abrahams)
// 28 Jan 2001 Removed not_an_iterator detritus (David Abrahams)
// 24 Jan 2001 Initial revision (David Abrahams)
#include <boost/config.hpp>
#ifdef __BORLANDC__ // Borland mis-detects our custom iterators
# pragma warn -8091 // template argument ForwardIterator passed to '...' is a output iterator
# pragma warn -8071 // Conversion may lose significant digits (due to counting_iterator<char> += n).
#endif
#ifdef BOOST_MSVC
# pragma warning(disable:4786) // identifier truncated in debug info
#endif
#include <boost/detail/iterator.hpp>
#include <boost/iterator/counting_iterator.hpp>
#include <boost/iterator/new_iterator_tests.hpp>
#include <boost/next_prior.hpp>
#include <boost/mpl/if.hpp>
#include <boost/detail/iterator.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/limits.hpp>
#include <algorithm>
#include <climits>
#include <iterator>
#include <stdlib.h>
#ifndef __BORLANDC__
# include <boost/tuple/tuple.hpp>
#endif
#include <vector>
#include <list>
#include <cassert>
#ifndef BOOST_NO_SLIST
# include <slist>
#endif
#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
template <class T>
struct signed_assert_nonnegative
{
static void test(T x) { assert(x >= 0); }
};
template <class T>
struct unsigned_assert_nonnegative
{
static void test(T x) {}
};
template <class T>
struct assert_nonnegative
: boost::mpl::if_c<
std::numeric_limits<T>::is_signed
, signed_assert_nonnegative<T>
, unsigned_assert_nonnegative<T>
>::type
{
};
#endif
// Special tests for RandomAccess CountingIterators.
template <class CountingIterator, class Value>
void category_test(
CountingIterator start,
CountingIterator finish,
Value,
std::random_access_iterator_tag)
{
typedef typename
boost::detail::iterator_traits<CountingIterator>::difference_type
difference_type;
difference_type distance = boost::detail::distance(start, finish);
// Pick a random position internal to the range
difference_type offset = (unsigned)rand() % distance;
#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
assert(offset >= 0);
#else
assert_nonnegative<difference_type>::test(offset);
#endif
CountingIterator internal = start;
std::advance(internal, offset);
// Try some binary searches on the range to show that it's ordered
assert(std::binary_search(start, finish, *internal));
// #including tuple crashed borland, so I had to give up on tie().
std::pair<CountingIterator,CountingIterator> xy(
std::equal_range(start, finish, *internal));
CountingIterator x = xy.first, y = xy.second;
assert(boost::detail::distance(x, y) == 1);
// Show that values outside the range can't be found
assert(!std::binary_search(start, boost::prior(finish), *finish));
// Do the generic random_access_iterator_test
typedef typename CountingIterator::value_type value_type;
std::vector<value_type> v;
for (value_type z = *start; !(z == *finish); ++z)
v.push_back(z);
// Note that this test requires a that the first argument is
// dereferenceable /and/ a valid iterator prior to the first argument
boost::random_access_iterator_test(start, v.size(), v.begin());
}
// Special tests for bidirectional CountingIterators
template <class CountingIterator, class Value>
void category_test(CountingIterator start, Value v1, std::bidirectional_iterator_tag)
{
Value v2 = v1;
++v2;
// Note that this test requires a that the first argument is
// dereferenceable /and/ a valid iterator prior to the first argument
boost::bidirectional_iterator_test(start, v1, v2);
}
template <class CountingIterator, class Value>
void category_test(CountingIterator start, CountingIterator finish, Value v1, std::forward_iterator_tag)
{
Value v2 = v1;
++v2;
if (finish != start && finish != boost::next(start))
boost::forward_readable_iterator_test(start, finish, v1, v2);
}
template <class CountingIterator, class Value>
void test_aux(CountingIterator start, CountingIterator finish, Value v1)
{
typedef typename CountingIterator::iterator_category category;
typedef typename CountingIterator::value_type value_type;
// If it's a RandomAccessIterator we can do a few delicate tests
category_test(start, finish, v1, category());
// Okay, brute force...
for (CountingIterator p = start
; p != finish && boost::next(p) != finish
; ++p)
{
assert(boost::next(*p) == *boost::next(p));
}
// prove that a reference can be formed to these values
typedef typename CountingIterator::value_type value;
const value* q = &*start;
(void)q; // suppress unused variable warning
}
template <class Incrementable>
void test(Incrementable start, Incrementable finish)
{
test_aux(boost::make_counting_iterator(start), boost::make_counting_iterator(finish), start);
}
template <class Integer>
void test_integer(Integer* = 0) // default arg works around MSVC bug
{
Integer start = 0;
Integer finish = 120;
test(start, finish);
}
template <class Integer, class Category, class Difference>
void test_integer3(Integer* = 0, Category* = 0, Difference* = 0) // default arg works around MSVC bug
{
Integer start = 0;
Integer finish = 120;
typedef boost::counting_iterator<Integer,Category,Difference> iterator;
test_aux(iterator(start), iterator(finish), start);
}
template <class Container>
void test_container(Container* = 0) // default arg works around MSVC bug
{
Container c(1 + (unsigned)rand() % 1673);
const typename Container::iterator start = c.begin();
// back off by 1 to leave room for dereferenceable value at the end
typename Container::iterator finish = start;
std::advance(finish, c.size() - 1);
test(start, finish);
typedef typename Container::const_iterator const_iterator;
test(const_iterator(start), const_iterator(finish));
}
class my_int1 {
public:
my_int1() { }
my_int1(int x) : m_int(x) { }
my_int1& operator++() { ++m_int; return *this; }
bool operator==(const my_int1& x) const { return m_int == x.m_int; }
private:
int m_int;
};
class my_int2 {
public:
typedef void value_type;
typedef void pointer;
typedef void reference;
typedef std::ptrdiff_t difference_type;
typedef std::bidirectional_iterator_tag iterator_category;
my_int2() { }
my_int2(int x) : m_int(x) { }
my_int2& operator++() { ++m_int; return *this; }
my_int2& operator--() { --m_int; return *this; }
bool operator==(const my_int2& x) const { return m_int == x.m_int; }
private:
int m_int;
};
class my_int3 {
public:
typedef void value_type;
typedef void pointer;
typedef void reference;
typedef std::ptrdiff_t difference_type;
typedef std::random_access_iterator_tag iterator_category;
my_int3() { }
my_int3(int x) : m_int(x) { }
my_int3& operator++() { ++m_int; return *this; }
my_int3& operator+=(std::ptrdiff_t n) { m_int += n; return *this; }
std::ptrdiff_t operator-(const my_int3& x) const { return m_int - x.m_int; }
my_int3& operator--() { --m_int; return *this; }
bool operator==(const my_int3& x) const { return m_int == x.m_int; }
bool operator!=(const my_int3& x) const { return m_int != x.m_int; }
bool operator<(const my_int3& x) const { return m_int < x.m_int; }
private:
int m_int;
};
int main()
{
// Test the built-in integer types.
test_integer<char>();
test_integer<unsigned char>();
test_integer<signed char>();
test_integer<wchar_t>();
test_integer<short>();
test_integer<unsigned short>();
test_integer<int>();
test_integer<unsigned int>();
test_integer<long>();
test_integer<unsigned long>();
#if defined(BOOST_HAS_LONG_LONG)
test_integer<long long>();
test_integer<unsigned long long>();
#endif
// Test user-defined type.
test_integer3<my_int1, std::forward_iterator_tag, int>();
test_integer<my_int2>();
test_integer<my_int3>();
// Some tests on container iterators, to prove we handle a few different categories
test_container<std::vector<int> >();
test_container<std::list<int> >();
# ifndef BOOST_NO_SLIST
test_container<BOOST_STD_EXTENSION_NAMESPACE::slist<int> >();
# endif
// Also prove that we can handle raw pointers.
int array[2000];
test(boost::make_counting_iterator(array), boost::make_counting_iterator(array+2000-1));
return 0;
}

View File

@@ -13,10 +13,12 @@
using boost::dummyT;
struct one_or_four {
bool operator()(dummyT x) const {
return x.foo() == 1 || x.foo() == 4;
}
struct one_or_four
{
bool operator()(dummyT x) const
{
return x.foo() == 1 || x.foo() == 4;
}
};
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
@@ -27,6 +29,7 @@ namespace boost { namespace detail
}}
#endif
template <class T> struct undefined;
// Test filter iterator
int main()
@@ -41,11 +44,15 @@ int main()
filter_iter(one_or_four(), array, array+N)
, dummyT(1), dummyT(4));
//# if 0
BOOST_STATIC_ASSERT(
(!boost::detail::is_bidirectional_traversal_iterator<
boost::traversal_category<filter_iter>::type
>::value) );
// Filter iterators can't be bidirectional, since we didn't choose
// to store the beginning of the range.
BOOST_STATIC_ASSERT((
!boost::detail::is_tag<
boost::bidirectional_traversal_tag
, boost::traversal_category<filter_iter>::type
>::value
));
//# endif
// On compilers not supporting partial specialization, we can do more type

View File

@@ -67,16 +67,6 @@ typedef RA_CONTAINER<int> storage;
typedef RA_CONTAINER<int*> pointer_ra_container;
typedef std::set<storage::iterator> iterator_set;
// Something has to be done about putting this in the lib
template <class Iter>
struct indirect_const_iterator_traits
: boost::detail::indirect_defaults<Iter>
{
typedef boost::detail::indirect_defaults<Iter> base;
typedef typename base::value_type const& reference;
typedef typename base::value_type const* pointer;
};
template <class Container>
struct indirect_iterator_pair_generator
{
@@ -84,7 +74,7 @@ struct indirect_iterator_pair_generator
typedef boost::indirect_iterator<
typename Container::iterator
, indirect_const_iterator_traits<typename Container::const_iterator>
, typename iterator::value_type const
> const_iterator;
};
@@ -114,8 +104,10 @@ namespace boost { namespace detail
}}
#endif
void more_indirect_iterator_tests()
{
# if 0
storage store(1000);
std::generate(store.begin(), store.end(), rand);
@@ -163,8 +155,8 @@ void more_indirect_iterator_tests()
typedef boost::indirect_iterator<iterator_set::iterator> indirect_set_iterator;
typedef boost::indirect_iterator<
iterator_set::iterator
, indirect_const_iterator_traits<iterator_set::const_iterator>
> const_indirect_set_iterator;
, iterator_set::iterator::value_type const
> const_indirect_set_iterator;
indirect_set_iterator sb(iter_set.begin());
indirect_set_iterator se(iter_set.end());
@@ -185,6 +177,7 @@ void more_indirect_iterator_tests()
boost::bidirectional_iterator_test(boost::next(sb), store[1], store[2]);
assert(std::equal(db, de, store.begin()));
#endif
}
int
@@ -210,8 +203,8 @@ main()
typedef boost::indirect_iterator<
shared_t::iterator
, indirect_const_iterator_traits<shared_t::const_iterator>
> c_iter_t;
, boost::iterator_value<shared_t::iterator>::type const
> c_iter_t;
# ifndef NO_MUTABLE_CONST_RA_ITERATOR_INTEROPERABILITY
boost::function_requires< boost_concepts::InteroperableConcept<iter_t, c_iter_t> >();
@@ -229,7 +222,7 @@ main()
typedef boost::indirect_iterator<dummyT**> indirect_iterator;
typedef boost::indirect_iterator<dummyT**, indirect_const_iterator_traits<dummyT* const*> >
typedef boost::indirect_iterator<dummyT**, dummyT const>
const_indirect_iterator;
indirect_iterator i(ptr);

View File

@@ -1,3 +1,8 @@
// Copyright Thomas Witt 2003. Permission to copy, use,
// modify, 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.
#include <boost/iterator/indirect_iterator.hpp>
#include <boost/iterator/reverse_iterator.hpp>
#include <boost/concept_check.hpp>

View File

@@ -1,6 +1,4 @@
// Test boost/iterator_adaptors.hpp
// (C) Copyright Jeremy Siek 2002. Permission to copy, use, modify,
// (C) Copyright Thomas Witt 2003. Permission to copy, use, modify,
// 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
@@ -8,44 +6,6 @@
// See http://www.boost.org for most recent version including documentation.
// Revision History
// 30 Nov 01 Added permutation_iterator.(Toon Knapen)
// 19 Nov 01 Added generator_iterator. (Jens Maurer)
// 04 Nov 01 Updated with respect to change in named parameters.
// (Jeremy Siek)
// 08 Mar 01 Moved indirect and transform tests to separate files.
// (Jeremy Siek)
// 19 Feb 01 Take adavantage of improved iterator_traits to do more tests
// on MSVC. Hack around an MSVC-with-STLport internal compiler
// error. (David Abrahams)
// 11 Feb 01 Added test of operator-> for forward and input iterators.
// (Jeremy Siek)
// 11 Feb 01 Borland fixes (David Abrahams)
// 10 Feb 01 Use new adaptors interface. (David Abrahams)
// 10 Feb 01 Use new filter_ interface. (David Abrahams)
// 09 Feb 01 Use new reverse_ and indirect_ interfaces. Replace
// BOOST_NO_STD_ITERATOR_TRAITS with
// BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION to prove we've
// normalized to core compiler capabilities (David Abrahams)
// 08 Feb 01 Use Jeremy's new make_reverse_iterator form; add more
// comprehensive testing. Force-decay array function arguments to
// pointers.
// 07 Feb 01 Added tests for the make_xxx_iterator() helper functions.
// (Jeremy Siek)
// 07 Feb 01 Replaced use of xxx_pair_generator with xxx_generator where
// possible (which was all but the projection iterator).
// (Jeremy Siek)
// 06 Feb 01 Removed now-defaulted template arguments where possible
// Updated names to correspond to new generator naming convention.
// Added a trivial test for make_transform_iterator().
// Gave traits for const iterators a mutable value_type, per std.
// Resurrected my original tests for indirect iterators.
// (David Abrahams)
// 04 Feb 01 Fix for compilers without standard iterator_traits
// (David Abrahams)
// 13 Jun 00 Added const version of the iterator tests (Jeremy Siek)
// 12 Dec 99 Initial version with iterator operators (Jeremy Siek)
#include <boost/config.hpp>
#include <iostream>
@@ -125,23 +85,24 @@ struct my_gen
template <class V>
struct ptr_iterator
: boost::iterator_adaptor<ptr_iterator<V>
, V, V&, V*
, boost::iterator_tag<boost::mutable_lvalue_iterator_tag
,boost::random_access_traversal_tag>
, std::ptrdiff_t>
: boost::iterator_adaptor<
ptr_iterator<V>,
boost::iterator_traits_adaptor<V*,
V,
boost::iterator_tag< boost::writable_lvalue_iterator_tag
,boost::random_access_traversal_tag > >
>
{
private:
typedef iterator_adaptor super_t;
public:
ptr_iterator() { }
ptr_iterator(V* d) : m_base(d) { }
ptr_iterator(V* d) : super_t(d) { }
template <class V2>
ptr_iterator(const ptr_iterator<V2>& x) // should assert is_same add_cv<V> add_cv<V2>
: m_base(x.base()) { }
: super_t(x.base()) { }
V*& base() { return m_base; }
V* const& base() const { return m_base; }
private:
V* m_base;
};
int
@@ -164,9 +125,7 @@ main()
boost::const_nonconst_iterator_test(i, ++j);
}
#if 0
// Test the named parameters
// Test the iterator_traits
{
// Test computation of defaults
typedef boost::iterator_adaptor<int*, boost::default_iterator_policies,
@@ -218,175 +177,6 @@ main()
boost::const_nonconst_iterator_test(i, ++j);
}
// Test projection_iterator_pair_generator
{
typedef std::pair<dummyT,dummyT> Pair;
Pair pair_array[N];
for (int k = 0; k < N; ++k)
pair_array[k].first = array[k];
typedef boost::projection_iterator_pair_generator<select1st_<Pair>,
Pair*, const Pair*
> Projection;
Projection::iterator i(pair_array);
boost::random_access_iterator_test(i, N, array);
boost::random_access_iterator_test(boost::make_projection_iterator(pair_array, select1st_<Pair>()), N, array);
boost::random_access_iterator_test(boost::make_projection_iterator< select1st_<Pair> >(pair_array), N, array);
Projection::const_iterator j(pair_array);
boost::random_access_iterator_test(j, N, array);
boost::random_access_iterator_test(boost::make_const_projection_iterator(pair_array, select1st_<Pair>()), N, array);
boost::random_access_iterator_test(boost::make_const_projection_iterator<select1st_<Pair> >(pair_array), N, array);
boost::const_nonconst_iterator_test(i, ++j);
}
// Test reverse_iterator_generator
{
dummyT reversed[N];
std::copy(array, array + N, reversed);
std::reverse(reversed, reversed + N);
typedef boost::reverse_iterator_generator<dummyT*
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) || defined(BOOST_NO_STD_ITERATOR_TRAITS)
, dummyT
#endif
>::type reverse_iterator;
reverse_iterator i(reversed + N);
boost::random_access_iterator_test(i, N, array);
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
boost::random_access_iterator_test(boost::make_reverse_iterator(reversed + N), N, array);
#endif
typedef boost::reverse_iterator_generator<const dummyT*
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) || defined(BOOST_NO_STD_ITERATOR_TRAITS)
, dummyT, const dummyT&, const dummyT
#endif
>::type const_reverse_iterator;
const_reverse_iterator j(reversed + N);
boost::random_access_iterator_test(j, N, array);
const dummyT* const_reversed = reversed;
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
boost::random_access_iterator_test(boost::make_reverse_iterator(const_reversed + N), N, array);
#endif
boost::const_nonconst_iterator_test(i, ++j);
}
// Test reverse_iterator_generator again, with traits fully deducible on all platforms
{
std::deque<dummyT> reversed_container;
std::reverse_copy(array, array + N, std::back_inserter(reversed_container));
const std::deque<dummyT>::iterator reversed = reversed_container.begin();
typedef boost::reverse_iterator_generator<
std::deque<dummyT>::iterator>::type reverse_iterator;
typedef boost::reverse_iterator_generator<
std::deque<dummyT>::const_iterator, const dummyT>::type const_reverse_iterator;
// MSVC/STLport gives an INTERNAL COMPILER ERROR when any computation
// (e.g. "reversed + N") is used in the constructor below.
const std::deque<dummyT>::iterator finish = reversed_container.end();
reverse_iterator i(finish);
boost::random_access_iterator_test(i, N, array);
boost::random_access_iterator_test(boost::make_reverse_iterator(reversed + N), N, array);
const_reverse_iterator j = reverse_iterator(finish);
boost::random_access_iterator_test(j, N, array);
const std::deque<dummyT>::const_iterator const_reversed = reversed;
boost::random_access_iterator_test(boost::make_reverse_iterator(const_reversed + N), N, array);
// Many compilers' builtin deque iterators don't interoperate well, though
// STLport fixes that problem.
#if defined(__SGI_STL_PORT) || !defined(__GNUC__) && !defined(__BORLANDC__) && (!defined(BOOST_MSVC) || BOOST_MSVC > 1200)
boost::const_nonconst_iterator_test(i, ++j);
#endif
}
// Test integer_range's iterators
{
int int_array[] = { 0, 1, 2, 3, 4, 5 };
boost::integer_range<int> r(0, 5);
boost::random_access_iterator_test(r.begin(), r.size(), int_array);
}
// Test filter iterator
{
// Using typedefs for filter_gen::type confused Borland terribly.
typedef boost::detail::non_bidirectional_category<dummyT*>::type category;
typedef boost::filter_iterator_generator<one_or_four, dummyT*
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) || defined(BOOST_NO_STD_ITERATOR_TRAITS)
, dummyT
#endif
>::type filter_iter;
#if defined(__BORLANDC__)
// Borland is choking on accessing the policies_type explicitly
// from the filter_iter.
boost::forward_iterator_test(make_filter_iterator(array, array+N,
one_or_four()),
dummyT(1), dummyT(4));
#else
filter_iter i(array, filter_iter::policies_type(one_or_four(), array + N));
boost::forward_iterator_test(i, dummyT(1), dummyT(4));
#endif
#if !defined(__BORLANDC__)
//
enum { is_forward = boost::is_same<
filter_iter::iterator_category,
std::forward_iterator_tag>::value };
BOOST_STATIC_ASSERT(is_forward);
#endif
// On compilers not supporting partial specialization, we can do more type
// deduction with deque iterators than with pointers... unless the library
// is broken ;-(
#if !defined(BOOST_MSVC) || BOOST_MSVC > 1200 || defined(__SGI_STL_PORT)
std::deque<dummyT> array2;
std::copy(array+0, array+N, std::back_inserter(array2));
boost::forward_iterator_test(
boost::make_filter_iterator(array2.begin(), array2.end(), one_or_four()),
dummyT(1), dummyT(4));
boost::forward_iterator_test(
boost::make_filter_iterator<one_or_four>(array2.begin(), array2.end()),
dummyT(1), dummyT(4));
#endif
#if !defined(BOOST_MSVC) || BOOST_MSVC > 1200 // This just freaks MSVC out completely
boost::forward_iterator_test(
boost::make_filter_iterator<one_or_four>(
boost::make_reverse_iterator(array2.end()),
boost::make_reverse_iterator(array2.begin())
),
dummyT(4), dummyT(1));
#endif
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
boost::forward_iterator_test(
boost::make_filter_iterator(array+0, array+N, one_or_four()),
dummyT(1), dummyT(4));
boost::forward_iterator_test(
boost::make_filter_iterator<one_or_four>(array, array + N),
dummyT(1), dummyT(4));
#endif
}
// check operator-> with a forward iterator
{
boost::forward_iterator_archetype<dummyT> forward_iter;
@@ -423,54 +213,6 @@ main()
assert((*i).m_x == i->foo());
}
{
// check generator_iterator
my_gen g1;
boost::generator_iterator_generator<my_gen>::type gen =
boost::make_generator_iterator(g1);
assert(*gen == 1);
++gen;
gen++;
assert(*gen == 3);
}
{
// check permutation_iterator
typedef std::deque< int > element_range_type;
typedef std::list< int > index_type;
static const int element_range_size = 10;
static const int index_size = 4;
element_range_type elements( element_range_size );
for(element_range_type::iterator el_it = elements.begin();
el_it != elements.end();
++el_it)
{
*el_it = std::distance( elements.begin(), el_it );
}
index_type indices( index_size );
for(index_type::iterator i_it = indices.begin();
i_it != indices.end();
++i_it)
{
*i_it = element_range_size - index_size
+ std::distance(indices.begin(), i_it );
}
std::reverse( indices.begin(), indices.end() );
typedef boost::permutation_iterator_generator< element_range_type::iterator, index_type::iterator >::type permutation_type;
permutation_type begin = boost::make_permutation_iterator( elements.begin(), indices.begin() );
permutation_type end = boost::make_permutation_iterator( elements.begin(), indices.end() );
int expected_outcome[] = { 9, 8, 7, 6 };
assert( std::equal( begin, end, expected_outcome ) );
}
#endif
std::cout << "test successful " << std::endl;
return 0;
}

87
test/reverse_iterator_test.cpp Executable file
View File

@@ -0,0 +1,87 @@
// Copyright Thomas Witt 2003. Permission to copy, use,
// modify, 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.
#include <boost/iterator/reverse_iterator.hpp>
#include <boost/iterator/new_iterator_tests.hpp>
// Test reverse iterator
int main()
{
#if 0
// Test reverse_iterator_generator
{
dummyT reversed[N];
std::copy(array, array + N, reversed);
std::reverse(reversed, reversed + N);
typedef boost::reverse_iterator_generator<dummyT*
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) || defined(BOOST_NO_STD_ITERATOR_TRAITS)
, dummyT
#endif
>::type reverse_iterator;
reverse_iterator i(reversed + N);
boost::random_access_iterator_test(i, N, array);
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
boost::random_access_iterator_test(boost::make_reverse_iterator(reversed + N), N, array);
#endif
typedef boost::reverse_iterator_generator<const dummyT*
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) || defined(BOOST_NO_STD_ITERATOR_TRAITS)
, dummyT, const dummyT&, const dummyT
#endif
>::type const_reverse_iterator;
const_reverse_iterator j(reversed + N);
boost::random_access_iterator_test(j, N, array);
const dummyT* const_reversed = reversed;
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
boost::random_access_iterator_test(boost::make_reverse_iterator(const_reversed + N), N, array);
#endif
boost::const_nonconst_iterator_test(i, ++j);
}
// Test reverse_iterator_generator again, with traits fully deducible on all platforms
{
std::deque<dummyT> reversed_container;
std::reverse_copy(array, array + N, std::back_inserter(reversed_container));
const std::deque<dummyT>::iterator reversed = reversed_container.begin();
typedef boost::reverse_iterator_generator<
std::deque<dummyT>::iterator>::type reverse_iterator;
typedef boost::reverse_iterator_generator<
std::deque<dummyT>::const_iterator, const dummyT>::type const_reverse_iterator;
// MSVC/STLport gives an INTERNAL COMPILER ERROR when any computation
// (e.g. "reversed + N") is used in the constructor below.
const std::deque<dummyT>::iterator finish = reversed_container.end();
reverse_iterator i(finish);
boost::random_access_iterator_test(i, N, array);
boost::random_access_iterator_test(boost::make_reverse_iterator(reversed + N), N, array);
const_reverse_iterator j = reverse_iterator(finish);
boost::random_access_iterator_test(j, N, array);
const std::deque<dummyT>::const_iterator const_reversed = reversed;
boost::random_access_iterator_test(boost::make_reverse_iterator(const_reversed + N), N, array);
// Many compilers' builtin deque iterators don't interoperate well, though
// STLport fixes that problem.
#if defined(__SGI_STL_PORT) || !defined(__GNUC__) && !defined(__BORLANDC__) && (!defined(BOOST_MSVC) || BOOST_MSVC > 1200)
boost::const_nonconst_iterator_test(i, ++j);
#endif
}
#endif
}