From 810b58cfb0eb5a5dd89641c7e88ea12f22ef2d83 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sat, 19 Jul 2014 20:57:42 +0400 Subject: [PATCH 1/6] Moved pure_traversal_tag to public namespace. Also added an import into the boost::detail namespace for backward compatibility with Boost.Range. Added a pure_iterator_traversal metafunction that automatically converts iterator category as well. --- .../boost/iterator/iterator_categories.hpp | 85 +++++++++++++------ include/boost/iterator/iterator_concepts.hpp | 15 +--- test/zip_iterator_test.cpp | 7 -- 3 files changed, 61 insertions(+), 46 deletions(-) diff --git a/include/boost/iterator/iterator_categories.hpp b/include/boost/iterator/iterator_categories.hpp index 20baf6d..71202c9 100644 --- a/include/boost/iterator/iterator_categories.hpp +++ b/include/boost/iterator/iterator_categories.hpp @@ -98,35 +98,8 @@ namespace detail > {}; - template - struct pure_traversal_tag - : mpl::eval_if< - is_convertible - , mpl::identity - , mpl::eval_if< - is_convertible - , mpl::identity - , mpl::eval_if< - is_convertible - , mpl::identity - , mpl::eval_if< - is_convertible - , mpl::identity - , mpl::eval_if< - is_convertible - , mpl::identity - , void - > - > - > - > - > - { - }; - } // namespace detail - // // Convert an iterator category into a traversal tag // @@ -166,6 +139,57 @@ struct iterator_traversal {}; # endif +// +// Convert an iterator traversal to one of the traversal tags. +// +template +struct pure_traversal_tag + : mpl::eval_if< + is_convertible + , mpl::identity + , mpl::eval_if< + is_convertible + , mpl::identity + , mpl::eval_if< + is_convertible + , mpl::identity + , mpl::eval_if< + is_convertible + , mpl::identity + , mpl::eval_if< + is_convertible + , mpl::identity + , void + > + > + > + > + > +{ +}; + +// +// Trait to retrieve one of the iterator traversal tags from the iterator category or traversal. +// +template +struct pure_iterator_traversal + : pure_traversal_tag::type> +{}; + +# ifdef BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT +template <> +struct pure_iterator_traversal +{ + template + struct apply : pure_iterator_traversal + {}; +}; +template <> +struct pure_iterator_traversal + : pure_iterator_traversal +{}; +# endif + } // namespace iterators using iterators::no_traversal_tag; @@ -177,6 +201,13 @@ using iterators::random_access_traversal_tag; using iterators::iterator_category_to_traversal; using iterators::iterator_traversal; +// This import is needed for backward compatibility with Boost.Range: +// boost/range/detail/demote_iterator_traversal_tag.hpp +// It should be removed when that header is fixed. +namespace detail { +using iterators::pure_traversal_tag; +} // namespace detail + } // namespace boost #include diff --git a/include/boost/iterator/iterator_concepts.hpp b/include/boost/iterator/iterator_concepts.hpp index ae6c4b3..1a9f7d6 100644 --- a/include/boost/iterator/iterator_concepts.hpp +++ b/include/boost/iterator/iterator_concepts.hpp @@ -248,19 +248,10 @@ namespace boost_concepts BOOST_concept(InteroperableIterator,(Iterator)(ConstIterator)) { private: - typedef typename boost::iterators::detail::pure_traversal_tag< - typename boost::iterator_traversal< - Iterator - >::type - >::type traversal_category; + typedef typename boost::iterators::pure_iterator_traversal::type traversal_category; + typedef typename boost::iterators::pure_iterator_traversal::type const_traversal_category; - typedef typename boost::iterators::detail::pure_traversal_tag< - typename boost::iterator_traversal< - ConstIterator - >::type - >::type const_traversal_category; - - public: + public: BOOST_CONCEPT_ASSERT((SinglePassIterator)); BOOST_CONCEPT_ASSERT((SinglePassIterator)); diff --git a/test/zip_iterator_test.cpp b/test/zip_iterator_test.cpp index fd7628f..b508098 100644 --- a/test/zip_iterator_test.cpp +++ b/test/zip_iterator_test.cpp @@ -55,13 +55,6 @@ #include #include -template -struct pure_traversal - : boost::iterators::detail::pure_traversal_tag< - typename boost::iterator_traversal::type - > -{}; - /// Tests for https://svn.boost.org/trac/boost/ticket/1517 int to_value(int const &v) From 8fe632d6b14e8fc2f5d7979c62db7845706cc838 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sat, 19 Jul 2014 21:03:11 +0400 Subject: [PATCH 2/6] Copied minimum_category.hpp to public headers. --- .../iterator/detail/minimum_category.hpp | 90 +-------------- include/boost/iterator/minimum_category.hpp | 103 ++++++++++++++++++ 2 files changed, 106 insertions(+), 87 deletions(-) create mode 100644 include/boost/iterator/minimum_category.hpp diff --git a/include/boost/iterator/detail/minimum_category.hpp b/include/boost/iterator/detail/minimum_category.hpp index 68a41a5..cd10601 100644 --- a/include/boost/iterator/detail/minimum_category.hpp +++ b/include/boost/iterator/detail/minimum_category.hpp @@ -4,96 +4,12 @@ #ifndef MINIMUM_CATEGORY_DWA20031119_HPP # define MINIMUM_CATEGORY_DWA20031119_HPP -# include -# include - -# include +# include namespace boost { -namespace iterators { -namespace detail { -// -// 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 exact boost _types_ are required. No derived types -// will work. -// -// -template -struct minimum_category_impl; -template -struct error_not_related_by_convertibility; - -template <> -struct minimum_category_impl -{ - template struct apply - { - typedef T2 type; - }; -}; - -template <> -struct minimum_category_impl -{ - template struct apply - { - typedef T1 type; - }; -}; - -template <> -struct minimum_category_impl -{ - template struct apply - { - BOOST_STATIC_ASSERT((is_same::value)); - typedef T1 type; - }; -}; - -template <> -struct minimum_category_impl -{ - template struct apply - : error_not_related_by_convertibility - { - }; -}; - -template -struct minimum_category -{ - typedef minimum_category_impl< - ::boost::is_convertible::value - , ::boost::is_convertible::value - > outer; - - typedef typename outer::template apply inner; - typedef typename inner::type type; - - BOOST_MPL_AUX_LAMBDA_SUPPORT(2,minimum_category,(T1,T2)) -}; - -template <> -struct minimum_category -{ - template - struct apply : minimum_category - {}; - - BOOST_MPL_AUX_LAMBDA_SUPPORT_SPEC(2,minimum_category,(mpl::_1,mpl::_2)) -}; - -} // namespace detail -} // namespace iterators - -// This import below is for backward compatibility with boost/token_iterator.hpp. -// It should be removed as soon as that header is fixed. +// This import below (as well as the whole header) is for backward compatibility +// with boost/token_iterator.hpp. It should be removed as soon as that header is fixed. namespace detail { using iterators::detail::minimum_category; } // namespace detail diff --git a/include/boost/iterator/minimum_category.hpp b/include/boost/iterator/minimum_category.hpp new file mode 100644 index 0000000..68a41a5 --- /dev/null +++ b/include/boost/iterator/minimum_category.hpp @@ -0,0 +1,103 @@ +// Copyright David Abrahams 2003. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef MINIMUM_CATEGORY_DWA20031119_HPP +# define MINIMUM_CATEGORY_DWA20031119_HPP + +# include +# include + +# include + +namespace boost { +namespace iterators { +namespace detail { +// +// 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 exact boost _types_ are required. No derived types +// will work. +// +// +template +struct minimum_category_impl; + +template +struct error_not_related_by_convertibility; + +template <> +struct minimum_category_impl +{ + template struct apply + { + typedef T2 type; + }; +}; + +template <> +struct minimum_category_impl +{ + template struct apply + { + typedef T1 type; + }; +}; + +template <> +struct minimum_category_impl +{ + template struct apply + { + BOOST_STATIC_ASSERT((is_same::value)); + typedef T1 type; + }; +}; + +template <> +struct minimum_category_impl +{ + template struct apply + : error_not_related_by_convertibility + { + }; +}; + +template +struct minimum_category +{ + typedef minimum_category_impl< + ::boost::is_convertible::value + , ::boost::is_convertible::value + > outer; + + typedef typename outer::template apply inner; + typedef typename inner::type type; + + BOOST_MPL_AUX_LAMBDA_SUPPORT(2,minimum_category,(T1,T2)) +}; + +template <> +struct minimum_category +{ + template + struct apply : minimum_category + {}; + + BOOST_MPL_AUX_LAMBDA_SUPPORT_SPEC(2,minimum_category,(mpl::_1,mpl::_2)) +}; + +} // namespace detail +} // namespace iterators + +// This import below is for backward compatibility with boost/token_iterator.hpp. +// It should be removed as soon as that header is fixed. +namespace detail { +using iterators::detail::minimum_category; +} // namespace detail + +} // namespace boost + +#endif // MINIMUM_CATEGORY_DWA20031119_HPP From f158dba6ad5dff424495d1518152034d6ac74db1 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sat, 19 Jul 2014 21:39:49 +0400 Subject: [PATCH 3/6] Moved minimum_category to the public namespace. Added tests. --- .../iterator/detail/minimum_category.hpp | 2 +- include/boost/iterator/minimum_category.hpp | 36 ++++++++----------- include/boost/iterator/zip_iterator.hpp | 2 +- test/Jamfile.v2 | 23 ++++++------ test/minimum_category.cpp | 22 ++++++++++++ test/minimum_category_compile_fail.cpp | 19 ++++++++++ test/unit_tests.cpp | 4 +-- 7 files changed, 72 insertions(+), 36 deletions(-) create mode 100644 test/minimum_category.cpp create mode 100644 test/minimum_category_compile_fail.cpp diff --git a/include/boost/iterator/detail/minimum_category.hpp b/include/boost/iterator/detail/minimum_category.hpp index cd10601..748c0d3 100644 --- a/include/boost/iterator/detail/minimum_category.hpp +++ b/include/boost/iterator/detail/minimum_category.hpp @@ -11,7 +11,7 @@ namespace boost { // This import below (as well as the whole header) is for backward compatibility // with boost/token_iterator.hpp. It should be removed as soon as that header is fixed. namespace detail { -using iterators::detail::minimum_category; +using iterators::minimum_category; } // namespace detail } // namespace boost diff --git a/include/boost/iterator/minimum_category.hpp b/include/boost/iterator/minimum_category.hpp index 68a41a5..15679bc 100644 --- a/include/boost/iterator/minimum_category.hpp +++ b/include/boost/iterator/minimum_category.hpp @@ -1,27 +1,20 @@ // Copyright David Abrahams 2003. Use, modification and distribution is // subject to the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -#ifndef MINIMUM_CATEGORY_DWA20031119_HPP -# define MINIMUM_CATEGORY_DWA20031119_HPP +#ifndef BOOST_ITERATOR_MINIMUM_CATEGORY_HPP_INCLUDED_ +# define BOOST_ITERATOR_MINIMUM_CATEGORY_HPP_INCLUDED_ +# include # include # include +# include # include namespace boost { namespace iterators { namespace detail { -// -// 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 exact boost _types_ are required. No derived types -// will work. -// -// + template struct minimum_category_impl; @@ -60,15 +53,21 @@ template <> struct minimum_category_impl { template struct apply - : error_not_related_by_convertibility + : error_not_related_by_convertibility { }; }; +} // namespace detail + +// +// Returns the minimum category type or fails to compile +// if T1 and T2 are unrelated. +// template struct minimum_category { - typedef minimum_category_impl< + typedef boost::iterators::detail::minimum_category_impl< ::boost::is_convertible::value , ::boost::is_convertible::value > outer; @@ -89,15 +88,8 @@ struct minimum_category BOOST_MPL_AUX_LAMBDA_SUPPORT_SPEC(2,minimum_category,(mpl::_1,mpl::_2)) }; -} // namespace detail } // namespace iterators -// This import below is for backward compatibility with boost/token_iterator.hpp. -// It should be removed as soon as that header is fixed. -namespace detail { -using iterators::detail::minimum_category; -} // namespace detail - } // namespace boost -#endif // MINIMUM_CATEGORY_DWA20031119_HPP +#endif // BOOST_ITERATOR_MINIMUM_CATEGORY_HPP_INCLUDED_ diff --git a/include/boost/iterator/zip_iterator.hpp b/include/boost/iterator/zip_iterator.hpp index fbbc1e7..304f65e 100644 --- a/include/boost/iterator/zip_iterator.hpp +++ b/include/boost/iterator/zip_iterator.hpp @@ -14,7 +14,7 @@ #include #include -#include +#include #include diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 6230469..b187835 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -3,28 +3,28 @@ # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) test-suite iterator - : + : # These first two tests will run last, and are expected to fail # for many less-capable compilers. - + [ compile-fail interoperable_fail.cpp ] # test uses expected success, so that we catch unrelated # compilation problems. - [ run is_convertible_fail.cpp ] + [ run is_convertible_fail.cpp ] [ run zip_iterator_test.cpp - : : : - + : : : + # stlport's debug mode generates long symbols which overwhelm # vc6 - #<*>release + #<*>release ] - + # These tests should work for just about everything. [ compile is_lvalue_iterator.cpp ] [ compile is_readable_iterator.cpp ] [ compile pointee.cpp ] - + [ run unit_tests.cpp ] [ run concept_tests.cpp ] [ run iterator_adaptor_cc.cpp ] @@ -41,9 +41,12 @@ test-suite iterator [ run counting_iterator_test.cpp ] [ run interoperable.cpp ] [ run iterator_traits_test.cpp ] - [ run permutation_iterator_test.cpp : : : # on + [ run permutation_iterator_test.cpp : : : # on ] [ run function_input_iterator_test.cpp ] - + [ run generator_iterator_test.cpp ] + + [ run minimum_category.cpp ] + [ compile-fail minimum_category_compile_fail.cpp ] ; diff --git a/test/minimum_category.cpp b/test/minimum_category.cpp new file mode 100644 index 0000000..3f89d6c --- /dev/null +++ b/test/minimum_category.cpp @@ -0,0 +1,22 @@ +// Copyright Andrey Semashev 2014. +// +// Use, modification and distribution is subject to +// the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include + +using boost::is_same; +using boost::iterators::minimum_category; + +int main(int, char*[]) +{ + BOOST_TEST_TRAIT_TRUE((is_same::type, std::forward_iterator_tag>)); + BOOST_TEST_TRAIT_TRUE((is_same::type, std::forward_iterator_tag>)); + BOOST_TEST_TRAIT_TRUE((is_same::type, std::random_access_iterator_tag>)); + + return boost::report_errors(); +} diff --git a/test/minimum_category_compile_fail.cpp b/test/minimum_category_compile_fail.cpp new file mode 100644 index 0000000..736cc20 --- /dev/null +++ b/test/minimum_category_compile_fail.cpp @@ -0,0 +1,19 @@ +// Copyright Andrey Semashev 2014. +// +// Use, modification and distribution is subject to +// the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +using boost::iterators::minimum_category; + +struct A {}; +struct B {}; + +int main(int, char*[]) +{ + minimum_category::type cat; + + return 0; +} diff --git a/test/unit_tests.cpp b/test/unit_tests.cpp index bcad0d6..656e72f 100644 --- a/test/unit_tests.cpp +++ b/test/unit_tests.cpp @@ -7,7 +7,7 @@ #include "static_assert_same.hpp" -#include +#include struct X { int a; }; @@ -29,7 +29,7 @@ void operator_arrow_test() template struct static_assert_min_cat : static_assert_same< - typename boost::iterators::detail::minimum_category::type, Min + typename boost::iterators::minimum_category::type, Min > {}; From 1073b7f7bc9774ef803ceee5100e336c90ecb5c6 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Wed, 30 Jul 2014 23:00:35 +0400 Subject: [PATCH 4/6] Adjustments for compatibility with commit https://github.com/boostorg/range/commit/48dfb6804598a1890198b0ecde48e4a0d1812ea1. --- include/boost/iterator/iterator_categories.hpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/boost/iterator/iterator_categories.hpp b/include/boost/iterator/iterator_categories.hpp index 71202c9..31b2a9d 100644 --- a/include/boost/iterator/iterator_categories.hpp +++ b/include/boost/iterator/iterator_categories.hpp @@ -168,6 +168,13 @@ struct pure_traversal_tag { }; +// This import is needed for backward compatibility with Boost.Range: +// boost/range/detail/demote_iterator_traversal_tag.hpp +// It should be removed when that header is fixed. +namespace detail { +using iterators::pure_traversal_tag; +} // namespace detail + // // Trait to retrieve one of the iterator traversal tags from the iterator category or traversal. // From 23934d7c0d41aee6a4f7d7a5fd00a9b67c01e49e Mon Sep 17 00:00:00 2001 From: Daniel James Date: Mon, 18 Aug 2014 15:00:20 +0100 Subject: [PATCH 5/6] Add metadata file. --- meta/libraries.json | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 meta/libraries.json diff --git a/meta/libraries.json b/meta/libraries.json new file mode 100644 index 0000000..537d803 --- /dev/null +++ b/meta/libraries.json @@ -0,0 +1,18 @@ +{ + "key": "iterator", + "name": "Iterator", + "authors": [ + "Dave Abrahams", + "Jeremy Siek", + "Thomas Witt" + ], + "description": "The Boost Iterator Library contains two parts. The first is a system of concepts which extend the C++ standard iterator requirements. The second is a framework of components for building iterators based on these extended concepts and includes several useful iterator adaptors.", + "category": [ + "Iterators" + ], + "maintainers": [ + "David Abrahams ", + "Thomas Witt ", + "Jeffrey Lee Hellrung Jr. " + ] +} From 82779f78ec46a26d7f64143b926bb9521e4adedd Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sun, 24 Aug 2014 01:55:25 +0400 Subject: [PATCH 6/6] Added docs for iterator category and traversal manipulation tools. --- doc/quickbook/utilities.qbk | 106 +++++++++++++++++++++++++++++++++++- 1 file changed, 103 insertions(+), 3 deletions(-) diff --git a/doc/quickbook/utilities.qbk b/doc/quickbook/utilities.qbk index 4ab4c04..3e001a2 100644 --- a/doc/quickbook/utilities.qbk +++ b/doc/quickbook/utilities.qbk @@ -49,11 +49,40 @@ proxy references or return the pointee by value. When that information is needed, call on `indirect_reference`. Both of these templates are essential to the correct functioning of -[link indirecct `indirect_iterator`]. +[link boost_iterator.indirect `indirect_iterator`]. + +[h2 `minimum_category`] + +`minimum_category` takes two iterator categories or two iterator traversal tags +and returns the one that is the weakest (i.e. least advanced). For example: + + static_assert( + is_same< + minimum_category< + std::forward_iterator_tag, + std::random_access_iterator_tag + >::type, + std::forward_iterator_tag + >::value, + "Unexpected minimum_category result" + ); + +[h2 Iterator category and traversal tags manipulation] + +The library provides several utilities to simplify conversions between iterator categories +and traversal tags: + +* `iterator_category_to_traversal::type` - the metafunction takes an iterator category `C` and returns +the corresponding traversal tag. +* `iterator_traversal::type` - a shorthand for `iterator_category_to_traversal::type>::type`. +* `pure_traversal_tag::type` - the metafunction takes a tag `T` which derives from one of the iterator traversal tags +and returns that traversal tag. `T` may also derive from other tags describing the iterator (e.g. whether this is a `const`-iterator +or not), these additional tags are not considered. +* `pure_iterator_traversal::type` - a shorthand for `pure_traversal_tag::type>::type`. [h2 Reference] -[h3 `pointeee`] +[h3 `pointee`] template struct pointee @@ -110,6 +139,77 @@ Both of these templates are essential to the correct functioning of else std::iterator_traits::reference +[h3 `minimum_category`] + + template + struct minimum_category + { + typedef /* see below */ type; + }; + +[*Requires:] Both `C1` and `C2` shall be standard iterator categories or + iterator traversal tags. + +`type` is determined according to the following algorithm, where `c1` is an +object of type `C1` and `c2` is an object of type `C2`: + + if (c1 is convertible to c2) + return C2; + else + return C1; + +[note The above definition relies on the fact that the more restricting categories +and traversal tags are convertible to the less restricting ones.] + +[h3 `iterator_category_to_traversal`] + + template + struct iterator_category_to_traversal + { + typedef /* see below */ type; + }; + +[*Requires:] `C` shall be a standard iterator category or an + iterator traversal tag. + +If `C` is an iterator traversal tag or convertible to one, `type` equivalent to `C`. +Otherwise, `type` is defined to the closest iterator traversal tag matching `C`. + +[h3 `iterator_traversal`] + + template + struct iterator_traversal + { + typedef typename iterator_category_to_traversal< + typename iterator_category::type + >::type type; + }; + +[*Requires:] `Iterator` shall be an iterator. + +[h3 `pure_traversal_tag`] + + template + struct pure_traversal_tag + { + typedef /* see below */ type; + }; + +[*Requires:] `T` shall be convertible to an iterator traversal tag. + +`type` is defined to be the most advanced traversal tag `Tag` so that `T` is convertible to `Tag`. + +[h3 `pure_iterator_traversal`] + + template + struct pure_iterator_traversal + { + typedef typename pure_traversal_tag< + typename iterator_traversal::type + >::type type; + }; + +[*Requires:] `Iterator` shall be an iterator. [endsect] @@ -221,4 +321,4 @@ Iterator Traversal Concepts [endsect] -[endsect] \ No newline at end of file +[endsect]