Merge upstream branch 'develop' into pr/zip_iterator/fusionize

This commit is contained in:
Kohei Takahashi
2014-08-25 00:36:36 +09:00
12 changed files with 337 additions and 141 deletions

View File

@ -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<C>::type` - the metafunction takes an iterator category `C` and returns
the corresponding traversal tag.
* `iterator_traversal<T>::type` - a shorthand for `iterator_category_to_traversal<iterator_category<T>::type>::type`.
* `pure_traversal_tag<T>::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<T>::type` - a shorthand for `pure_traversal_tag<iterator_traversal<T>::type>::type`.
[h2 Reference]
[h3 `pointeee`]
[h3 `pointee`]
template <class Dereferenceable>
struct pointee
@ -110,6 +139,77 @@ Both of these templates are essential to the correct functioning of
else
std::iterator_traits<Dereferenceable>::reference
[h3 `minimum_category`]
template <typename C1, typename C2>
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 <typename C>
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 <typename Iterator>
struct iterator_traversal
{
typedef typename iterator_category_to_traversal<
typename iterator_category<Iterator>::type
>::type type;
};
[*Requires:] `Iterator` shall be an iterator.
[h3 `pure_traversal_tag`]
template <typename T>
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 <typename Iterator>
struct pure_iterator_traversal
{
typedef typename pure_traversal_tag<
typename iterator_traversal<Iterator>::type
>::type type;
};
[*Requires:] `Iterator` shall be an iterator.
[endsect]

View File

@ -4,98 +4,14 @@
#ifndef MINIMUM_CATEGORY_DWA20031119_HPP
# define MINIMUM_CATEGORY_DWA20031119_HPP
# include <boost/type_traits/is_convertible.hpp>
# include <boost/type_traits/is_same.hpp>
# include <boost/mpl/aux_/lambda_support.hpp>
# include <boost/iterator/minimum_category.hpp>
namespace boost {
namespace iterators {
// 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 {
//
// 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 <bool GreaterEqual, bool LessEqual>
struct minimum_category_impl;
template <class T1, class T2>
struct error_not_related_by_convertibility;
template <>
struct minimum_category_impl<true,false>
{
template <class T1, class T2> struct apply
{
typedef T2 type;
};
};
template <>
struct minimum_category_impl<false,true>
{
template <class T1, class T2> struct apply
{
typedef T1 type;
};
};
template <>
struct minimum_category_impl<true,true>
{
template <class T1, class T2> struct apply
{
BOOST_STATIC_ASSERT((is_same<T1,T2>::value));
typedef T1 type;
};
};
template <>
struct minimum_category_impl<false,false>
{
template <class T1, class T2> struct apply
: error_not_related_by_convertibility<T1,T2>
{
};
};
template <class T1 = mpl::_1, class T2 = mpl::_2>
struct minimum_category
{
typedef minimum_category_impl<
::boost::is_convertible<T1,T2>::value
, ::boost::is_convertible<T2,T1>::value
> outer;
typedef typename outer::template apply<T1,T2> inner;
typedef typename inner::type type;
BOOST_MPL_AUX_LAMBDA_SUPPORT(2,minimum_category,(T1,T2))
};
template <>
struct minimum_category<mpl::_1,mpl::_2>
{
template <class T1, class T2>
struct apply : minimum_category<T1,T2>
{};
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;
using iterators::minimum_category;
} // namespace detail
} // namespace boost

View File

@ -98,35 +98,8 @@ namespace detail
>
{};
template <class Traversal>
struct pure_traversal_tag
: mpl::eval_if<
is_convertible<Traversal,random_access_traversal_tag>
, mpl::identity<random_access_traversal_tag>
, mpl::eval_if<
is_convertible<Traversal,bidirectional_traversal_tag>
, mpl::identity<bidirectional_traversal_tag>
, mpl::eval_if<
is_convertible<Traversal,forward_traversal_tag>
, mpl::identity<forward_traversal_tag>
, mpl::eval_if<
is_convertible<Traversal,single_pass_traversal_tag>
, mpl::identity<single_pass_traversal_tag>
, mpl::eval_if<
is_convertible<Traversal,incrementable_traversal_tag>
, mpl::identity<incrementable_traversal_tag>
, void
>
>
>
>
>
{
};
} // namespace detail
//
// Convert an iterator category into a traversal tag
//
@ -166,6 +139,64 @@ struct iterator_traversal<mpl::_>
{};
# endif
//
// Convert an iterator traversal to one of the traversal tags.
//
template <class Traversal>
struct pure_traversal_tag
: mpl::eval_if<
is_convertible<Traversal,random_access_traversal_tag>
, mpl::identity<random_access_traversal_tag>
, mpl::eval_if<
is_convertible<Traversal,bidirectional_traversal_tag>
, mpl::identity<bidirectional_traversal_tag>
, mpl::eval_if<
is_convertible<Traversal,forward_traversal_tag>
, mpl::identity<forward_traversal_tag>
, mpl::eval_if<
is_convertible<Traversal,single_pass_traversal_tag>
, mpl::identity<single_pass_traversal_tag>
, mpl::eval_if<
is_convertible<Traversal,incrementable_traversal_tag>
, mpl::identity<incrementable_traversal_tag>
, void
>
>
>
>
>
{
};
// 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.
//
template <class Iterator = mpl::_1>
struct pure_iterator_traversal
: pure_traversal_tag<typename iterator_traversal<Iterator>::type>
{};
# ifdef BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT
template <>
struct pure_iterator_traversal<mpl::_1>
{
template <class T>
struct apply : pure_iterator_traversal<T>
{};
};
template <>
struct pure_iterator_traversal<mpl::_>
: pure_iterator_traversal<mpl::_1>
{};
# endif
} // namespace iterators
using iterators::no_traversal_tag;
@ -177,6 +208,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 <boost/iterator/detail/config_undef.hpp>

View File

@ -248,17 +248,8 @@ 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::detail::pure_traversal_tag<
typename boost::iterator_traversal<
ConstIterator
>::type
>::type const_traversal_category;
typedef typename boost::iterators::pure_iterator_traversal<Iterator>::type traversal_category;
typedef typename boost::iterators::pure_iterator_traversal<ConstIterator>::type const_traversal_category;
public:
BOOST_CONCEPT_ASSERT((SinglePassIterator<Iterator>));

View File

@ -0,0 +1,95 @@
// 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 BOOST_ITERATOR_MINIMUM_CATEGORY_HPP_INCLUDED_
# define BOOST_ITERATOR_MINIMUM_CATEGORY_HPP_INCLUDED_
# include <boost/static_assert.hpp>
# include <boost/type_traits/is_convertible.hpp>
# include <boost/type_traits/is_same.hpp>
# include <boost/mpl/placeholders.hpp>
# include <boost/mpl/aux_/lambda_support.hpp>
namespace boost {
namespace iterators {
namespace detail {
template <bool GreaterEqual, bool LessEqual>
struct minimum_category_impl;
template <class T1, class T2>
struct error_not_related_by_convertibility;
template <>
struct minimum_category_impl<true,false>
{
template <class T1, class T2> struct apply
{
typedef T2 type;
};
};
template <>
struct minimum_category_impl<false,true>
{
template <class T1, class T2> struct apply
{
typedef T1 type;
};
};
template <>
struct minimum_category_impl<true,true>
{
template <class T1, class T2> struct apply
{
BOOST_STATIC_ASSERT((is_same<T1,T2>::value));
typedef T1 type;
};
};
template <>
struct minimum_category_impl<false,false>
{
template <class T1, class T2> struct apply
: error_not_related_by_convertibility<T1,T2>
{
};
};
} // namespace detail
//
// Returns the minimum category type or fails to compile
// if T1 and T2 are unrelated.
//
template <class T1 = mpl::_1, class T2 = mpl::_2>
struct minimum_category
{
typedef boost::iterators::detail::minimum_category_impl<
::boost::is_convertible<T1,T2>::value
, ::boost::is_convertible<T2,T1>::value
> outer;
typedef typename outer::template apply<T1,T2> inner;
typedef typename inner::type type;
BOOST_MPL_AUX_LAMBDA_SUPPORT(2,minimum_category,(T1,T2))
};
template <>
struct minimum_category<mpl::_1,mpl::_2>
{
template <class T1, class T2>
struct apply : minimum_category<T1,T2>
{};
BOOST_MPL_AUX_LAMBDA_SUPPORT_SPEC(2,minimum_category,(mpl::_1,mpl::_2))
};
} // namespace iterators
} // namespace boost
#endif // BOOST_ITERATOR_MINIMUM_CATEGORY_HPP_INCLUDED_

View File

@ -15,7 +15,7 @@
#include <boost/iterator/iterator_adaptor.hpp> // for enable_if_convertible
#include <boost/iterator/iterator_categories.hpp>
#include <boost/iterator/detail/minimum_category.hpp>
#include <boost/iterator/minimum_category.hpp>
#include <utility> // for std::pair
#include <boost/fusion/adapted/boost_tuple.hpp> // for backward compatibility

18
meta/libraries.json Normal file
View File

@ -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 <dave -at- boost-consulting.com>",
"Thomas Witt <witt - at - acm.org>",
"Jeffrey Lee Hellrung Jr. <jeffrey.hellrung -at- gmail.com>"
]
}

View File

@ -46,5 +46,9 @@ test-suite iterator
[ run permutation_iterator_test.cpp : : : # <stlport-iostream>on
]
[ run function_input_iterator_test.cpp ]
[ run generator_iterator_test.cpp ]
[ run minimum_category.cpp ]
[ compile-fail minimum_category_compile_fail.cpp ]
;

22
test/minimum_category.cpp Normal file
View File

@ -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 <boost/iterator/minimum_category.hpp>
#include <boost/core/lightweight_test_trait.hpp>
#include <boost/type_traits/is_same.hpp>
#include <iterator>
using boost::is_same;
using boost::iterators::minimum_category;
int main(int, char*[])
{
BOOST_TEST_TRAIT_TRUE((is_same<minimum_category<std::forward_iterator_tag, std::random_access_iterator_tag>::type, std::forward_iterator_tag>));
BOOST_TEST_TRAIT_TRUE((is_same<minimum_category<std::random_access_iterator_tag, std::forward_iterator_tag>::type, std::forward_iterator_tag>));
BOOST_TEST_TRAIT_TRUE((is_same<minimum_category<std::random_access_iterator_tag, std::random_access_iterator_tag>::type, std::random_access_iterator_tag>));
return boost::report_errors();
}

View File

@ -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 <boost/iterator/minimum_category.hpp>
using boost::iterators::minimum_category;
struct A {};
struct B {};
int main(int, char*[])
{
minimum_category<A, B>::type cat;
return 0;
}

View File

@ -7,7 +7,7 @@
#include "static_assert_same.hpp"
#include <boost/iterator/detail/minimum_category.hpp>
#include <boost/iterator/minimum_category.hpp>
struct X { int a; };
@ -29,7 +29,7 @@ void operator_arrow_test()
template <class T, class U, class Min>
struct static_assert_min_cat
: static_assert_same<
typename boost::iterators::detail::minimum_category<T,U>::type, Min
typename boost::iterators::minimum_category<T,U>::type, Min
>
{};

View File

@ -55,13 +55,6 @@
#include <boost/detail/workaround.hpp>
#include <stddef.h>
template <class It>
struct pure_traversal
: boost::iterators::detail::pure_traversal_tag<
typename boost::iterator_traversal<It>::type
>
{};
/// Tests for https://svn.boost.org/trac/boost/ticket/1517
int to_value(int const &v)