Reduced dependency on MPL in iterator_categories.hpp.

Also simplified implementation of type traits using Boost.MP11.
This commit is contained in:
Andrey Semashev
2025-01-28 01:11:36 +03:00
parent 6fab3bbfa4
commit 83905b219e

View File

@ -4,15 +4,13 @@
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_ITERATOR_CATEGORIES_HPP #ifndef BOOST_ITERATOR_CATEGORIES_HPP
# define BOOST_ITERATOR_CATEGORIES_HPP #define BOOST_ITERATOR_CATEGORIES_HPP
# include <boost/mpl/eval_if.hpp>
# include <boost/mpl/identity.hpp>
# include <boost/mpl/placeholders.hpp>
# include <boost/mpl/aux_/lambda_support.hpp>
#include <type_traits>
#include <iterator> #include <iterator>
#include <type_traits>
#include <boost/mpl/arg_fwd.hpp>
#include <boost/mp11/utility.hpp>
namespace boost { namespace boost {
namespace iterators { namespace iterators {
@ -20,168 +18,78 @@ namespace iterators {
// //
// Traversal Categories // Traversal Categories
// //
struct no_traversal_tag {}; struct no_traversal_tag {};
struct incrementable_traversal_tag : public no_traversal_tag {};
struct incrementable_traversal_tag struct single_pass_traversal_tag : public incrementable_traversal_tag {};
: no_traversal_tag struct forward_traversal_tag : public single_pass_traversal_tag {};
{ struct bidirectional_traversal_tag : public forward_traversal_tag {};
// incrementable_traversal_tag() {} struct random_access_traversal_tag : public bidirectional_traversal_tag {};
// incrementable_traversal_tag(std::output_iterator_tag const&) {};
};
struct single_pass_traversal_tag
: incrementable_traversal_tag
{
// single_pass_traversal_tag() {}
// single_pass_traversal_tag(std::input_iterator_tag const&) {};
};
struct forward_traversal_tag
: single_pass_traversal_tag
{
// forward_traversal_tag() {}
// forward_traversal_tag(std::forward_iterator_tag const&) {};
};
struct bidirectional_traversal_tag
: forward_traversal_tag
{
// bidirectional_traversal_tag() {};
// bidirectional_traversal_tag(std::bidirectional_iterator_tag const&) {};
};
struct random_access_traversal_tag
: bidirectional_traversal_tag
{
// random_access_traversal_tag() {};
// random_access_traversal_tag(std::random_access_iterator_tag const&) {};
};
namespace detail
{
//
// Convert a "strictly old-style" iterator category to a traversal
// tag. This is broken out into a separate metafunction to reduce
// the cost of instantiating iterator_category_to_traversal, below,
// for new-style types.
//
template <class Cat>
struct old_category_to_traversal
: mpl::eval_if<
std::is_convertible<Cat,std::random_access_iterator_tag>
, mpl::identity<random_access_traversal_tag>
, mpl::eval_if<
std::is_convertible<Cat,std::bidirectional_iterator_tag>
, mpl::identity<bidirectional_traversal_tag>
, mpl::eval_if<
std::is_convertible<Cat,std::forward_iterator_tag>
, mpl::identity<forward_traversal_tag>
, mpl::eval_if<
std::is_convertible<Cat,std::input_iterator_tag>
, mpl::identity<single_pass_traversal_tag>
, mpl::eval_if<
std::is_convertible<Cat,std::output_iterator_tag>
, mpl::identity<incrementable_traversal_tag>
, void
>
>
>
>
>
{};
} // namespace detail
// //
// Convert an iterator category into a traversal tag // Convert an iterator category into a traversal tag
// //
template <class Cat> template< typename Cat >
using iterator_category_to_traversal_t = mp11::mp_cond<
// if already convertible to a traversal tag, we're done.
std::is_convertible< Cat, incrementable_traversal_tag >, Cat,
std::is_convertible< Cat, std::random_access_iterator_tag >, random_access_traversal_tag,
std::is_convertible< Cat, std::bidirectional_iterator_tag >, bidirectional_traversal_tag,
std::is_convertible< Cat, std::forward_iterator_tag >, forward_traversal_tag,
std::is_convertible< Cat, std::input_iterator_tag >, single_pass_traversal_tag,
std::is_convertible< Cat, std::output_iterator_tag >, incrementable_traversal_tag,
std::true_type, void
>;
template< typename Cat >
struct iterator_category_to_traversal struct iterator_category_to_traversal
: mpl::eval_if< // if already convertible to a traversal tag, we're done. {
std::is_convertible<Cat, incrementable_traversal_tag> using type = iterator_category_to_traversal_t< Cat >;
, mpl::identity<Cat> };
, boost::iterators::detail::old_category_to_traversal<Cat>
>
{};
// Trait to get an iterator's traversal category // Trait to get an iterator's traversal category
template <class Iterator = mpl::_1> template< typename Iterator >
struct iterator_traversal using iterator_traversal_t = iterator_category_to_traversal_t<
: iterator_category_to_traversal< typename std::iterator_traits< Iterator >::iterator_category
typename std::iterator_traits<Iterator>::iterator_category >;
>
{};
# ifdef BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT template< typename Iterator = mpl::arg< 1 > >
// Hack because BOOST_MPL_AUX_LAMBDA_SUPPORT doesn't seem to work struct iterator_traversal
// out well. Instantiating the nested apply template also
// requires instantiating iterator_traits on the
// placeholder. Instead we just specialize it as a metafunction
// class.
template <>
struct iterator_traversal<mpl::_1>
{ {
template <class T> using type = iterator_traversal_t< Iterator >;
struct apply : iterator_traversal<T>
{};
}; };
template <>
struct iterator_traversal<mpl::_>
: iterator_traversal<mpl::_1>
{};
# endif
// //
// Convert an iterator traversal to one of the traversal tags. // Convert an iterator traversal to one of the traversal tags.
// //
template <class Traversal> template< typename Traversal >
using pure_traversal_tag_t = mp11::mp_cond<
std::is_convertible< Traversal, random_access_traversal_tag >, random_access_traversal_tag,
std::is_convertible< Traversal, bidirectional_traversal_tag >, bidirectional_traversal_tag,
std::is_convertible< Traversal, forward_traversal_tag >, forward_traversal_tag,
std::is_convertible< Traversal, single_pass_traversal_tag >, single_pass_traversal_tag,
std::is_convertible< Traversal, incrementable_traversal_tag >, incrementable_traversal_tag,
std::true_type, void
>;
template< typename Traversal >
struct pure_traversal_tag struct pure_traversal_tag
: mpl::eval_if<
std::is_convertible<Traversal,random_access_traversal_tag>
, mpl::identity<random_access_traversal_tag>
, mpl::eval_if<
std::is_convertible<Traversal,bidirectional_traversal_tag>
, mpl::identity<bidirectional_traversal_tag>
, mpl::eval_if<
std::is_convertible<Traversal,forward_traversal_tag>
, mpl::identity<forward_traversal_tag>
, mpl::eval_if<
std::is_convertible<Traversal,single_pass_traversal_tag>
, mpl::identity<single_pass_traversal_tag>
, mpl::eval_if<
std::is_convertible<Traversal,incrementable_traversal_tag>
, mpl::identity<incrementable_traversal_tag>
, void
>
>
>
>
>
{ {
using type = pure_traversal_tag_t< Traversal >;
}; };
// //
// Trait to retrieve one of the iterator traversal tags from the iterator category or traversal. // Trait to retrieve one of the iterator traversal tags from the iterator category or traversal.
// //
template <class Iterator = mpl::_1> template< typename Iterator >
struct pure_iterator_traversal using pure_iterator_traversal_t = pure_traversal_tag_t<
: pure_traversal_tag<typename iterator_traversal<Iterator>::type> iterator_traversal_t< Iterator >
{}; >;
# ifdef BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT template< typename Iterator = mpl::arg< 1 > >
template <> struct pure_iterator_traversal
struct pure_iterator_traversal<mpl::_1>
{ {
template <class T> using type = pure_iterator_traversal_t< Iterator >;
struct apply : pure_iterator_traversal<T>
{};
}; };
template <>
struct pure_iterator_traversal<mpl::_>
: pure_iterator_traversal<mpl::_1>
{};
# endif
} // namespace iterators } // namespace iterators
@ -194,13 +102,6 @@ using iterators::random_access_traversal_tag;
using iterators::iterator_category_to_traversal; using iterators::iterator_category_to_traversal;
using iterators::iterator_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 } // namespace boost
#endif // BOOST_ITERATOR_CATEGORIES_HPP #endif // BOOST_ITERATOR_CATEGORIES_HPP