Removed MPL usage from iterator_adaptor.hpp.

This commit is contained in:
Andrey Semashev
2025-02-01 02:03:06 +03:00
parent 4f5f61e37b
commit 1875d95019

View File

@ -7,10 +7,10 @@
#ifndef BOOST_ITERATOR_ADAPTOR_23022003THW_HPP #ifndef BOOST_ITERATOR_ADAPTOR_23022003THW_HPP
#define BOOST_ITERATOR_ADAPTOR_23022003THW_HPP #define BOOST_ITERATOR_ADAPTOR_23022003THW_HPP
#include <boost/core/use_default.hpp>
#include <type_traits> #include <type_traits>
#include <boost/core/use_default.hpp>
#include <boost/iterator/iterator_categories.hpp> #include <boost/iterator/iterator_categories.hpp>
#include <boost/iterator/iterator_facade.hpp> #include <boost/iterator/iterator_facade.hpp>
#include <boost/iterator/iterator_traits.hpp> #include <boost/iterator/iterator_traits.hpp>
@ -20,228 +20,238 @@
namespace boost { namespace boost {
namespace iterators { namespace iterators {
// Used as a default template argument internally, merely to // Used as a default template argument internally, merely to
// indicate "use the default", this can also be passed by users // indicate "use the default", this can also be passed by users
// explicitly in order to specify that the default should be used. // explicitly in order to specify that the default should be used.
using boost::use_default; using boost::use_default;
} // namespace iterators namespace detail {
namespace iterators { //
// Result type used in enable_if_convertible meta function.
// This can be an incomplete type, as only pointers to
// enable_if_convertible< ... >::type are used.
// We could have used void for this, but conversion to
// void* is just too easy.
//
struct enable_type;
namespace detail } // namespace detail
{
// //
// Result type used in enable_if_convertible meta function. // enable_if for use in adapted iterators constructors.
// This can be an incomplete type, as only pointers to //
// enable_if_convertible< ... >::type are used. // In order to provide interoperability between adapted constant and
// We could have used void for this, but conversion to // mutable iterators, adapted iterators will usually provide templated
// void* is just to easy. // conversion constructors of the following form
// //
struct enable_type; // template <class BaseIterator>
} // class adapted_iterator :
// public iterator_adaptor< adapted_iterator<Iterator>, Iterator >
// {
// // public:
// enable_if for use in adapted iterators constructors. //
// // ...
// In order to provide interoperability between adapted constant and //
// mutable iterators, adapted iterators will usually provide templated // template <class OtherIterator>
// conversion constructors of the following form // adapted_iterator(
// // OtherIterator const& it
// template <class BaseIterator> // , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0);
// class adapted_iterator : //
// public iterator_adaptor< adapted_iterator<Iterator>, Iterator > // ...
// { // };
// public: //
// // enable_if_convertible is used to remove those overloads from the overload
// ... // set that cannot be instantiated. For all practical purposes only overloads
// // for constant/mutable interaction will remain. This has the advantage that
// template <class OtherIterator> // meta functions like boost::is_convertible do not return false positives,
// adapted_iterator( // as they can only look at the signature of the conversion constructor
// OtherIterator const& it // and not at the actual instantiation.
// , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0); //
// // enable_if_interoperable can be safely used in user code. It falls back to
// ... // always enabled for compilers that don't support enable_if or is_convertible.
// }; // There is no need for compiler specific workarounds in user code.
// //
// enable_if_convertible is used to remove those overloads from the overload // The operators implementation relies on boost::is_convertible not returning
// set that cannot be instantiated. For all practical purposes only overloads // false positives for user/library defined iterator types. See comments
// for constant/mutable interaction will remain. This has the advantage that // on operator implementation for consequences.
// meta functions like boost::is_convertible do not return false positives, //
// as they can only look at the signature of the conversion constructor template< typename From, typename To >
// and not at the actual instantiation. struct enable_if_convertible :
// public std::enable_if<
// enable_if_interoperable can be safely used in user code. It falls back to std::is_convertible< From, To >::value,
// always enabled for compilers that don't support enable_if or is_convertible. boost::iterators::detail::enable_type
// There is no need for compiler specific workarounds in user code.
//
// The operators implementation relies on boost::is_convertible not returning
// false positives for user/library defined iterator types. See comments
// on operator implementation for consequences.
//
template<typename From, typename To>
struct enable_if_convertible
: std::enable_if<
std::is_convertible<From, To>::value
, boost::iterators::detail::enable_type
> >
{}; {};
// //
// Default template argument handling for iterator_adaptor // Default template argument handling for iterator_adaptor
// //
namespace detail namespace detail {
{
// If T is use_default, return the result of invoking // If T is use_default, return the result of invoking
// DefaultNullaryFn, otherwise return T. // DefaultNullaryFn, otherwise return T.
template <class T, class DefaultNullaryFn> template< typename T, typename DefaultNullaryFn >
struct ia_dflt_help struct ia_dflt_help
: mpl::eval_if< {
std::is_same<T, use_default> using type = T;
, DefaultNullaryFn };
, mpl::identity<T>
template< typename DefaultNullaryFn >
struct ia_dflt_help< use_default, DefaultNullaryFn >
{
using type = typename DefaultNullaryFn::type;
};
template< typename T, typename DefaultNullaryFn >
using ia_dflt_help_t = typename ia_dflt_help< T, DefaultNullaryFn >::type;
// If T is use_default, return the result of invoking
// DefaultNullaryFn, otherwise - of NondefaultNullaryFn.
template< typename T, typename DefaultNullaryFn, typename NondefaultNullaryFn >
struct ia_eval_if_default
{
using type = typename NondefaultNullaryFn::type;
};
template< typename DefaultNullaryFn, typename NondefaultNullaryFn >
struct ia_eval_if_default< use_default, DefaultNullaryFn, NondefaultNullaryFn >
{
using type = typename DefaultNullaryFn::type;
};
template< typename T, typename DefaultNullaryFn, typename NondefaultNullaryFn >
using ia_eval_if_default_t = typename ia_eval_if_default< T, DefaultNullaryFn, NondefaultNullaryFn >::type;
// A metafunction which computes an iterator_adaptor's base class,
// a specialization of iterator_facade.
template<
typename Derived,
typename Base,
typename Value,
typename Traversal,
typename Reference,
typename Difference
>
using iterator_adaptor_base_t = iterator_facade<
Derived,
#ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY
detail::ia_dflt_help_t<
Value,
detail::ia_eval_if_default<
Reference,
iterator_value< Base >,
std::remove_reference< Reference >
> >
{ >,
}; #else
detail::ia_dflt_help_t<
Value,
iterator_value< Base >
>,
#endif
// A metafunction which computes an iterator_adaptor's base class, detail::ia_dflt_help_t<
// a specialization of iterator_facade. Traversal,
template < iterator_traversal< Base >
class Derived >,
, class Base
, class Value detail::ia_dflt_help_t<
, class Traversal Reference,
, class Reference detail::ia_eval_if_default<
, class Difference Value,
iterator_reference< Base >,
std::add_lvalue_reference< Value >
> >
struct iterator_adaptor_base >,
{
typedef iterator_facade<
Derived
# ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY detail::ia_dflt_help_t<
, typename boost::iterators::detail::ia_dflt_help< Difference,
Value iterator_difference< Base >
, mpl::eval_if<
std::is_same<Reference,use_default>
, iterator_value<Base>
, std::remove_reference<Reference>
> >
>::type >;
# else
, typename boost::iterators::detail::ia_dflt_help<
Value, iterator_value<Base>
>::type
# endif
, typename boost::iterators::detail::ia_dflt_help< } // namespace detail
Traversal
, iterator_traversal<Base>
>::type
, typename boost::iterators::detail::ia_dflt_help< //
Reference // Iterator Adaptor
, mpl::eval_if< //
std::is_same<Value,use_default> // The parameter ordering changed slightly with respect to former
, iterator_reference<Base> // versions of iterator_adaptor The idea is that when the user needs
, std::add_lvalue_reference<Value> // to fiddle with the reference type it is highly likely that the
> // iterator category has to be adjusted as well. Any of the
>::type // following four template arguments may be omitted or explicitly
// replaced by use_default.
, typename boost::iterators::detail::ia_dflt_help< //
Difference, iterator_difference<Base> // Value - if supplied, the value_type of the resulting iterator, unless
>::type // const. If const, a conforming compiler strips constness for the
> // value_type. If not supplied, iterator_traits<Base>::value_type is used
type; //
}; // Category - the traversal category of the resulting iterator. If not
} // supplied, iterator_traversal<Base>::type is used.
//
// // Reference - the reference type of the resulting iterator, and in
// Iterator Adaptor // particular, the result type of operator*(). If not supplied but
// // Value is supplied, Value& is used. Otherwise
// The parameter ordering changed slightly with respect to former // iterator_traits<Base>::reference is used.
// versions of iterator_adaptor The idea is that when the user needs //
// to fiddle with the reference type it is highly likely that the // Difference - the difference_type of the resulting iterator. If not
// iterator category has to be adjusted as well. Any of the // supplied, iterator_traits<Base>::difference_type is used.
// following four template arguments may be omitted or explicitly //
// replaced by use_default. template<
// typename Derived,
// Value - if supplied, the value_type of the resulting iterator, unless typename Base,
// const. If const, a conforming compiler strips constness for the typename Value = use_default,
// value_type. If not supplied, iterator_traits<Base>::value_type is used typename Traversal = use_default,
// typename Reference = use_default,
// Category - the traversal category of the resulting iterator. If not typename Difference = use_default
// supplied, iterator_traversal<Base>::type is used. >
// class iterator_adaptor :
// Reference - the reference type of the resulting iterator, and in public detail::iterator_adaptor_base_t<
// particular, the result type of operator*(). If not supplied but
// Value is supplied, Value& is used. Otherwise
// iterator_traits<Base>::reference is used.
//
// Difference - the difference_type of the resulting iterator. If not
// supplied, iterator_traits<Base>::difference_type is used.
//
template <
class Derived
, class Base
, class Value = use_default
, class Traversal = use_default
, class Reference = use_default
, class Difference = use_default
>
class iterator_adaptor
: public boost::iterators::detail::iterator_adaptor_base<
Derived, Base, Value, Traversal, Reference, Difference Derived, Base, Value, Traversal, Reference, Difference
>::type >
{ {
friend class iterator_core_access; friend class iterator_core_access;
protected: protected:
typedef typename boost::iterators::detail::iterator_adaptor_base< using super_t = detail::iterator_adaptor_base_t<
Derived, Base, Value, Traversal, Reference, Difference Derived, Base, Value, Traversal, Reference, Difference
>::type super_t; >;
public:
iterator_adaptor() {}
explicit iterator_adaptor(Base const& iter) public:
: m_iterator(iter) using base_type = Base;
iterator_adaptor() = default;
explicit iterator_adaptor(Base const& iter) :
m_iterator(iter)
{ {
} }
typedef Base base_type; base_type const& base() const { return m_iterator; }
Base const& base() const protected:
{ return m_iterator; }
protected:
// for convenience in derived classes // for convenience in derived classes
typedef iterator_adaptor<Derived,Base,Value,Traversal,Reference,Difference> iterator_adaptor_; using iterator_adaptor_ = iterator_adaptor< Derived, Base, Value, Traversal, Reference, Difference >;
// //
// lvalue access to the Base object for Derived // lvalue access to the Base object for Derived
// //
Base const& base_reference() const Base& base_reference() { return m_iterator; }
{ return m_iterator; } Base const& base_reference() const { return m_iterator; }
Base& base_reference() private:
{ return m_iterator; }
private:
// //
// Core iterator interface for iterator_facade. This is private // Core iterator interface for iterator_facade. This is private
// to prevent temptation for Derived classes to use it, which // to prevent temptation for Derived classes to use it, which
// will often result in an error. Derived classes should use // will often result in an error. Derived classes should use
// base_reference(), above, to get direct access to m_iterator. // base_reference(), above, to get direct access to m_iterator.
// //
typename super_t::reference dereference() const typename super_t::reference dereference() const { return *m_iterator; }
{ return *m_iterator; }
template < template< typename OtherDerived, typename OtherIterator, typename V, typename C, typename R, typename D >
class OtherDerived, class OtherIterator, class V, class C, class R, class D bool equal(iterator_adaptor< OtherDerived, OtherIterator, V, C, R, D > const& x) const
>
bool equal(iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& x) const
{ {
// Maybe readd with same_distance // Maybe readd with same_distance
// BOOST_STATIC_ASSERT( // BOOST_STATIC_ASSERT(
@ -250,16 +260,12 @@ namespace iterators {
return m_iterator == x.base(); return m_iterator == x.base();
} }
typedef typename iterator_category_to_traversal< using my_traversal = typename iterator_category_to_traversal< typename super_t::iterator_category >::type;
typename super_t::iterator_category
>::type my_traversal;
void advance(typename super_t::difference_type n) void advance(typename super_t::difference_type n)
{ {
static_assert( static_assert(detail::is_traversal_at_least< my_traversal, random_access_traversal_tag >::value,
std::is_convertible<my_traversal, random_access_traversal_tag>::value, "Iterator must support random access traversal.");
"Iterator must support random access traversal."
);
m_iterator += n; m_iterator += n;
} }
@ -267,23 +273,16 @@ namespace iterators {
void decrement() void decrement()
{ {
static_assert( static_assert(detail::is_traversal_at_least< my_traversal, bidirectional_traversal_tag >::value,
std::is_convertible<my_traversal, bidirectional_traversal_tag>::value, "Iterator must support bidirectional traversal.");
"Iterator must support bidirectional traversal."
);
--m_iterator; --m_iterator;
} }
template < template< typename OtherDerived, typename OtherIterator, typename V, typename C, typename R, typename D >
class OtherDerived, class OtherIterator, class V, class C, class R, class D typename super_t::difference_type distance_to(iterator_adaptor< OtherDerived, OtherIterator, V, C, R, D > const& y) const
>
typename super_t::difference_type distance_to(
iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& y) const
{ {
static_assert( static_assert(detail::is_traversal_at_least< my_traversal, random_access_traversal_tag >::value,
std::is_convertible<my_traversal, random_access_traversal_tag>::value, "Super iterator must support random access traversal.");
"Super iterator must support random access traversal."
);
// Maybe readd with same_distance // Maybe readd with same_distance
// BOOST_STATIC_ASSERT( // BOOST_STATIC_ASSERT(
// (detail::same_category_and_difference<Derived,OtherDerived>::value) // (detail::same_category_and_difference<Derived,OtherDerived>::value)
@ -291,9 +290,9 @@ namespace iterators {
return y.base() - m_iterator; return y.base() - m_iterator;
} }
private: // data members private: // data members
Base m_iterator; Base m_iterator;
}; };
} // namespace iterators } // namespace iterators