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_convertible.hpp>
|
||||||
#include <boost/type_traits/is_same.hpp>
|
#include <boost/type_traits/is_same.hpp>
|
||||||
#include <boost/mpl/if.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/bool.hpp>
|
||||||
#include <boost/mpl/or.hpp>
|
#include <boost/mpl/or.hpp>
|
||||||
|
#include <boost/mpl/and.hpp>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
|
||||||
#if BOOST_WORKAROUND(__MWERKS__, <=0x2407)
|
#if BOOST_WORKAROUND(__MWERKS__, <=0x2407)
|
||||||
# define BOOST_NO_IS_CONVERTIBLE // "Convertible does not provide enough/is not working"
|
# define BOOST_NO_IS_CONVERTIBLE // "Convertible does not provide enough/is not working"
|
||||||
#endif
|
#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
|
// Traversal Categories
|
||||||
struct input_traversal_tag { };
|
//
|
||||||
struct output_traversal_tag { };
|
struct incrementable_iterator_tag
|
||||||
struct forward_traversal_tag : virtual public input_traversal_tag,
|
{
|
||||||
virtual public output_traversal_tag { };
|
typedef std::output_iterator_tag max_category;
|
||||||
struct bidirectional_traversal_tag : virtual public forward_traversal_tag { };
|
};
|
||||||
struct random_access_traversal_tag : virtual public bidirectional_traversal_tag { };
|
|
||||||
|
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 { };
|
struct error_iterator_tag { };
|
||||||
|
|
||||||
@@ -57,384 +113,162 @@ namespace boost {
|
|||||||
//
|
//
|
||||||
// Tag detection meta functions
|
// 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.
|
// I bet this is defined somewhere else. Let's wait and see.
|
||||||
//
|
|
||||||
struct error_type;
|
struct error_type;
|
||||||
|
|
||||||
#ifdef BOOST_NO_IS_CONVERTIBLE
|
#ifndef 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
|
|
||||||
|
|
||||||
template <class Base, class Derived>
|
template <class Base, class Derived>
|
||||||
struct is_base_or_same :
|
struct is_same_or_derived
|
||||||
mpl::or_< is_same< Base, Derived >,
|
# ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||||
is_base_and_derived< Base, Derived > >
|
: 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
|
// Returns the minimum category type or error_type
|
||||||
// if T1 and T2 are unrelated.
|
// if T1 and T2 are unrelated.
|
||||||
@@ -446,19 +280,18 @@ namespace boost {
|
|||||||
//
|
//
|
||||||
//
|
//
|
||||||
template <class T1, class T2>
|
template <class T1, class T2>
|
||||||
struct minimum_category :
|
struct minimum_category
|
||||||
#ifndef BOOST_NO_IS_CONVERTIBLE
|
: mpl::apply_if<
|
||||||
mpl::if_< is_base_or_same< T1, T2 >,
|
is_tag<T1,T2>
|
||||||
T1,
|
, mpl::identity<T1>
|
||||||
mpl::if_< is_base_or_same< T2, T1 >,
|
, mpl::if_<
|
||||||
T2,
|
is_tag<T2, T1>
|
||||||
error_type > >
|
, T2
|
||||||
#else
|
, error_type
|
||||||
minimum_category_select< minimum_return_category<T1, T2>,
|
>
|
||||||
minimum_traversal_category<T1, T2> >
|
>
|
||||||
#endif
|
|
||||||
{};
|
{};
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
} // namespace boost
|
} // namespace boost
|
||||||
|
@@ -69,7 +69,7 @@ namespace boost
|
|||||||
class Return>
|
class Return>
|
||||||
struct enable_if
|
struct enable_if
|
||||||
# if !defined(BOOST_NO_SFINAE) && !defined(BOOST_NO_IS_CONVERTIBLE)
|
# if !defined(BOOST_NO_SFINAE) && !defined(BOOST_NO_IS_CONVERTIBLE)
|
||||||
: enabled<Cond::value>::template base<Return>
|
: enabled<(Cond::value)>::template base<Return>
|
||||||
# else
|
# else
|
||||||
: mpl::identity<Return>
|
: mpl::identity<Return>
|
||||||
# endif
|
# endif
|
||||||
|
@@ -15,20 +15,18 @@
|
|||||||
|
|
||||||
namespace boost
|
namespace boost
|
||||||
{
|
{
|
||||||
|
namespace detail
|
||||||
namespace detail {
|
{
|
||||||
|
|
||||||
template <class Iterator>
|
template <class Iterator>
|
||||||
struct filter_iterator_traits
|
struct filter_iterator_category
|
||||||
: iterator_traits<Iterator>
|
|
||||||
{
|
{
|
||||||
typedef iterator_tag<
|
typedef iterator_tag<
|
||||||
typename return_category<Iterator>::type
|
typename access_category<Iterator>::type
|
||||||
, typename minimum_category<
|
, typename minimum_category<
|
||||||
forward_traversal_tag
|
forward_traversal_tag
|
||||||
, typename traversal_category<Iterator>::type
|
, typename traversal_category<Iterator>::type
|
||||||
>::type
|
>::type
|
||||||
> iterator_category;
|
> type;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
@@ -37,13 +35,15 @@ namespace boost
|
|||||||
class filter_iterator
|
class filter_iterator
|
||||||
: public iterator_adaptor<
|
: public iterator_adaptor<
|
||||||
filter_iterator<Predicate, Iterator>, Iterator
|
filter_iterator<Predicate, Iterator>, Iterator
|
||||||
, detail::filter_iterator_traits<Iterator>
|
, not_specified
|
||||||
|
, typename detail::filter_iterator_category<Iterator>::type
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
typedef iterator_adaptor<
|
typedef iterator_adaptor<
|
||||||
filter_iterator<Predicate, Iterator>, Iterator
|
filter_iterator<Predicate, Iterator>, Iterator
|
||||||
, detail::filter_iterator_traits<Iterator>
|
, not_specified
|
||||||
> super_t;
|
, typename detail::filter_iterator_category<Iterator>::type
|
||||||
|
> super_t;
|
||||||
|
|
||||||
friend class iterator_core_access;
|
friend class iterator_core_access;
|
||||||
|
|
||||||
|
@@ -13,6 +13,10 @@
|
|||||||
#include <boost/iterator/iterator_adaptor.hpp>
|
#include <boost/iterator/iterator_adaptor.hpp>
|
||||||
|
|
||||||
#include <boost/iterator/detail/config_def.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
|
#ifdef BOOST_NO_MPL_AUX_HAS_XXX
|
||||||
# include <boost/shared_ptr.hpp>
|
# include <boost/shared_ptr.hpp>
|
||||||
@@ -23,6 +27,8 @@
|
|||||||
|
|
||||||
namespace boost
|
namespace boost
|
||||||
{
|
{
|
||||||
|
template <class Iter, class Value, class Category, class Reference, class Pointer, class Difference>
|
||||||
|
struct indirect_iterator;
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
@@ -73,59 +79,103 @@ namespace boost
|
|||||||
|
|
||||||
// Metafunction returning the nested element_type typedef
|
// Metafunction returning the nested element_type typedef
|
||||||
template <class T>
|
template <class T>
|
||||||
struct smart_pointer_traits
|
struct smart_pointer_value : remove_const<typename T::element_type>
|
||||||
{
|
{};
|
||||||
typedef typename remove_const<
|
|
||||||
typename T::element_type
|
|
||||||
>::type value_type;
|
|
||||||
|
|
||||||
typedef typename T::element_type& reference;
|
template <class T>
|
||||||
typedef typename T::element_type* pointer;
|
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
|
// If the Value parameter is unspecified, we use this metafunction
|
||||||
// to deduce the default types
|
// to deduce the default types
|
||||||
template <class Iter>
|
template <class Iter, class Value, class Category, class Reference, class Pointer, class Difference>
|
||||||
struct indirect_defaults
|
struct indirect_base
|
||||||
: 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
|
|
||||||
{
|
{
|
||||||
typedef typename iterator_traits<Iter>::iterator_category iterator_category;
|
typedef typename iterator_value<Iter>::type dereferenceable;
|
||||||
typedef typename iterator_traits<Iter>::difference_type difference_type;
|
|
||||||
|
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
|
template <>
|
||||||
// is supplied gets passed through traits_iterator<...> so that it
|
struct indirect_base<int, int, int, int, int, int> {};
|
||||||
// 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
|
|
||||||
{
|
|
||||||
};
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
template <class Iterator, class Traits = detail::unspecified>
|
template <
|
||||||
class indirect_iterator :
|
class Iterator
|
||||||
public iterator_adaptor<
|
, class Value = not_specified
|
||||||
indirect_iterator<Iterator, Traits>
|
, class Category = not_specified
|
||||||
, Iterator
|
, class Reference = not_specified
|
||||||
, detail::indirect_traits<Iterator,Traits> >
|
, 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<
|
typedef typename detail::indirect_base<
|
||||||
indirect_iterator<Iterator, Traits>
|
Iterator
|
||||||
, Iterator
|
, Value
|
||||||
, detail::indirect_traits<Iterator,Traits>
|
, Category
|
||||||
> super_t;
|
, Reference
|
||||||
|
, Pointer
|
||||||
|
, Difference
|
||||||
|
>::type super_t;
|
||||||
|
|
||||||
friend class iterator_core_access;
|
friend class iterator_core_access;
|
||||||
|
|
||||||
@@ -145,7 +195,14 @@ namespace boost
|
|||||||
{}
|
{}
|
||||||
|
|
||||||
private:
|
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/iterator/detail/enable_if.hpp>
|
||||||
|
|
||||||
#include <boost/mpl/and.hpp>
|
#include <boost/mpl/and.hpp>
|
||||||
|
#include <boost/mpl/not.hpp>
|
||||||
#include <boost/mpl/or.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_same.hpp>
|
||||||
#include <boost/type_traits/is_convertible.hpp>
|
#include <boost/type_traits/is_convertible.hpp>
|
||||||
|
|
||||||
#include <boost/iterator/detail/config_def.hpp>
|
#include <boost/iterator/detail/config_def.hpp>
|
||||||
|
|
||||||
|
#include <boost/iterator/iterator_traits.hpp>
|
||||||
|
|
||||||
namespace boost
|
namespace boost
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
template <class Traits, class Other>
|
template <class Traits, class Other>
|
||||||
@@ -37,8 +41,8 @@ namespace boost
|
|||||||
, typename Other::iterator_category
|
, typename Other::iterator_category
|
||||||
>
|
>
|
||||||
, is_same<
|
, is_same<
|
||||||
typename Traits::iterator_category
|
typename Traits::iterator_category // *** THIS IS A BUG!! ***
|
||||||
, typename Other::iterator_category
|
, typename Other::iterator_category // MAKE FAILING TEST BEFORE FIXING!!
|
||||||
>
|
>
|
||||||
>
|
>
|
||||||
{};
|
{};
|
||||||
@@ -116,6 +120,7 @@ namespace boost
|
|||||||
# endif
|
# endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// iterator_traits_adaptor can be used to create new iterator traits by adapting
|
// 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
|
// 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
|
// argument ordering is different from the std::iterator template, so that default
|
||||||
// arguments can be used effectivly.
|
// arguments can be used effectivly.
|
||||||
//
|
//
|
||||||
template <
|
// The ordering changed slightly with respect to former versions of iterator_adaptor
|
||||||
class Iterator
|
// The idea is that when the user needs to fiddle with the reference type
|
||||||
, class ValueType = typename detail::iterator_traits<Iterator>::value_type
|
// it is highly likely that the iterator category has to be adjusted as well
|
||||||
, class Reference = ValueType&
|
//
|
||||||
, class Pointer = ValueType*
|
// Value - if supplied, the value_type of the resulting iterator, unless
|
||||||
, class IteratorCategory = typename detail::iterator_traits<Iterator>::iterator_category
|
// const. If const, a conforming compiler strips constness for the
|
||||||
, class DifferenceType = typename detail::iterator_traits<Iterator>::difference_type
|
// value_type. If not supplied, iterator_traits<Base>::value_type is used
|
||||||
>
|
//
|
||||||
struct iterator_traits_adaptor
|
// Reference - the reference type of the resulting iterator, and in
|
||||||
: iterator<
|
// particular, the result type of operator*(). If not supplied but
|
||||||
IteratorCategory
|
// Value is supplied, Value& is used. Otherwise
|
||||||
, ValueType
|
// iterator_traits<Base>::reference is used.
|
||||||
, DifferenceType
|
//
|
||||||
, Pointer
|
// Pointer - the pointer type of the resulting iterator, and in
|
||||||
, Reference
|
// 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 <
|
template <
|
||||||
class Derived
|
class Derived
|
||||||
, class Iterator
|
, class Base
|
||||||
, class Traits = detail::iterator_traits<Iterator>
|
, class Value = not_specified
|
||||||
|
, class Category = not_specified
|
||||||
|
, class Reference = not_specified
|
||||||
|
, class Pointer = not_specified
|
||||||
|
, class Difference = not_specified
|
||||||
>
|
>
|
||||||
class iterator_adaptor
|
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;
|
friend class iterator_core_access;
|
||||||
|
|
||||||
|
typedef typename detail::iterator_adaptor_base<
|
||||||
|
Derived, Base, Value, Category, Reference, Pointer, Difference
|
||||||
|
>::type super_t;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
iterator_adaptor() {}
|
iterator_adaptor() {}
|
||||||
|
|
||||||
explicit iterator_adaptor(Iterator iter)
|
explicit iterator_adaptor(Base iter)
|
||||||
: m_iterator(iter)
|
: m_iterator(iter)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator base() const
|
Base base() const
|
||||||
{ return m_iterator; }
|
{ return m_iterator; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Core iterator interface for iterator_facade
|
// Core iterator interface for iterator_facade
|
||||||
//
|
//
|
||||||
|
|
||||||
typename Traits::reference dereference() const
|
typename super_t::reference dereference() const
|
||||||
{ return *m_iterator; }
|
{ return *m_iterator; }
|
||||||
|
|
||||||
template <
|
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(
|
BOOST_STATIC_ASSERT(
|
||||||
(detail::same_category_and_difference<Traits,OtherTraits>::value)
|
(detail::same_category_and_difference<Derived,OtherDerived>::value)
|
||||||
);
|
);
|
||||||
return m_iterator == x.base();
|
return m_iterator == x.base();
|
||||||
}
|
}
|
||||||
|
|
||||||
void advance(typename Traits::difference_type n)
|
void advance(typename super_t::difference_type n)
|
||||||
{
|
{
|
||||||
m_iterator += n;
|
m_iterator += n;
|
||||||
}
|
}
|
||||||
@@ -192,19 +254,24 @@ namespace boost
|
|||||||
void increment() { ++m_iterator; }
|
void increment() { ++m_iterator; }
|
||||||
void decrement() { --m_iterator; }
|
void decrement() { --m_iterator; }
|
||||||
|
|
||||||
template <class OtherDerived, class OtherIterator, class OtherTraits>
|
template <
|
||||||
typename Traits::difference_type distance_to(
|
class OtherDerived, class OtherIterator, class V, class C, class R, class P, class D
|
||||||
iterator_adaptor<OtherDerived, OtherIterator, OtherTraits> const& y) const
|
>
|
||||||
|
typename super_t::difference_type distance_to(
|
||||||
|
iterator_adaptor<OtherDerived, OtherIterator, V, C, R, P, D> const& y) const
|
||||||
{
|
{
|
||||||
BOOST_STATIC_ASSERT(
|
BOOST_STATIC_ASSERT(
|
||||||
(detail::same_category_and_difference<Traits,OtherTraits>::value)
|
(detail::same_category_and_difference<Derived,OtherDerived>::value)
|
||||||
);
|
);
|
||||||
return y.base() - m_iterator;
|
return y.base() - m_iterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
private: // data members
|
// Needed for counting iterator
|
||||||
Iterator m_iterator;
|
Base const& base_reference() const
|
||||||
|
{ return m_iterator; }
|
||||||
|
|
||||||
|
private: // data members
|
||||||
|
Base m_iterator;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace boost
|
} // namespace boost
|
||||||
|
@@ -12,17 +12,23 @@
|
|||||||
|
|
||||||
#include <boost/config.hpp>
|
#include <boost/config.hpp>
|
||||||
#include <boost/iterator/detail/categories.hpp>
|
#include <boost/iterator/detail/categories.hpp>
|
||||||
|
|
||||||
#include <boost/type_traits/conversion_traits.hpp>
|
#include <boost/type_traits/conversion_traits.hpp>
|
||||||
#include <boost/type_traits/cv_traits.hpp>
|
#include <boost/type_traits/cv_traits.hpp>
|
||||||
|
|
||||||
|
#include <boost/python/detail/indirect_traits.hpp>
|
||||||
|
|
||||||
#include <boost/detail/iterator.hpp>
|
#include <boost/detail/iterator.hpp>
|
||||||
#include <boost/detail/workaround.hpp>
|
#include <boost/detail/workaround.hpp>
|
||||||
|
|
||||||
#include <boost/mpl/apply_if.hpp>
|
#include <boost/mpl/apply_if.hpp>
|
||||||
#include <boost/mpl/if.hpp>
|
#include <boost/mpl/if.hpp>
|
||||||
#include <boost/mpl/bool.hpp>
|
#include <boost/mpl/bool.hpp>
|
||||||
#include <boost/mpl/aux_/has_xxx.hpp>
|
#include <boost/mpl/aux_/has_xxx.hpp>
|
||||||
#include <boost/mpl/not.hpp>
|
#include <boost/mpl/not.hpp>
|
||||||
#include <boost/mpl/or.hpp>
|
#include <boost/mpl/or.hpp>
|
||||||
#include <boost/mpl/and.hpp>
|
#include <boost/mpl/apply.hpp>
|
||||||
|
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
|
||||||
#if BOOST_WORKAROUND(__MWERKS__, <=0x2407)
|
#if BOOST_WORKAROUND(__MWERKS__, <=0x2407)
|
||||||
@@ -33,60 +39,142 @@ namespace boost {
|
|||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
// Helper metafunction for std_category below
|
||||||
template <typename ValueType>
|
template <class Cat, class Tag, class Next>
|
||||||
struct choose_lvalue_return
|
struct match_tag
|
||||||
: mpl::if_<
|
: mpl::apply_if<is_tag<Tag, Cat>, mpl::identity<Tag>, Next>
|
||||||
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
|
|
||||||
>
|
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Category>
|
// Converts a possibly user-defined category tag to the
|
||||||
struct iter_category_to_traversal
|
// most-derived standard tag which is a base of that tag.
|
||||||
: mpl::if_<
|
template <class Category>
|
||||||
is_random_access_iterator<Category>
|
struct std_category
|
||||||
, random_access_traversal_tag
|
: match_tag<
|
||||||
, typename mpl::if_<
|
Category, std::random_access_iterator_tag
|
||||||
is_bidirectional_iterator<Category>
|
, match_tag<Category, std::bidirectional_iterator_tag
|
||||||
, bidirectional_traversal_tag
|
, match_tag<Category, std::forward_iterator_tag
|
||||||
, typename mpl::if_<
|
, match_tag<Category, std::input_iterator_tag
|
||||||
is_forward_iterator<Category>
|
, match_tag<Category, std::output_iterator_tag
|
||||||
, forward_traversal_tag
|
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
||||||
, typename mpl::if_<
|
, mpl::identity<void>
|
||||||
is_input_iterator<Category>
|
# else
|
||||||
, input_traversal_tag
|
, void
|
||||||
, output_traversal_tag
|
# endif
|
||||||
>::type
|
>
|
||||||
>::type
|
>
|
||||||
>::type
|
>
|
||||||
|
>
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 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>
|
template <class T>
|
||||||
struct is_boost_iterator_tag;
|
struct is_boost_iterator_tag;
|
||||||
|
|
||||||
#if BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
|
#if BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
|
||||||
//
|
//
|
||||||
// has_xxx fails, so we have to use
|
// has_xxx fails, so we have to use
|
||||||
@@ -98,9 +186,13 @@ namespace boost {
|
|||||||
// defined for cwpro7.
|
// defined for cwpro7.
|
||||||
//
|
//
|
||||||
template <class Tag>
|
template <class Tag>
|
||||||
struct is_new_iterator_tag :
|
struct is_new_iterator_tag
|
||||||
mpl::and_< mpl::not_< is_input_iterator<Tag> >,
|
: mpl::not_<
|
||||||
mpl::not_< is_output_iterator<Tag> > >
|
mpl::or_<
|
||||||
|
is_tag<std::input_iterator_tag, Tag>
|
||||||
|
, is_tag<std::output_iterator_tag, Tag>
|
||||||
|
>
|
||||||
|
>
|
||||||
{};
|
{};
|
||||||
|
|
||||||
#elif BOOST_WORKAROUND(__GNUC__, == 2 && __GNUC_MINOR__ == 95) \
|
#elif BOOST_WORKAROUND(__GNUC__, == 2 && __GNUC_MINOR__ == 95) \
|
||||||
@@ -118,12 +210,11 @@ namespace boost {
|
|||||||
|
|
||||||
template <class Tag>
|
template <class Tag>
|
||||||
struct is_new_iterator_tag
|
struct is_new_iterator_tag
|
||||||
: //has_traversal<Tag>
|
: mpl::if_<
|
||||||
mpl::if_<
|
is_class<Tag>
|
||||||
is_class<Tag>
|
, has_traversal<Tag>
|
||||||
, has_traversal<Tag>
|
, mpl::false_
|
||||||
, mpl::false_
|
>::type
|
||||||
>::type
|
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -134,7 +225,7 @@ namespace boost {
|
|||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template <class NewCategoryTag>
|
template <class NewCategoryTag>
|
||||||
struct get_return_category {
|
struct get_access_category {
|
||||||
typedef typename NewCategoryTag::returns type;
|
typedef typename NewCategoryTag::returns type;
|
||||||
};
|
};
|
||||||
template <class NewCategoryTag>
|
template <class NewCategoryTag>
|
||||||
@@ -142,51 +233,57 @@ namespace boost {
|
|||||||
typedef typename NewCategoryTag::traversal type;
|
typedef typename NewCategoryTag::traversal type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class CategoryTag, class Value>
|
template <class CategoryTag, class Reference>
|
||||||
struct return_category_tag
|
struct access_category_tag
|
||||||
: mpl::apply_if<
|
: mpl::apply_if<
|
||||||
is_new_iterator_tag<CategoryTag>
|
is_new_iterator_tag<CategoryTag>
|
||||||
, get_return_category<CategoryTag>
|
, get_access_category<CategoryTag>
|
||||||
, iter_category_to_return<CategoryTag, Value>
|
, iter_category_to_access<CategoryTag, Reference>
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class CategoryTag, class Value>
|
template <class CategoryTag>
|
||||||
struct traversal_category_tag
|
struct traversal_category_tag
|
||||||
: mpl::apply_if<
|
: mpl::apply_if<
|
||||||
is_new_iterator_tag<CategoryTag>
|
is_new_iterator_tag<CategoryTag>
|
||||||
, get_traversal_category<CategoryTag>
|
, get_traversal_category<CategoryTag>
|
||||||
, iter_category_to_traversal<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
|
} // namespace detail
|
||||||
|
|
||||||
template <class Iterator>
|
template <class Iterator>
|
||||||
struct return_category
|
struct access_category
|
||||||
: detail::return_category_tag<
|
: detail::access_category_tag<
|
||||||
typename detail::iterator_traits<Iterator>::iterator_category
|
typename detail::iterator_traits<Iterator>::iterator_category
|
||||||
, typename detail::iterator_traits<Iterator>::value_type>
|
, typename detail::iterator_traits<Iterator>::reference>
|
||||||
{};
|
{};
|
||||||
|
|
||||||
template <class Iterator>
|
template <class Iterator>
|
||||||
struct traversal_category
|
struct traversal_category
|
||||||
: detail::traversal_category_tag<
|
: detail::traversal_category_tag<
|
||||||
typename detail::iterator_traits<Iterator>::iterator_category
|
typename detail::iterator_traits<Iterator>::iterator_category
|
||||||
, typename detail::iterator_traits<Iterator>::value_type>
|
>
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct return_category<T*>
|
struct access_category<T*>
|
||||||
: mpl::if_<
|
: mpl::if_<
|
||||||
is_const<T>
|
is_const<T>
|
||||||
, constant_lvalue_iterator_tag
|
, readable_lvalue_iterator_tag
|
||||||
, mutable_lvalue_iterator_tag>
|
, writable_lvalue_iterator_tag>
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -198,50 +295,12 @@ namespace boost {
|
|||||||
|
|
||||||
#endif
|
#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>
|
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 ReturnTag returns;
|
||||||
typedef TraversalTag traversal;
|
typedef TraversalTag traversal;
|
||||||
@@ -264,11 +323,11 @@ namespace boost {
|
|||||||
typedef char (&yes)[1];
|
typedef char (&yes)[1];
|
||||||
typedef char (&no)[2];
|
typedef char (&no)[2];
|
||||||
|
|
||||||
template <class R, class T>
|
template <class R, class U>
|
||||||
static yes test(iterator_tag<R,T> const&);
|
static yes test(mpl::identity<iterator_tag<R,U> >*);
|
||||||
static no test(...);
|
static no test(...);
|
||||||
|
|
||||||
static T inst;
|
static mpl::identity<T>* inst;
|
||||||
BOOST_STATIC_CONSTANT(bool, value = sizeof(test(inst)) == sizeof(yes));
|
BOOST_STATIC_CONSTANT(bool, value = sizeof(test(inst)) == sizeof(yes));
|
||||||
typedef mpl::bool_<value> type;
|
typedef mpl::bool_<value> type;
|
||||||
};
|
};
|
||||||
|
@@ -43,9 +43,9 @@ namespace boost_concepts {
|
|||||||
template <typename Iterator>
|
template <typename Iterator>
|
||||||
class ReadableIteratorConcept {
|
class ReadableIteratorConcept {
|
||||||
public:
|
public:
|
||||||
typedef typename boost::detail::iterator_traits<Iterator>::value_type value_type;
|
typedef BOOST_DEDUCED_TYPENAME ::boost::detail::iterator_traits<Iterator>::value_type value_type;
|
||||||
typedef typename boost::detail::iterator_traits<Iterator>::reference reference;
|
typedef BOOST_DEDUCED_TYPENAME ::boost::detail::iterator_traits<Iterator>::reference reference;
|
||||||
typedef typename boost::return_category<Iterator>::type return_category;
|
typedef BOOST_DEDUCED_TYPENAME ::boost::access_category<Iterator>::type access_category;
|
||||||
|
|
||||||
void constraints() {
|
void constraints() {
|
||||||
boost::function_requires< boost::SGIAssignableConcept<Iterator> >();
|
boost::function_requires< boost::SGIAssignableConcept<Iterator> >();
|
||||||
@@ -53,7 +53,7 @@ namespace boost_concepts {
|
|||||||
boost::function_requires<
|
boost::function_requires<
|
||||||
boost::DefaultConstructibleConcept<Iterator> >();
|
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)
|
reference r = *i; // or perhaps read(x)
|
||||||
value_type v(r);
|
value_type v(r);
|
||||||
@@ -65,7 +65,7 @@ namespace boost_concepts {
|
|||||||
template <typename Iterator, typename ValueType>
|
template <typename Iterator, typename ValueType>
|
||||||
class WritableIteratorConcept {
|
class WritableIteratorConcept {
|
||||||
public:
|
public:
|
||||||
typedef typename boost::return_category<Iterator>::type return_category;
|
typedef typename boost::access_category<Iterator>::type access_category;
|
||||||
|
|
||||||
void constraints() {
|
void constraints() {
|
||||||
boost::function_requires< boost::SGIAssignableConcept<Iterator> >();
|
boost::function_requires< boost::SGIAssignableConcept<Iterator> >();
|
||||||
@@ -73,7 +73,7 @@ namespace boost_concepts {
|
|||||||
boost::function_requires<
|
boost::function_requires<
|
||||||
boost::DefaultConstructibleConcept<Iterator> >();
|
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)
|
*i = v; // a good alternative could be something like write(x, v)
|
||||||
}
|
}
|
||||||
@@ -86,12 +86,12 @@ namespace boost_concepts {
|
|||||||
public:
|
public:
|
||||||
typedef typename boost::detail::iterator_traits<Iterator>::value_type value_type;
|
typedef typename boost::detail::iterator_traits<Iterator>::value_type value_type;
|
||||||
typedef typename boost::detail::iterator_traits<Iterator>::reference reference;
|
typedef typename boost::detail::iterator_traits<Iterator>::reference reference;
|
||||||
typedef typename boost::return_category<Iterator>::type return_category;
|
typedef typename boost::access_category<Iterator>::type access_category;
|
||||||
|
|
||||||
void constraints() {
|
void constraints() {
|
||||||
boost::function_requires< ReadableIteratorConcept<Iterator> >();
|
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));
|
BOOST_STATIC_ASSERT((boost::is_same<reference, const value_type&>::value));
|
||||||
|
|
||||||
@@ -106,14 +106,14 @@ namespace boost_concepts {
|
|||||||
public:
|
public:
|
||||||
typedef typename boost::detail::iterator_traits<Iterator>::value_type value_type;
|
typedef typename boost::detail::iterator_traits<Iterator>::value_type value_type;
|
||||||
typedef typename boost::detail::iterator_traits<Iterator>::reference reference;
|
typedef typename boost::detail::iterator_traits<Iterator>::reference reference;
|
||||||
typedef typename boost::return_category<Iterator>::type return_category;
|
typedef typename boost::access_category<Iterator>::type access_category;
|
||||||
|
|
||||||
void constraints() {
|
void constraints() {
|
||||||
boost::function_requires< ReadableIteratorConcept<Iterator> >();
|
boost::function_requires< ReadableIteratorConcept<Iterator> >();
|
||||||
boost::function_requires<
|
boost::function_requires<
|
||||||
WritableIteratorConcept<Iterator, value_type> >();
|
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));
|
BOOST_STATIC_ASSERT((boost::is_same<reference, value_type&>::value));
|
||||||
|
|
||||||
@@ -188,54 +188,56 @@ namespace boost_concepts {
|
|||||||
//===========================================================================
|
//===========================================================================
|
||||||
// Iterator Interoperability Concept
|
// Iterator Interoperability Concept
|
||||||
|
|
||||||
namespace detail {
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
template <typename TraversalTag>
|
template <typename TraversalTag>
|
||||||
struct Operations;
|
struct Operations;
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct Operations<boost::input_traversal_tag>
|
struct Operations<boost::incrementable_iterator_tag>
|
||||||
{
|
{
|
||||||
template <typename Iterator1, typename Iterator2>
|
template <typename Iterator1, typename Iterator2>
|
||||||
static void constraints(Iterator1 const& i1, Iterator2 const& i2)
|
static void constraints(Iterator1 const& i1, Iterator2 const& i2)
|
||||||
{
|
{
|
||||||
i1 == i2;
|
// no interoperability constraints
|
||||||
i1 != i2;
|
|
||||||
|
|
||||||
i2 == i1;
|
|
||||||
i2 != i1;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct Operations<boost::output_traversal_tag>
|
struct Operations<boost::single_pass_iterator_tag>
|
||||||
{
|
{
|
||||||
template <typename Iterator1, typename Iterator2>
|
template <typename Iterator1, typename Iterator2>
|
||||||
static void constraints(Iterator1 const& i1, Iterator2 const& i2)
|
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 <>
|
i2 == i1;
|
||||||
struct Operations<boost::forward_traversal_tag>
|
i2 != i1;
|
||||||
{
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct Operations<boost::forward_traversal_tag>
|
||||||
|
{
|
||||||
template <typename Iterator1, typename Iterator2>
|
template <typename Iterator1, typename Iterator2>
|
||||||
static void constraints(Iterator1 const& i1, Iterator2 const& i2)
|
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 <>
|
template <>
|
||||||
struct Operations<boost::bidirectional_traversal_tag>
|
struct Operations<boost::bidirectional_traversal_tag>
|
||||||
{
|
{
|
||||||
template <typename Iterator1, typename Iterator2>
|
template <typename Iterator1, typename Iterator2>
|
||||||
static void constraints(Iterator1 const& i1, Iterator2 const& i2)
|
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 <>
|
template <>
|
||||||
struct Operations<boost::random_access_traversal_tag>
|
struct Operations<boost::random_access_traversal_tag>
|
||||||
|
@@ -10,18 +10,25 @@
|
|||||||
#define BOOST_ITERATOR_FACADE_23022003THW_HPP
|
#define BOOST_ITERATOR_FACADE_23022003THW_HPP
|
||||||
|
|
||||||
#include <boost/static_assert.hpp>
|
#include <boost/static_assert.hpp>
|
||||||
|
|
||||||
#include <boost/iterator.hpp>
|
#include <boost/iterator.hpp>
|
||||||
|
#include <boost/iterator/iterator_categories.hpp>
|
||||||
#include <boost/iterator/interoperable.hpp>
|
#include <boost/iterator/interoperable.hpp>
|
||||||
#include <boost/iterator/detail/enable_if.hpp>
|
#include <boost/iterator/detail/enable_if.hpp>
|
||||||
|
|
||||||
#include <boost/type_traits/is_same.hpp>
|
#include <boost/type_traits/is_same.hpp>
|
||||||
#include <boost/type_traits/is_convertible.hpp>
|
#include <boost/type_traits/is_convertible.hpp>
|
||||||
|
|
||||||
|
#include <boost/iterator/iterator_traits.hpp>
|
||||||
#include <boost/iterator/detail/config_def.hpp>
|
#include <boost/iterator/detail/config_def.hpp>
|
||||||
|
|
||||||
|
#include <boost/mpl/apply_if.hpp>
|
||||||
|
|
||||||
namespace boost
|
namespace boost
|
||||||
{
|
{
|
||||||
|
|
||||||
|
struct not_specified;
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -53,19 +60,135 @@ namespace boost
|
|||||||
// Generates the corresponding std::iterator specialization
|
// Generates the corresponding std::iterator specialization
|
||||||
// from the given iterator traits type
|
// from the given iterator traits type
|
||||||
//
|
//
|
||||||
template <class Traits>
|
template <class Value, class Category, class Reference, class Pointer, class Difference>
|
||||||
struct std_iterator_from_traits
|
struct iterator_facade_base
|
||||||
: iterator<
|
|
||||||
typename Traits::iterator_category
|
|
||||||
, typename Traits::value_type
|
|
||||||
, typename Traits::difference_type
|
|
||||||
, typename Traits::pointer
|
|
||||||
, typename Traits::reference
|
|
||||||
>
|
|
||||||
{
|
{
|
||||||
|
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
|
} // namespace detail
|
||||||
|
|
||||||
|
|
||||||
@@ -131,17 +254,24 @@ namespace boost
|
|||||||
//
|
//
|
||||||
template <
|
template <
|
||||||
class Derived
|
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
|
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
|
// CRT interface.
|
||||||
// from the public interface without template friends
|
|
||||||
//
|
//
|
||||||
typedef Derived derived_t;
|
typedef Derived derived_t;
|
||||||
|
|
||||||
@@ -155,10 +285,13 @@ namespace boost
|
|||||||
return static_cast<Derived const&>(*this);
|
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::reference reference;
|
||||||
typedef typename super_t::difference_type difference_type;
|
typedef typename super_t::difference_type difference_type;
|
||||||
typedef typename super_t::pointer pointer;
|
typedef typename super_t::pointer pointer;
|
||||||
|
typedef typename super_t::iterator_category iterator_category;
|
||||||
|
|
||||||
reference operator*() const
|
reference operator*() const
|
||||||
{
|
{
|
||||||
@@ -166,14 +299,32 @@ namespace boost
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Needs eventual help for input iterators
|
// 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++()
|
Derived& operator++()
|
||||||
@@ -289,13 +440,16 @@ namespace boost
|
|||||||
//
|
//
|
||||||
|
|
||||||
# define BOOST_ITERATOR_FACADE_INTEROP(op, result_type, condition, return_prefix, base_op) \
|
# 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< \
|
inline typename detail::enable_if_interoperable< \
|
||||||
Derived1, Derived2, result_type \
|
Derived1, Derived2, result_type \
|
||||||
>::type \
|
>::type \
|
||||||
operator op( \
|
operator op( \
|
||||||
iterator_facade<Derived1, Traits1> const& lhs \
|
iterator_facade<Derived1, V1, C1, R1, P1, D1> const& lhs \
|
||||||
, iterator_facade<Derived2, Traits2> const& rhs) \
|
, iterator_facade<Derived2, V2, C2, R2, P2, D2> const& rhs) \
|
||||||
{ \
|
{ \
|
||||||
/* For those compilers that do not support enable_if */ \
|
/* For those compilers that do not support enable_if */ \
|
||||||
BOOST_STATIC_ASSERT(( \
|
BOOST_STATIC_ASSERT(( \
|
||||||
@@ -303,8 +457,8 @@ namespace boost
|
|||||||
&& condition \
|
&& condition \
|
||||||
)); \
|
)); \
|
||||||
return_prefix iterator_core_access::base_op( \
|
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) \
|
# define BOOST_ITERATOR_FACADE_RELATION(op, return_prefix, base_op) \
|
||||||
BOOST_ITERATOR_FACADE_INTEROP( \
|
BOOST_ITERATOR_FACADE_INTEROP( \
|
||||||
@@ -327,31 +481,31 @@ namespace boost
|
|||||||
// operator- requires an additional part in the static assertion
|
// operator- requires an additional part in the static assertion
|
||||||
BOOST_ITERATOR_FACADE_INTEROP(
|
BOOST_ITERATOR_FACADE_INTEROP(
|
||||||
-
|
-
|
||||||
, typename Traits1::difference_type
|
, typename Derived1::difference_type
|
||||||
, (is_same<
|
, (is_same<
|
||||||
BOOST_ARG_DEP_TYPENAME Traits1::difference_type
|
BOOST_ARG_DEP_TYPENAME Derived1::difference_type
|
||||||
, BOOST_ARG_DEP_TYPENAME Traits2::difference_type
|
, BOOST_ARG_DEP_TYPENAME Derived2::difference_type
|
||||||
>::value)
|
>::value)
|
||||||
, return
|
, return
|
||||||
, distance_to )
|
, distance_to )
|
||||||
# undef BOOST_ITERATOR_FACADE_INTEROP
|
# undef BOOST_ITERATOR_FACADE_INTEROP
|
||||||
|
|
||||||
# define BOOST_ITERATOR_FACADE_PLUS(args) \
|
# define BOOST_ITERATOR_FACADE_PLUS(args) \
|
||||||
template <class Derived, class Traits> \
|
template <class Derived, class V, class C, class R, class P, class D> \
|
||||||
inline Derived operator+ args \
|
inline Derived operator+ args \
|
||||||
{ \
|
{ \
|
||||||
Derived tmp(i.derived()); \
|
Derived tmp(static_cast<Derived const&>(i)); \
|
||||||
return tmp += n; \
|
return tmp += n; \
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_ITERATOR_FACADE_PLUS((
|
BOOST_ITERATOR_FACADE_PLUS((
|
||||||
iterator_facade<Derived, Traits> const& i
|
iterator_facade<Derived, V, C, R, P, D> const& i
|
||||||
, typename Traits::difference_type n
|
, typename Derived::difference_type n
|
||||||
))
|
))
|
||||||
|
|
||||||
BOOST_ITERATOR_FACADE_PLUS((
|
BOOST_ITERATOR_FACADE_PLUS((
|
||||||
typename Traits::difference_type n
|
typename Derived::difference_type n
|
||||||
, iterator_facade<Derived, Traits> const& i
|
, iterator_facade<Derived, V, C, R, P, D> const& i
|
||||||
))
|
))
|
||||||
# undef BOOST_ITERATOR_FACADE_PLUS
|
# 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_readable(readable_iterator_tag) { }
|
||||||
void is_writable(writable_iterator_tag) { }
|
void is_writable(writable_iterator_tag) { }
|
||||||
void is_swappable(swappable_iterator_tag) { }
|
void is_swappable(swappable_iterator_tag) { }
|
||||||
void is_constant_lvalue(constant_lvalue_iterator_tag) { }
|
void is_constant_lvalue(readable_lvalue_iterator_tag) { }
|
||||||
void is_mutable_lvalue(mutable_lvalue_iterator_tag) { }
|
void is_mutable_lvalue(writable_lvalue_iterator_tag) { }
|
||||||
|
|
||||||
// Preconditions: *i == v
|
// Preconditions: *i == v
|
||||||
template <class Iterator, class T>
|
template <class Iterator, class T>
|
||||||
@@ -45,7 +45,7 @@ void readable_iterator_test(const Iterator i1, T v)
|
|||||||
T v2 = r2;
|
T v2 = r2;
|
||||||
assert(v1 == v);
|
assert(v1 == v);
|
||||||
assert(v2 == v);
|
assert(v2 == v);
|
||||||
typename return_category<Iterator>::type result_category;
|
typename access_category<Iterator>::type result_category;
|
||||||
is_readable(result_category);
|
is_readable(result_category);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ void writable_iterator_test(Iterator i, T v)
|
|||||||
{
|
{
|
||||||
Iterator i2(i); // Copy Constructible
|
Iterator i2(i); // Copy Constructible
|
||||||
*i2 = v;
|
*i2 = v;
|
||||||
is_writable(typename return_category<Iterator>::type());
|
is_writable(typename access_category<Iterator>::type());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Iterator>
|
template <class Iterator>
|
||||||
@@ -65,7 +65,7 @@ void swappable_iterator_test(Iterator i, Iterator j)
|
|||||||
iter_swap(i2, j2);
|
iter_swap(i2, j2);
|
||||||
typename detail::iterator_traits<Iterator>::value_type ai = *i, aj = *j;
|
typename detail::iterator_traits<Iterator>::value_type ai = *i, aj = *j;
|
||||||
assert(bi == aj && bj == ai);
|
assert(bi == aj && bj == ai);
|
||||||
typedef typename return_category<Iterator>::type result_category;
|
typedef typename access_category<Iterator>::type result_category;
|
||||||
is_swappable(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));
|
BOOST_STATIC_ASSERT((is_same<const value_type&, reference>::value));
|
||||||
const T& v2 = *i2;
|
const T& v2 = *i2;
|
||||||
assert(v1 == v2);
|
assert(v1 == v2);
|
||||||
typedef typename return_category<Iterator>::type result_category;
|
typedef typename access_category<Iterator>::type result_category;
|
||||||
is_constant_lvalue(result_category());
|
is_constant_lvalue(result_category());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,7 +94,7 @@ void mutable_lvalue_iterator_test(Iterator i, T v1, T v2)
|
|||||||
*i = v2;
|
*i = v2;
|
||||||
T& v4 = *i2;
|
T& v4 = *i2;
|
||||||
assert(v2 == v4);
|
assert(v2 == v4);
|
||||||
typedef typename return_category<Iterator>::type result_category;
|
typedef typename access_category<Iterator>::type result_category;
|
||||||
is_mutable_lvalue(result_category());
|
is_mutable_lvalue(result_category());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -15,43 +15,36 @@
|
|||||||
|
|
||||||
namespace boost
|
namespace boost
|
||||||
{
|
{
|
||||||
|
template <class AdaptableUnaryFunction, class Iterator>
|
||||||
|
class transform_iterator;
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
|
||||||
// Given the transform iterator's transformation and iterator, this
|
// Given the transform iterator's transformation and iterator, this
|
||||||
// is the type used as its traits.
|
// is the type used as its traits.
|
||||||
template <class AdaptableUnaryFunction, class Iterator>
|
template <class AdaptableUnaryFunction, class Iterator>
|
||||||
struct transform_iterator_traits
|
struct transform_iterator_base
|
||||||
: iterator_traits_adaptor<
|
{
|
||||||
Iterator
|
typedef iterator_adaptor<
|
||||||
|
transform_iterator<AdaptableUnaryFunction, Iterator>
|
||||||
|
, Iterator
|
||||||
, typename AdaptableUnaryFunction::result_type
|
, typename AdaptableUnaryFunction::result_type
|
||||||
, typename AdaptableUnaryFunction::result_type
|
|
||||||
, typename AdaptableUnaryFunction::result_type*
|
|
||||||
, iterator_tag<
|
, iterator_tag<
|
||||||
readable_iterator_tag
|
readable_iterator_tag
|
||||||
, typename traversal_category<Iterator>::type
|
, typename traversal_category<Iterator>::type
|
||||||
>
|
>
|
||||||
>
|
, typename AdaptableUnaryFunction::result_type
|
||||||
{
|
> type;
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
} // transform_iterator_traits
|
|
||||||
|
|
||||||
//
|
|
||||||
template <class AdaptableUnaryFunction, class Iterator>
|
template <class AdaptableUnaryFunction, class Iterator>
|
||||||
class transform_iterator
|
class transform_iterator
|
||||||
: public iterator_adaptor<
|
: public detail::transform_iterator_base<AdaptableUnaryFunction, Iterator>::type
|
||||||
transform_iterator<AdaptableUnaryFunction, Iterator>
|
|
||||||
, Iterator
|
|
||||||
, detail::transform_iterator_traits<AdaptableUnaryFunction,Iterator>
|
|
||||||
>
|
|
||||||
{
|
{
|
||||||
typedef iterator_adaptor<
|
typedef typename
|
||||||
transform_iterator<AdaptableUnaryFunction, Iterator>
|
detail::transform_iterator_base<AdaptableUnaryFunction, Iterator>::type
|
||||||
, Iterator
|
super_t;
|
||||||
, detail::transform_iterator_traits<AdaptableUnaryFunction,Iterator>
|
|
||||||
> super_t;
|
|
||||||
|
|
||||||
friend class iterator_core_access;
|
friend class iterator_core_access;
|
||||||
|
|
||||||
|
@@ -2,6 +2,7 @@ SEARCH on testing.jam = $(BOOST_BUILD_PATH) ;
|
|||||||
include testing.jam ;
|
include testing.jam ;
|
||||||
run concept_tests.cpp ;
|
run concept_tests.cpp ;
|
||||||
run iterator_adaptor_cc.cpp ;
|
run iterator_adaptor_cc.cpp ;
|
||||||
|
run counting_iterator_test.cpp ;
|
||||||
run transform_iterator_test.cpp ;
|
run transform_iterator_test.cpp ;
|
||||||
run indirect_iterator_test.cpp ;
|
run indirect_iterator_test.cpp ;
|
||||||
run filter_iterator_test.cpp ;
|
run filter_iterator_test.cpp ;
|
||||||
|
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
struct new_iterator
|
struct new_iterator
|
||||||
: public boost::iterator< boost::iterator_tag<
|
: public boost::iterator< boost::iterator_tag<
|
||||||
boost::mutable_lvalue_iterator_tag
|
boost::writable_lvalue_iterator_tag
|
||||||
, boost::random_access_traversal_tag>, int>
|
, boost::random_access_traversal_tag>, int>
|
||||||
{
|
{
|
||||||
int& operator*() const { return *m_x; }
|
int& operator*() const { return *m_x; }
|
||||||
@@ -53,16 +53,14 @@ old_iterator operator+(std::ptrdiff_t, old_iterator x) { return x; }
|
|||||||
int
|
int
|
||||||
main()
|
main()
|
||||||
{
|
{
|
||||||
BOOST_STATIC_ASSERT( boost::detail::is_random_access_traversal_iterator<boost::random_access_traversal_tag>::value );
|
typedef boost::iterator_tag< boost::writable_lvalue_iterator_tag, boost::random_access_traversal_tag > tag;
|
||||||
|
|
||||||
typedef boost::iterator_tag< boost::mutable_lvalue_iterator_tag, boost::random_access_traversal_tag > tag;
|
|
||||||
|
|
||||||
// BOOST_STATIC_ASSERT((boost::detail::is_random_access_iterator<tag>::value));
|
// 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::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::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));
|
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;
|
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;
|
using boost::dummyT;
|
||||||
|
|
||||||
struct one_or_four {
|
struct one_or_four
|
||||||
bool operator()(dummyT x) const {
|
{
|
||||||
return x.foo() == 1 || x.foo() == 4;
|
bool operator()(dummyT x) const
|
||||||
}
|
{
|
||||||
|
return x.foo() == 1 || x.foo() == 4;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||||
@@ -27,6 +29,7 @@ namespace boost { namespace detail
|
|||||||
}}
|
}}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
template <class T> struct undefined;
|
||||||
|
|
||||||
// Test filter iterator
|
// Test filter iterator
|
||||||
int main()
|
int main()
|
||||||
@@ -41,11 +44,15 @@ int main()
|
|||||||
filter_iter(one_or_four(), array, array+N)
|
filter_iter(one_or_four(), array, array+N)
|
||||||
, dummyT(1), dummyT(4));
|
, dummyT(1), dummyT(4));
|
||||||
|
|
||||||
//# if 0
|
// Filter iterators can't be bidirectional, since we didn't choose
|
||||||
BOOST_STATIC_ASSERT(
|
// to store the beginning of the range.
|
||||||
(!boost::detail::is_bidirectional_traversal_iterator<
|
BOOST_STATIC_ASSERT((
|
||||||
boost::traversal_category<filter_iter>::type
|
!boost::detail::is_tag<
|
||||||
>::value) );
|
boost::bidirectional_traversal_tag
|
||||||
|
, boost::traversal_category<filter_iter>::type
|
||||||
|
>::value
|
||||||
|
));
|
||||||
|
|
||||||
//# endif
|
//# endif
|
||||||
|
|
||||||
// On compilers not supporting partial specialization, we can do more type
|
// 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 RA_CONTAINER<int*> pointer_ra_container;
|
||||||
typedef std::set<storage::iterator> iterator_set;
|
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>
|
template <class Container>
|
||||||
struct indirect_iterator_pair_generator
|
struct indirect_iterator_pair_generator
|
||||||
{
|
{
|
||||||
@@ -84,7 +74,7 @@ struct indirect_iterator_pair_generator
|
|||||||
|
|
||||||
typedef boost::indirect_iterator<
|
typedef boost::indirect_iterator<
|
||||||
typename Container::iterator
|
typename Container::iterator
|
||||||
, indirect_const_iterator_traits<typename Container::const_iterator>
|
, typename iterator::value_type const
|
||||||
> const_iterator;
|
> const_iterator;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -114,8 +104,10 @@ namespace boost { namespace detail
|
|||||||
}}
|
}}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void more_indirect_iterator_tests()
|
void more_indirect_iterator_tests()
|
||||||
{
|
{
|
||||||
|
# if 0
|
||||||
storage store(1000);
|
storage store(1000);
|
||||||
std::generate(store.begin(), store.end(), rand);
|
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_set_iterator;
|
||||||
typedef boost::indirect_iterator<
|
typedef boost::indirect_iterator<
|
||||||
iterator_set::iterator
|
iterator_set::iterator
|
||||||
, indirect_const_iterator_traits<iterator_set::const_iterator>
|
, iterator_set::iterator::value_type const
|
||||||
> const_indirect_set_iterator;
|
> const_indirect_set_iterator;
|
||||||
|
|
||||||
indirect_set_iterator sb(iter_set.begin());
|
indirect_set_iterator sb(iter_set.begin());
|
||||||
indirect_set_iterator se(iter_set.end());
|
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]);
|
boost::bidirectional_iterator_test(boost::next(sb), store[1], store[2]);
|
||||||
assert(std::equal(db, de, store.begin()));
|
assert(std::equal(db, de, store.begin()));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -210,8 +203,8 @@ main()
|
|||||||
|
|
||||||
typedef boost::indirect_iterator<
|
typedef boost::indirect_iterator<
|
||||||
shared_t::iterator
|
shared_t::iterator
|
||||||
, indirect_const_iterator_traits<shared_t::const_iterator>
|
, boost::iterator_value<shared_t::iterator>::type const
|
||||||
> c_iter_t;
|
> c_iter_t;
|
||||||
|
|
||||||
# ifndef NO_MUTABLE_CONST_RA_ITERATOR_INTEROPERABILITY
|
# ifndef NO_MUTABLE_CONST_RA_ITERATOR_INTEROPERABILITY
|
||||||
boost::function_requires< boost_concepts::InteroperableConcept<iter_t, c_iter_t> >();
|
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_iterator;
|
||||||
|
|
||||||
typedef boost::indirect_iterator<dummyT**, indirect_const_iterator_traits<dummyT* const*> >
|
typedef boost::indirect_iterator<dummyT**, dummyT const>
|
||||||
const_indirect_iterator;
|
const_indirect_iterator;
|
||||||
|
|
||||||
indirect_iterator i(ptr);
|
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/indirect_iterator.hpp>
|
||||||
#include <boost/iterator/reverse_iterator.hpp>
|
#include <boost/iterator/reverse_iterator.hpp>
|
||||||
#include <boost/concept_check.hpp>
|
#include <boost/concept_check.hpp>
|
||||||
|
@@ -1,6 +1,4 @@
|
|||||||
// Test boost/iterator_adaptors.hpp
|
// (C) Copyright Thomas Witt 2003. Permission to copy, use, modify,
|
||||||
|
|
||||||
// (C) Copyright Jeremy Siek 2002. Permission to copy, use, modify,
|
|
||||||
// sell and distribute this software is granted provided this
|
// sell and distribute this software is granted provided this
|
||||||
// copyright notice appears in all copies. This software is provided
|
// copyright notice appears in all copies. This software is provided
|
||||||
// "as is" without express or implied warranty, and with no claim as
|
// "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.
|
// 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 <boost/config.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
@@ -125,23 +85,24 @@ struct my_gen
|
|||||||
|
|
||||||
template <class V>
|
template <class V>
|
||||||
struct ptr_iterator
|
struct ptr_iterator
|
||||||
: boost::iterator_adaptor<ptr_iterator<V>
|
: boost::iterator_adaptor<
|
||||||
, V, V&, V*
|
ptr_iterator<V>,
|
||||||
, boost::iterator_tag<boost::mutable_lvalue_iterator_tag
|
boost::iterator_traits_adaptor<V*,
|
||||||
,boost::random_access_traversal_tag>
|
V,
|
||||||
, std::ptrdiff_t>
|
boost::iterator_tag< boost::writable_lvalue_iterator_tag
|
||||||
|
,boost::random_access_traversal_tag > >
|
||||||
|
>
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
typedef iterator_adaptor super_t;
|
||||||
|
public:
|
||||||
ptr_iterator() { }
|
ptr_iterator() { }
|
||||||
ptr_iterator(V* d) : m_base(d) { }
|
ptr_iterator(V* d) : super_t(d) { }
|
||||||
|
|
||||||
template <class V2>
|
template <class V2>
|
||||||
ptr_iterator(const ptr_iterator<V2>& x) // should assert is_same add_cv<V> add_cv<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
|
int
|
||||||
@@ -164,9 +125,7 @@ main()
|
|||||||
boost::const_nonconst_iterator_test(i, ++j);
|
boost::const_nonconst_iterator_test(i, ++j);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test the iterator_traits
|
||||||
#if 0
|
|
||||||
// Test the named parameters
|
|
||||||
{
|
{
|
||||||
// Test computation of defaults
|
// Test computation of defaults
|
||||||
typedef boost::iterator_adaptor<int*, boost::default_iterator_policies,
|
typedef boost::iterator_adaptor<int*, boost::default_iterator_policies,
|
||||||
@@ -218,175 +177,6 @@ main()
|
|||||||
boost::const_nonconst_iterator_test(i, ++j);
|
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
|
// check operator-> with a forward iterator
|
||||||
{
|
{
|
||||||
boost::forward_iterator_archetype<dummyT> forward_iter;
|
boost::forward_iterator_archetype<dummyT> forward_iter;
|
||||||
@@ -423,54 +213,6 @@ main()
|
|||||||
assert((*i).m_x == i->foo());
|
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;
|
std::cout << "test successful " << std::endl;
|
||||||
return 0;
|
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