diff --git a/include/boost/iterator/detail/categories.hpp b/include/boost/iterator/detail/categories.hpp index 9055378..da8ed48 100644 --- a/include/boost/iterator/detail/categories.hpp +++ b/include/boost/iterator/detail/categories.hpp @@ -12,7 +12,6 @@ #include #include #include -#include #include #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 + // struct min_cat + // : mpl::if_< is_return_category< Cat1 >::template is_category< Cat2 >, + // Cat1, + // mpl::if_< is_return_category::template is_category, + // Cat2, + // error_type + // > + // > {}; template struct is_mutable_lvalue_iterator : mpl::false_c - {}; + { + template + struct is_category + : boost::mpl::false_c {}; + }; template <> struct is_mutable_lvalue_iterator : mpl::true_c - {}; + { + template + struct is_category + : is_mutable_lvalue_iterator {}; + }; template struct is_constant_lvalue_iterator : @@ -218,7 +247,11 @@ namespace boost { template <> struct is_constant_lvalue_iterator : mpl::true_c - {}; + { + template + struct is_category + : is_constant_lvalue_iterator {}; + }; template struct is_swappable_iterator : @@ -228,18 +261,27 @@ namespace boost { template <> struct is_swappable_iterator : mpl::true_c - {}; + { + template + struct is_category + : is_swappable_iterator {}; + }; template struct is_readable_iterator : - mpl::logical_or< is_swappable_iterator, - is_constant_lvalue_iterator > + mpl::if_< is_swappable_iterator, + is_swappable_iterator, + is_constant_lvalue_iterator >::type {}; template <> struct is_readable_iterator : mpl::true_c - {}; + { + template + struct is_category + : is_readable_iterator {}; + }; template struct is_writable_iterator : @@ -249,7 +291,19 @@ namespace boost { template <> struct is_writable_iterator : mpl::true_c - {}; + { + template + struct is_category + : is_writable_iterator {}; + }; + + template + struct is_return_category + : mpl::if_< is_writable_iterator, + is_writable_iterator, + is_readable_iterator >::type + { + }; // // Traversal @@ -258,12 +312,20 @@ namespace boost { template struct is_random_access_traversal_iterator : mpl::false_c - {}; + { + template + struct is_category + : boost::mpl::false_c {}; + }; template <> struct is_random_access_traversal_iterator : mpl::true_c - {}; + { + template + struct is_category + : is_random_access_traversal_iterator {}; + }; template struct is_bidirectional_traversal_iterator : @@ -273,7 +335,11 @@ namespace boost { template <> struct is_bidirectional_traversal_iterator : mpl::true_c - {}; + { + template + struct is_category + : is_bidirectional_traversal_iterator {}; + }; template struct is_forward_traversal_iterator : @@ -283,7 +349,11 @@ namespace boost { template <> struct is_forward_traversal_iterator : mpl::true_c - {}; + { + template + struct is_category + : is_forward_traversal_iterator {}; + }; template struct is_input_traversal_iterator : @@ -293,7 +363,11 @@ namespace boost { template <> struct is_input_traversal_iterator : mpl::true_c - {}; + { + template + struct is_category + : is_input_traversal_iterator {}; + }; template struct is_output_traversal_iterator : @@ -303,6 +377,17 @@ namespace boost { template <> struct is_output_traversal_iterator : mpl::true_c + { + template + struct is_category + : is_output_traversal_iterator {}; + }; + + template + struct is_traversal_category + : mpl::if_< is_input_traversal_iterator, + is_input_traversal_iterator, + is_output_traversal_iterator >::type {}; #endif diff --git a/include/boost/iterator/iterator_adaptors.hpp b/include/boost/iterator/iterator_adaptors.hpp index 8269d91..ab89f80 100644 --- a/include/boost/iterator/iterator_adaptors.hpp +++ b/include/boost/iterator/iterator_adaptors.hpp @@ -149,6 +149,7 @@ namespace boost // struct enable_type; +#if 0 // traits_iterator has two important properties: // // 1. It is derived from boost::iterator<...>, which is @@ -172,7 +173,79 @@ namespace boost > { }; +#endif + template + 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 + struct minimum_return_category + : mpl::if_< is_return_category< Cat1 >::template is_category< Cat2 >, + Cat1, + mpl::if_< is_return_category::template is_category, + Cat2, + error_type + > + > {}; + + template + struct minimum_traversal_category + : mpl::if_< is_traversal_category< Cat1 >::template is_category< Cat2 >, + Cat1, + mpl::if_< is_traversal_category::template is_category, + Cat2, + error_type + > + > {}; + + template + 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 + 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, + minimum_traversal_category > +#endif + {}; + } // namespace detail // @@ -539,21 +612,29 @@ 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 > > > class iterator_facade - : public Super + : public iterator_arith< + iterator_comparisons< + downcastable > > > { - typedef Super super_t; + typedef iterator_arith< + iterator_comparisons< + downcastable > > > super_t; public: typedef typename super_t::reference reference; typedef typename super_t::difference_type difference_type; - typedef typename super_t::pointer pointer; + typedef typename super_t::pointer pointer; reference operator*() const { return iterator_core_access::dereference(this->derived()); } @@ -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 ::value_type, + class Reference = ValueType&, + class Pointer = ValueType*, + class IteratorCategory = typename detail::iterator_traits::iterator_category, + class DifferenceType = typename detail::iterator_traits::difference_type > + struct iterator_traits_adaptor + : iterator + { + }; + + // + // // template < class Derived , class Iterator - , class Traits = detail::traits_iterator + , class Traits = detail::iterator_traits > class iterator_adaptor : public iterator_facade @@ -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 struct transform_iterator_traits - : iterator< - typename detail::iterator_traits::iterator_category - , typename AdaptableUnaryFunction::result_type - , typename detail::iterator_traits::difference_type - , typename AdaptableUnaryFunction::result_type* - , typename AdaptableUnaryFunction::result_type - > - {}; + : iterator_traits_adaptor::type > > + { + }; - // - // TODO fix category // template class transform_iterator @@ -847,13 +948,11 @@ namespace boost // is ultimately derived from boost::iterator<...> template struct indirect_traits - : traits_iterator< - typename mpl::if_< - is_same + : mpl::if_< + is_same , indirect_defaults , Traits >::type - > { }; } // namespace detail @@ -907,26 +1006,35 @@ namespace boost return indirect_iterator(x); } - template - struct filter_iterator_traits - : detail::iterator_traits - { + namespace detail { + + template + struct filter_iterator_traits + : iterator_traits + { +#if !BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1300)) + BOOST_STATIC_ASSERT((detail::is_forward_traversal_iterator< + typename traversal_category::type >::value)); +#endif + typedef iterator_tag< - typename return_category::type - , forward_traversal_tag - > iterator_category; - }; + typename return_category::type + , forward_traversal_tag + > iterator_category; + }; + + } // namespace detail template class filter_iterator : public iterator_adaptor< filter_iterator, Iterator - , detail::traits_iterator > + , detail::filter_iterator_traits > { typedef iterator_adaptor< filter_iterator, Iterator - , detail::traits_iterator > + , detail::filter_iterator_traits > super_t; friend class iterator_core_access; diff --git a/include/boost/iterator/iterator_categories.hpp b/include/boost/iterator/iterator_categories.hpp index 16bab94..2f12818 100644 --- a/include/boost/iterator/iterator_categories.hpp +++ b/include/boost/iterator/iterator_categories.hpp @@ -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 diff --git a/test/filter_iterator_test.cpp b/test/filter_iterator_test.cpp index 8eb0082..b1f285d 100644 --- a/test/filter_iterator_test.cpp +++ b/test/filter_iterator_test.cpp @@ -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::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