forked from boostorg/iterator
Added iterator_traits_adaptor.
Implemented minimum_category. Removed base class injection facilities. [SVN r879]
This commit is contained in:
@@ -12,7 +12,6 @@
|
||||
#include <boost/type_traits/conversion_traits.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/bool_c.hpp>
|
||||
#include <boost/mpl/logical/or.hpp>
|
||||
#include <iterator>
|
||||
|
||||
#if BOOST_WORKAROUND(__MWERKS__, <=0x2407)
|
||||
@@ -21,6 +20,13 @@
|
||||
|
||||
namespace boost {
|
||||
|
||||
//
|
||||
// Categories
|
||||
//
|
||||
// !! Fix detection functions if categories
|
||||
// are changed.
|
||||
//
|
||||
|
||||
// Return Type Categories
|
||||
struct readable_iterator_tag { };
|
||||
struct writable_iterator_tag { };
|
||||
@@ -199,16 +205,39 @@ namespace boost {
|
||||
//
|
||||
// Return type
|
||||
//
|
||||
// The nested is_category template class are used for
|
||||
// minimum category detection in iterator_adaptors.
|
||||
// They are basically a pore 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_c
|
||||
{};
|
||||
{
|
||||
template <class T>
|
||||
struct is_category
|
||||
: boost::mpl::false_c {};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_mutable_lvalue_iterator<mutable_lvalue_iterator_tag> :
|
||||
mpl::true_c
|
||||
{};
|
||||
{
|
||||
template <class Category>
|
||||
struct is_category
|
||||
: is_mutable_lvalue_iterator<Category> {};
|
||||
};
|
||||
|
||||
template <class Category>
|
||||
struct is_constant_lvalue_iterator :
|
||||
@@ -218,7 +247,11 @@ namespace boost {
|
||||
template <>
|
||||
struct is_constant_lvalue_iterator<constant_lvalue_iterator_tag> :
|
||||
mpl::true_c
|
||||
{};
|
||||
{
|
||||
template <class Category>
|
||||
struct is_category
|
||||
: is_constant_lvalue_iterator<Category> {};
|
||||
};
|
||||
|
||||
template <class Category>
|
||||
struct is_swappable_iterator :
|
||||
@@ -228,18 +261,27 @@ namespace boost {
|
||||
template <>
|
||||
struct is_swappable_iterator<swappable_iterator_tag> :
|
||||
mpl::true_c
|
||||
{};
|
||||
{
|
||||
template <class Category>
|
||||
struct is_category
|
||||
: is_swappable_iterator<Category> {};
|
||||
};
|
||||
|
||||
template <class Category>
|
||||
struct is_readable_iterator :
|
||||
mpl::logical_or< is_swappable_iterator<Category>,
|
||||
is_constant_lvalue_iterator<Category> >
|
||||
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_c
|
||||
{};
|
||||
{
|
||||
template <class Category>
|
||||
struct is_category
|
||||
: is_readable_iterator<Category> {};
|
||||
};
|
||||
|
||||
template <class Category>
|
||||
struct is_writable_iterator :
|
||||
@@ -249,7 +291,19 @@ namespace boost {
|
||||
template <>
|
||||
struct is_writable_iterator<writable_iterator_tag> :
|
||||
mpl::true_c
|
||||
{};
|
||||
{
|
||||
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
|
||||
@@ -258,12 +312,20 @@ namespace boost {
|
||||
template <class Category>
|
||||
struct is_random_access_traversal_iterator :
|
||||
mpl::false_c
|
||||
{};
|
||||
{
|
||||
template <class T>
|
||||
struct is_category
|
||||
: boost::mpl::false_c {};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_random_access_traversal_iterator<random_access_traversal_tag> :
|
||||
mpl::true_c
|
||||
{};
|
||||
{
|
||||
template <class Category>
|
||||
struct is_category
|
||||
: is_random_access_traversal_iterator<Category> {};
|
||||
};
|
||||
|
||||
template <class Category>
|
||||
struct is_bidirectional_traversal_iterator :
|
||||
@@ -273,7 +335,11 @@ namespace boost {
|
||||
template <>
|
||||
struct is_bidirectional_traversal_iterator<bidirectional_traversal_tag> :
|
||||
mpl::true_c
|
||||
{};
|
||||
{
|
||||
template <class Category>
|
||||
struct is_category
|
||||
: is_bidirectional_traversal_iterator<Category> {};
|
||||
};
|
||||
|
||||
template <class Category>
|
||||
struct is_forward_traversal_iterator :
|
||||
@@ -283,7 +349,11 @@ namespace boost {
|
||||
template <>
|
||||
struct is_forward_traversal_iterator<forward_traversal_tag> :
|
||||
mpl::true_c
|
||||
{};
|
||||
{
|
||||
template <class Category>
|
||||
struct is_category
|
||||
: is_forward_traversal_iterator<Category> {};
|
||||
};
|
||||
|
||||
template <class Category>
|
||||
struct is_input_traversal_iterator :
|
||||
@@ -293,7 +363,11 @@ namespace boost {
|
||||
template <>
|
||||
struct is_input_traversal_iterator<input_traversal_tag> :
|
||||
mpl::true_c
|
||||
{};
|
||||
{
|
||||
template <class Category>
|
||||
struct is_category
|
||||
: is_input_traversal_iterator<Category> {};
|
||||
};
|
||||
|
||||
template <class Category>
|
||||
struct is_output_traversal_iterator :
|
||||
@@ -303,6 +377,17 @@ namespace boost {
|
||||
template <>
|
||||
struct is_output_traversal_iterator<output_traversal_tag> :
|
||||
mpl::true_c
|
||||
{
|
||||
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
|
||||
|
@@ -149,6 +149,7 @@ namespace boost
|
||||
//
|
||||
struct enable_type;
|
||||
|
||||
#if 0
|
||||
// traits_iterator<It> has two important properties:
|
||||
//
|
||||
// 1. It is derived from boost::iterator<...>, which is
|
||||
@@ -172,6 +173,78 @@ namespace boost
|
||||
>
|
||||
{
|
||||
};
|
||||
#endif
|
||||
|
||||
template <class Traits>
|
||||
struct std_iterator_from_traits
|
||||
: iterator<
|
||||
typename Traits::iterator_category
|
||||
, typename Traits::value_type
|
||||
, typename Traits::difference_type
|
||||
, typename Traits::pointer
|
||||
, typename Traits::reference
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
//
|
||||
// I bet this is defined somewhere else. Let's wait and see.
|
||||
//
|
||||
struct error_type;
|
||||
|
||||
#ifdef BOOST_NO_IS_CONVERTIBLE
|
||||
template <class Cat1, class Cat2>
|
||||
struct minimum_return_category
|
||||
: mpl::if_< is_return_category< Cat1 >::template is_category< Cat2 >,
|
||||
Cat1,
|
||||
mpl::if_< is_return_category<Cat2>::template is_category<Cat1>,
|
||||
Cat2,
|
||||
error_type
|
||||
>
|
||||
> {};
|
||||
|
||||
template <class Cat1, class Cat2>
|
||||
struct minimum_traversal_category
|
||||
: mpl::if_< is_traversal_category< Cat1 >::template is_category< Cat2 >,
|
||||
Cat1,
|
||||
mpl::if_< is_traversal_category<Cat2>::template is_category<Cat1>,
|
||||
Cat2,
|
||||
error_type
|
||||
>
|
||||
> {};
|
||||
|
||||
template <class T1, class T2>
|
||||
struct minimum_category_select
|
||||
: mpl::if_< is_same< typename T1::type, error_type >,
|
||||
T2,
|
||||
T1 >
|
||||
{};
|
||||
#endif
|
||||
|
||||
//
|
||||
// Returns the minimum category type or error_type
|
||||
// if T1 and T2 are unrelated.
|
||||
//
|
||||
// For compilers not supporting is_convertible this only
|
||||
// works with the new boost return and traversal category
|
||||
// types. The exect boost _types_ are required. No derived types
|
||||
// will work.
|
||||
//
|
||||
//
|
||||
template <class T1, class T2>
|
||||
struct minimum_category :
|
||||
#ifndef BOOST_NO_IS_CONVERTIBLE
|
||||
// We may need a VC7.1 is_same shortcut here
|
||||
mpl::if_< is_base_and_derived< T1, T2 >,
|
||||
T1,
|
||||
mpl::if_< is_base_and_derived< T2, T1 >,
|
||||
T2,
|
||||
error_type > >
|
||||
#else
|
||||
minimum_category_select< minimum_return_category<T1, T2>,
|
||||
minimum_traversal_category<T1, T2> >
|
||||
#endif
|
||||
{};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -539,17 +612,25 @@ namespace boost
|
||||
lhs.derived());
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
// iterator_facade applies iterator_traits_adaptor to it's traits argument.
|
||||
// The net effect is that iterator_facade is derived from std::iterator. This
|
||||
// is important for standard library interoperability of iterator types on some
|
||||
// (broken) implementations.
|
||||
//
|
||||
template <
|
||||
class Derived
|
||||
, class Traits
|
||||
, class Super = iterator_arith<
|
||||
iterator_comparisons<
|
||||
downcastable<Derived, Traits> > >
|
||||
>
|
||||
class iterator_facade
|
||||
: public Super
|
||||
: public iterator_arith<
|
||||
iterator_comparisons<
|
||||
downcastable<Derived, detail::std_iterator_from_traits<Traits> > > >
|
||||
{
|
||||
typedef Super super_t;
|
||||
typedef iterator_arith<
|
||||
iterator_comparisons<
|
||||
downcastable<Derived, detail::std_iterator_from_traits<Traits> > > > super_t;
|
||||
public:
|
||||
typedef typename super_t::reference reference;
|
||||
typedef typename super_t::difference_type difference_type;
|
||||
@@ -604,13 +685,34 @@ namespace boost
|
||||
}
|
||||
|
||||
//
|
||||
// TODO Handle default arguments the same way as
|
||||
// in former ia lib
|
||||
// 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 creation of adapted iterator types. Therefore the ordering the template
|
||||
// argument ordering is different from the std::iterator template, so that default
|
||||
// arguments can be used effectivly.
|
||||
//
|
||||
template <class Iterator,
|
||||
class ValueType = typename detail::iterator_traits<Iterator>::value_type,
|
||||
class Reference = ValueType&,
|
||||
class Pointer = ValueType*,
|
||||
class IteratorCategory = typename detail::iterator_traits<Iterator>::iterator_category,
|
||||
class DifferenceType = typename detail::iterator_traits<Iterator>::difference_type >
|
||||
struct iterator_traits_adaptor
|
||||
: iterator<IteratorCategory,
|
||||
ValueType,
|
||||
DifferenceType,
|
||||
Pointer,
|
||||
Reference>
|
||||
{
|
||||
};
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
template <
|
||||
class Derived
|
||||
, class Iterator
|
||||
, class Traits = detail::traits_iterator<Iterator>
|
||||
, class Traits = detail::iterator_traits<Iterator>
|
||||
>
|
||||
class iterator_adaptor
|
||||
: public iterator_facade<Derived,Traits>
|
||||
@@ -630,6 +732,7 @@ namespace boost
|
||||
protected:
|
||||
// Core iterator interface for iterator_facade
|
||||
//
|
||||
|
||||
typename Traits::reference dereference() const { return *m_iterator; }
|
||||
|
||||
template <
|
||||
@@ -719,17 +822,15 @@ namespace boost
|
||||
// is the type used as its traits.
|
||||
template <class AdaptableUnaryFunction, class Iterator>
|
||||
struct transform_iterator_traits
|
||||
: iterator<
|
||||
typename detail::iterator_traits<Iterator>::iterator_category
|
||||
, typename AdaptableUnaryFunction::result_type
|
||||
, typename detail::iterator_traits<Iterator>::difference_type
|
||||
, typename AdaptableUnaryFunction::result_type*
|
||||
, typename AdaptableUnaryFunction::result_type
|
||||
>
|
||||
{};
|
||||
: iterator_traits_adaptor<Iterator
|
||||
,typename AdaptableUnaryFunction::result_type
|
||||
,typename AdaptableUnaryFunction::result_type
|
||||
,typename AdaptableUnaryFunction::result_type*
|
||||
,iterator_tag< readable_iterator_tag,
|
||||
typename traversal_category<Iterator>::type > >
|
||||
{
|
||||
};
|
||||
|
||||
//
|
||||
// TODO fix category
|
||||
//
|
||||
template <class AdaptableUnaryFunction, class Iterator>
|
||||
class transform_iterator
|
||||
@@ -847,13 +948,11 @@ namespace boost
|
||||
// is ultimately derived from boost::iterator<...>
|
||||
template <class Base, class Traits>
|
||||
struct indirect_traits
|
||||
: traits_iterator<
|
||||
typename mpl::if_<
|
||||
: mpl::if_<
|
||||
is_same<Traits,unspecified>
|
||||
, indirect_defaults<Base>
|
||||
, Traits
|
||||
>::type
|
||||
>
|
||||
{
|
||||
};
|
||||
} // namespace detail
|
||||
@@ -907,26 +1006,35 @@ namespace boost
|
||||
return indirect_iterator<Iter, Traits>(x);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <class Iterator>
|
||||
struct filter_iterator_traits
|
||||
: detail::iterator_traits<Iterator>
|
||||
: iterator_traits<Iterator>
|
||||
{
|
||||
#if !BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1300))
|
||||
BOOST_STATIC_ASSERT((detail::is_forward_traversal_iterator<
|
||||
typename traversal_category<Iterator>::type >::value));
|
||||
#endif
|
||||
|
||||
typedef iterator_tag<
|
||||
typename return_category<Iterator>::type
|
||||
, forward_traversal_tag
|
||||
> iterator_category;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class Predicate, class Iterator>
|
||||
class filter_iterator
|
||||
: public iterator_adaptor<
|
||||
filter_iterator<Predicate, Iterator>, Iterator
|
||||
, detail::traits_iterator<filter_iterator_traits<Iterator> >
|
||||
, detail::filter_iterator_traits<Iterator>
|
||||
>
|
||||
{
|
||||
typedef iterator_adaptor<
|
||||
filter_iterator<Predicate, Iterator>, Iterator
|
||||
, detail::traits_iterator<filter_iterator_traits<Iterator> >
|
||||
, detail::filter_iterator_traits<Iterator>
|
||||
> super_t;
|
||||
|
||||
friend class iterator_core_access;
|
||||
|
@@ -31,29 +31,6 @@
|
||||
|
||||
namespace boost {
|
||||
|
||||
// When creating new iterators, you have three options.
|
||||
|
||||
// 1) The recommended option is to specialize the return_category
|
||||
// and traversal_category for your iterator. However, if your
|
||||
// iterator is a templates, this will cause a problem on compilers
|
||||
// that do not have partial specialization.
|
||||
// 2) The second option is to put two nested typedefs in your
|
||||
// iterator, return_category and traversal_category, and derive your
|
||||
// iterator from new_iterator_base.
|
||||
// 3) The third option is the create your iterator in the old STL
|
||||
// style and let the backward compatibility parts of this header
|
||||
// handle the rest.
|
||||
|
||||
// BTW, if you choose one of the first two options, you can still
|
||||
// implement all the old-style iterator typedefs, they will not get
|
||||
// in the way of the new categories.
|
||||
|
||||
// Inherit from iterator_base if your iterator defines its own
|
||||
// return_category and traversal_category. Otherwise, the "old style"
|
||||
// iterator category will be mapped to the return_category and
|
||||
// traversal_category.
|
||||
struct new_iterator_base { };
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
@@ -303,8 +280,6 @@ namespace boost {
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#ifdef BOOST_NO_IS_CONVERTIBLE
|
||||
# undef BOOST_NO_IS_CONVERTIBLE
|
||||
#endif
|
||||
#undef BOOST_NO_IS_CONVERTIBLE
|
||||
|
||||
#endif // BOOST_ITERATOR_CATEGORIES_HPP
|
||||
|
@@ -40,12 +40,12 @@ int main()
|
||||
filter_iter(one_or_four(), array, array+N)
|
||||
, dummyT(1), dummyT(4));
|
||||
|
||||
# if 0
|
||||
//# if 0
|
||||
BOOST_STATIC_ASSERT(
|
||||
(!boost::detail::is_bidirectional_traversal_iterator<
|
||||
boost::traversal_category<filter_iter>::type
|
||||
>::value) );
|
||||
# endif
|
||||
//# endif
|
||||
|
||||
// On compilers not supporting partial specialization, we can do more type
|
||||
// deduction with deque iterators than with pointers... unless the library
|
||||
|
Reference in New Issue
Block a user