diff --git a/include/boost/iterator/detail/categories.hpp b/include/boost/iterator/detail/categories.hpp index 48d1e3d..2e53fb6 100644 --- a/include/boost/iterator/detail/categories.hpp +++ b/include/boost/iterator/detail/categories.hpp @@ -329,6 +329,25 @@ namespace boost template <> struct minimum_category { typedef minimum_category type; }; # endif + // + // Tag classification for use in iterator_adaptor + // + template + struct is_access_tag + : mpl::or_< + is_tag + , mpl::or_< + is_tag + , is_tag + > + > + {}; + + template + struct is_traversal_tag + : is_tag + {}; + } // namespace detail } // namespace boost diff --git a/include/boost/iterator/filter_iterator.hpp b/include/boost/iterator/filter_iterator.hpp index 390dc8e..cd490dc 100644 --- a/include/boost/iterator/filter_iterator.hpp +++ b/include/boost/iterator/filter_iterator.hpp @@ -15,34 +15,25 @@ namespace boost { - namespace detail - { - template - struct filter_iterator_category - { - typedef iterator_tag< - typename access_category::type - , typename minimum_category< - bidirectional_traversal_tag - , typename traversal_category::type - >::type - > type; - }; - - } // namespace detail template class filter_iterator : public iterator_adaptor< filter_iterator, Iterator , use_default - , typename detail::filter_iterator_category::type + , typename detail::minimum_category< + bidirectional_traversal_tag + , typename traversal_category::type + >::type > { typedef iterator_adaptor< filter_iterator, Iterator , use_default - , typename detail::filter_iterator_category::type + , typename detail::minimum_category< + bidirectional_traversal_tag + , typename traversal_category::type + >::type > super_t; friend class iterator_core_access; diff --git a/include/boost/iterator/iterator_adaptor.hpp b/include/boost/iterator/iterator_adaptor.hpp index faecc1a..af14283 100644 --- a/include/boost/iterator/iterator_adaptor.hpp +++ b/include/boost/iterator/iterator_adaptor.hpp @@ -148,9 +148,18 @@ namespace boost > struct iterator_adaptor_base { - private: // intermediate results - typedef typename detail::ia_dflt_help< - Category, BOOST_ITERATOR_CATEGORY + private: // intermediate results + + typedef typename mpl::apply_if< + mpl::or_< + is_same + , mpl::or_< + is_access_tag + , is_traversal_tag + > + > + , BOOST_ITERATOR_CATEGORY + , mpl::identity >::type category; typedef typename detail::ia_dflt_help< @@ -170,9 +179,17 @@ namespace boost Value, iterator_value >::type - , typename access_category_tag::type - - , typename traversal_category_tag::type + , typename mpl::apply_if< + is_access_tag + , mpl::identity + , access_category_tag + >::type + + , typename mpl::apply_if< + is_traversal_tag + , mpl::identity + , traversal_category_tag + >::type , reference diff --git a/include/boost/iterator/transform_iterator.hpp b/include/boost/iterator/transform_iterator.hpp index f281b82..cb41f07 100644 --- a/include/boost/iterator/transform_iterator.hpp +++ b/include/boost/iterator/transform_iterator.hpp @@ -90,10 +90,7 @@ namespace boost transform_iterator , Iterator , cv_value_type - , iterator_tag< - access_category - , typename traversal_category::type - > + , access_category , result_type > type; }; diff --git a/test/iterator_adaptor_test.cpp b/test/iterator_adaptor_test.cpp index 32edd85..5c471d7 100644 --- a/test/iterator_adaptor_test.cpp +++ b/test/iterator_adaptor_test.cpp @@ -112,6 +112,17 @@ public: {} }; +// Non-functional iterator for category modification checking +template +struct modify_category + : boost::iterator_adaptor< + modify_category + , Iter + , boost::use_default + , Category + > +{}; + template struct fwd_iterator : boost::iterator_adaptor< @@ -221,6 +232,15 @@ main() test = static_assert_same::value; test = static_assert_same::value; + + // Test category modification + typedef modify_category ReadableIter; + test = static_assert_same::value; + + typedef modify_category IncrementableIter; + test = static_assert_same::value; + test = static_assert_same::value; + } // Test the iterator_adaptor diff --git a/test/unit_tests.cpp b/test/unit_tests.cpp index 4887357..622d9a7 100644 --- a/test/unit_tests.cpp +++ b/test/unit_tests.cpp @@ -91,6 +91,25 @@ void category_test() std::output_iterator_tag,std::random_access_iterator_tag, std::output_iterator_tag >::value; + BOOST_STATIC_ASSERT((is_traversal_tag< incrementable_traversal_tag >::value)); + BOOST_STATIC_ASSERT((is_traversal_tag< single_pass_traversal_tag >::value)); + BOOST_STATIC_ASSERT((is_traversal_tag< forward_traversal_tag >::value)); + BOOST_STATIC_ASSERT((is_traversal_tag< bidirectional_traversal_tag >::value)); + BOOST_STATIC_ASSERT((is_traversal_tag< random_access_traversal_tag >::value)); + + BOOST_STATIC_ASSERT((!is_traversal_tag< std::input_iterator_tag >::value)); + BOOST_STATIC_ASSERT((!is_traversal_tag< readable_iterator_tag >::value)); + + BOOST_STATIC_ASSERT((is_access_tag< readable_iterator_tag >::value)); + BOOST_STATIC_ASSERT((is_access_tag< writable_iterator_tag >::value)); + BOOST_STATIC_ASSERT((is_access_tag< swappable_iterator_tag >::value)); + BOOST_STATIC_ASSERT((is_access_tag< readable_writable_iterator_tag >::value)); + BOOST_STATIC_ASSERT((is_access_tag< readable_lvalue_iterator_tag >::value)); + BOOST_STATIC_ASSERT((is_access_tag< writable_lvalue_iterator_tag >::value)); + + BOOST_STATIC_ASSERT((!is_access_tag< std::input_iterator_tag >::value)); + BOOST_STATIC_ASSERT((!is_access_tag< incrementable_traversal_tag >::value)); + (void)test; }