forked from boostorg/iterator
Many changes from Oxford
[SVN r1137]
This commit is contained in:
194
include/boost/iterator/counting_iterator.hpp
Executable file
194
include/boost/iterator/counting_iterator.hpp
Executable 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
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
};
|
||||
|
@@ -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>
|
||||
|
@@ -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
|
||||
|
||||
|
93
include/boost/iterator/iterator_traits.hpp
Executable file
93
include/boost/iterator/iterator_traits.hpp
Executable 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
|
@@ -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());
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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 ;
|
||||
|
@@ -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
295
test/counting_iterator_test.cpp
Executable 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;
|
||||
}
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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>
|
||||
|
@@ -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
87
test/reverse_iterator_test.cpp
Executable 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
|
||||
|
||||
|
||||
}
|
Reference in New Issue
Block a user