Added iterator_traits_adaptor.

Implemented minimum_category.
Removed base class injection facilities.


[SVN r879]
This commit is contained in:
Thomas Witt
2003-01-27 20:41:09 +00:00
parent 7818686c94
commit 4e63c5e8dc
4 changed files with 243 additions and 75 deletions

View File

@@ -12,7 +12,6 @@
#include <boost/type_traits/conversion_traits.hpp> #include <boost/type_traits/conversion_traits.hpp>
#include <boost/mpl/if.hpp> #include <boost/mpl/if.hpp>
#include <boost/mpl/bool_c.hpp> #include <boost/mpl/bool_c.hpp>
#include <boost/mpl/logical/or.hpp>
#include <iterator> #include <iterator>
#if BOOST_WORKAROUND(__MWERKS__, <=0x2407) #if BOOST_WORKAROUND(__MWERKS__, <=0x2407)
@@ -21,6 +20,13 @@
namespace boost { namespace boost {
//
// Categories
//
// !! Fix detection functions if categories
// are changed.
//
// Return Type Categories // Return Type Categories
struct readable_iterator_tag { }; struct readable_iterator_tag { };
struct writable_iterator_tag { }; struct writable_iterator_tag { };
@@ -199,16 +205,39 @@ namespace boost {
// //
// Return type // 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> template <class Category>
struct is_mutable_lvalue_iterator : struct is_mutable_lvalue_iterator :
mpl::false_c mpl::false_c
{}; {
template <class T>
struct is_category
: boost::mpl::false_c {};
};
template <> template <>
struct is_mutable_lvalue_iterator<mutable_lvalue_iterator_tag> : struct is_mutable_lvalue_iterator<mutable_lvalue_iterator_tag> :
mpl::true_c mpl::true_c
{}; {
template <class Category>
struct is_category
: is_mutable_lvalue_iterator<Category> {};
};
template <class Category> template <class Category>
struct is_constant_lvalue_iterator : struct is_constant_lvalue_iterator :
@@ -218,7 +247,11 @@ namespace boost {
template <> template <>
struct is_constant_lvalue_iterator<constant_lvalue_iterator_tag> : struct is_constant_lvalue_iterator<constant_lvalue_iterator_tag> :
mpl::true_c mpl::true_c
{}; {
template <class Category>
struct is_category
: is_constant_lvalue_iterator<Category> {};
};
template <class Category> template <class Category>
struct is_swappable_iterator : struct is_swappable_iterator :
@@ -228,18 +261,27 @@ namespace boost {
template <> template <>
struct is_swappable_iterator<swappable_iterator_tag> : struct is_swappable_iterator<swappable_iterator_tag> :
mpl::true_c mpl::true_c
{}; {
template <class Category>
struct is_category
: is_swappable_iterator<Category> {};
};
template <class Category> template <class Category>
struct is_readable_iterator : struct is_readable_iterator :
mpl::logical_or< is_swappable_iterator<Category>, mpl::if_< is_swappable_iterator<Category>,
is_constant_lvalue_iterator<Category> > is_swappable_iterator<Category>,
is_constant_lvalue_iterator<Category> >::type
{}; {};
template <> template <>
struct is_readable_iterator<readable_iterator_tag> : struct is_readable_iterator<readable_iterator_tag> :
mpl::true_c mpl::true_c
{}; {
template <class Category>
struct is_category
: is_readable_iterator<Category> {};
};
template <class Category> template <class Category>
struct is_writable_iterator : struct is_writable_iterator :
@@ -249,7 +291,19 @@ namespace boost {
template <> template <>
struct is_writable_iterator<writable_iterator_tag> : struct is_writable_iterator<writable_iterator_tag> :
mpl::true_c 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 // Traversal
@@ -258,12 +312,20 @@ namespace boost {
template <class Category> template <class Category>
struct is_random_access_traversal_iterator : struct is_random_access_traversal_iterator :
mpl::false_c mpl::false_c
{}; {
template <class T>
struct is_category
: boost::mpl::false_c {};
};
template <> template <>
struct is_random_access_traversal_iterator<random_access_traversal_tag> : struct is_random_access_traversal_iterator<random_access_traversal_tag> :
mpl::true_c mpl::true_c
{}; {
template <class Category>
struct is_category
: is_random_access_traversal_iterator<Category> {};
};
template <class Category> template <class Category>
struct is_bidirectional_traversal_iterator : struct is_bidirectional_traversal_iterator :
@@ -273,7 +335,11 @@ namespace boost {
template <> template <>
struct is_bidirectional_traversal_iterator<bidirectional_traversal_tag> : struct is_bidirectional_traversal_iterator<bidirectional_traversal_tag> :
mpl::true_c mpl::true_c
{}; {
template <class Category>
struct is_category
: is_bidirectional_traversal_iterator<Category> {};
};
template <class Category> template <class Category>
struct is_forward_traversal_iterator : struct is_forward_traversal_iterator :
@@ -283,7 +349,11 @@ namespace boost {
template <> template <>
struct is_forward_traversal_iterator<forward_traversal_tag> : struct is_forward_traversal_iterator<forward_traversal_tag> :
mpl::true_c mpl::true_c
{}; {
template <class Category>
struct is_category
: is_forward_traversal_iterator<Category> {};
};
template <class Category> template <class Category>
struct is_input_traversal_iterator : struct is_input_traversal_iterator :
@@ -293,7 +363,11 @@ namespace boost {
template <> template <>
struct is_input_traversal_iterator<input_traversal_tag> : struct is_input_traversal_iterator<input_traversal_tag> :
mpl::true_c mpl::true_c
{}; {
template <class Category>
struct is_category
: is_input_traversal_iterator<Category> {};
};
template <class Category> template <class Category>
struct is_output_traversal_iterator : struct is_output_traversal_iterator :
@@ -303,6 +377,17 @@ namespace boost {
template <> template <>
struct is_output_traversal_iterator<output_traversal_tag> : struct is_output_traversal_iterator<output_traversal_tag> :
mpl::true_c 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 #endif

View File

@@ -149,6 +149,7 @@ namespace boost
// //
struct enable_type; struct enable_type;
#if 0
// traits_iterator<It> has two important properties: // traits_iterator<It> has two important properties:
// //
// 1. It is derived from boost::iterator<...>, which is // 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 } // namespace detail
@@ -539,21 +612,29 @@ namespace boost
lhs.derived()); 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 < template <
class Derived class Derived
, class Traits , class Traits
, class Super = iterator_arith<
iterator_comparisons<
downcastable<Derived, Traits> > >
> >
class iterator_facade 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: public:
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;
reference operator*() const reference operator*() const
{ return iterator_core_access::dereference(this->derived()); } { return iterator_core_access::dereference(this->derived()); }
@@ -604,13 +685,34 @@ namespace boost
} }
// //
// TODO Handle default arguments the same way as // iterator_traits_adaptor can be used to create new iterator traits by adapting
// in former ia lib // 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 < template <
class Derived class Derived
, class Iterator , class Iterator
, class Traits = detail::traits_iterator<Iterator> , class Traits = detail::iterator_traits<Iterator>
> >
class iterator_adaptor class iterator_adaptor
: public iterator_facade<Derived,Traits> : public iterator_facade<Derived,Traits>
@@ -630,6 +732,7 @@ namespace boost
protected: protected:
// Core iterator interface for iterator_facade // Core iterator interface for iterator_facade
// //
typename Traits::reference dereference() const { return *m_iterator; } typename Traits::reference dereference() const { return *m_iterator; }
template < template <
@@ -719,17 +822,15 @@ namespace boost
// 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_traits
: iterator< : iterator_traits_adaptor<Iterator
typename detail::iterator_traits<Iterator>::iterator_category ,typename AdaptableUnaryFunction::result_type
, typename AdaptableUnaryFunction::result_type ,typename AdaptableUnaryFunction::result_type
, typename detail::iterator_traits<Iterator>::difference_type ,typename AdaptableUnaryFunction::result_type*
, typename AdaptableUnaryFunction::result_type* ,iterator_tag< readable_iterator_tag,
, typename AdaptableUnaryFunction::result_type typename traversal_category<Iterator>::type > >
> {
{}; };
//
// TODO fix category
// //
template <class AdaptableUnaryFunction, class Iterator> template <class AdaptableUnaryFunction, class Iterator>
class transform_iterator class transform_iterator
@@ -847,13 +948,11 @@ namespace boost
// is ultimately derived from boost::iterator<...> // is ultimately derived from boost::iterator<...>
template <class Base, class Traits> template <class Base, class Traits>
struct indirect_traits struct indirect_traits
: traits_iterator< : mpl::if_<
typename mpl::if_< is_same<Traits,unspecified>
is_same<Traits,unspecified>
, indirect_defaults<Base> , indirect_defaults<Base>
, Traits , Traits
>::type >::type
>
{ {
}; };
} // namespace detail } // namespace detail
@@ -907,26 +1006,35 @@ namespace boost
return indirect_iterator<Iter, Traits>(x); return indirect_iterator<Iter, Traits>(x);
} }
template <class Iterator> namespace detail {
struct filter_iterator_traits
: detail::iterator_traits<Iterator> template <class Iterator>
{ struct filter_iterator_traits
: 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< typedef iterator_tag<
typename return_category<Iterator>::type typename return_category<Iterator>::type
, forward_traversal_tag , forward_traversal_tag
> iterator_category; > iterator_category;
}; };
} // namespace detail
template <class Predicate, class Iterator> template <class Predicate, class Iterator>
class filter_iterator class filter_iterator
: public iterator_adaptor< : public iterator_adaptor<
filter_iterator<Predicate, Iterator>, Iterator filter_iterator<Predicate, Iterator>, Iterator
, detail::traits_iterator<filter_iterator_traits<Iterator> > , detail::filter_iterator_traits<Iterator>
> >
{ {
typedef iterator_adaptor< typedef iterator_adaptor<
filter_iterator<Predicate, Iterator>, Iterator filter_iterator<Predicate, Iterator>, Iterator
, detail::traits_iterator<filter_iterator_traits<Iterator> > , detail::filter_iterator_traits<Iterator>
> super_t; > super_t;
friend class iterator_core_access; friend class iterator_core_access;

View File

@@ -31,29 +31,6 @@
namespace boost { 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 namespace detail
{ {
@@ -303,8 +280,6 @@ namespace boost {
} // namespace boost } // namespace boost
#ifdef BOOST_NO_IS_CONVERTIBLE #undef BOOST_NO_IS_CONVERTIBLE
# undef BOOST_NO_IS_CONVERTIBLE
#endif
#endif // BOOST_ITERATOR_CATEGORIES_HPP #endif // BOOST_ITERATOR_CATEGORIES_HPP

View File

@@ -40,12 +40,12 @@ int main()
filter_iter(one_or_four(), array, array+N) filter_iter(one_or_four(), array, array+N)
, dummyT(1), dummyT(4)); , dummyT(1), dummyT(4));
# if 0 //# if 0
BOOST_STATIC_ASSERT( BOOST_STATIC_ASSERT(
(!boost::detail::is_bidirectional_traversal_iterator< (!boost::detail::is_bidirectional_traversal_iterator<
boost::traversal_category<filter_iter>::type boost::traversal_category<filter_iter>::type
>::value) ); >::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
// deduction with deque iterators than with pointers... unless the library // deduction with deque iterators than with pointers... unless the library