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,280 +20,279 @@
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
//
namespace detail
{
// If T is use_default, return the result of invoking
// DefaultNullaryFn, otherwise return T.
template <class T, class DefaultNullaryFn>
struct ia_dflt_help
: mpl::eval_if<
std::is_same<T, use_default>
, DefaultNullaryFn
, mpl::identity<T>
>
{
};
// A metafunction which computes an iterator_adaptor's base class,
// a specialization of iterator_facade.
template <
class Derived
, class Base
, class Value
, class Traversal
, class Reference
, class Difference
> >
struct iterator_adaptor_base {};
{
typedef iterator_facade<
Derived
# ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY //
, typename boost::iterators::detail::ia_dflt_help< // Default template argument handling for iterator_adaptor
Value //
, mpl::eval_if< namespace detail {
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< // If T is use_default, return the result of invoking
Traversal // DefaultNullaryFn, otherwise return T.
, iterator_traversal<Base> template< typename T, typename DefaultNullaryFn >
>::type struct ia_dflt_help
{
using type = T;
};
, typename boost::iterators::detail::ia_dflt_help< template< typename DefaultNullaryFn >
Reference struct ia_dflt_help< use_default, DefaultNullaryFn >
, mpl::eval_if< {
std::is_same<Value,use_default> using type = typename DefaultNullaryFn::type;
, iterator_reference<Base> };
, std::add_lvalue_reference<Value>
>
>::type
, typename boost::iterators::detail::ia_dflt_help< template< typename T, typename DefaultNullaryFn >
Difference, iterator_difference<Base> using ia_dflt_help_t = typename ia_dflt_help< T, DefaultNullaryFn >::type;
>::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 >
> >
type; >,
}; #else
} detail::ia_dflt_help_t<
Value,
iterator_value< Base >
>,
#endif
// detail::ia_dflt_help_t<
// Iterator Adaptor Traversal,
// iterator_traversal< Base >
// The parameter ordering changed slightly with respect to former >,
// versions of iterator_adaptor The idea is that when the user needs
// to fiddle with the reference type it is highly likely that the detail::ia_dflt_help_t<
// iterator category has to be adjusted as well. Any of the Reference,
// following four template arguments may be omitted or explicitly detail::ia_eval_if_default<
// replaced by use_default. Value,
// iterator_reference< Base >,
// Value - if supplied, the value_type of the resulting iterator, unless std::add_lvalue_reference< Value >
// const. If const, a conforming compiler strips constness for the >
// value_type. If not supplied, iterator_traits<Base>::value_type is used >,
//
// Category - the traversal category of the resulting iterator. If not detail::ia_dflt_help_t<
// supplied, iterator_traversal<Base>::type is used. Difference,
// iterator_difference< Base >
// Reference - the reference type of the resulting iterator, and in >
// particular, the result type of operator*(). If not supplied but >;
// Value is supplied, Value& is used. Otherwise
// iterator_traits<Base>::reference is used. } // namespace detail
//
// Difference - the difference_type of the resulting iterator. If not //
// supplied, iterator_traits<Base>::difference_type is used. // Iterator Adaptor
// //
template < // The parameter ordering changed slightly with respect to former
class Derived // versions of iterator_adaptor The idea is that when the user needs
, class Base // to fiddle with the reference type it is highly likely that the
, class Value = use_default // iterator category has to be adjusted as well. Any of the
, class Traversal = use_default // following four template arguments may be omitted or explicitly
, class Reference = use_default // replaced by use_default.
, class Difference = use_default //
> // Value - if supplied, the value_type of the resulting iterator, unless
class iterator_adaptor // const. If const, a conforming compiler strips constness for the
: public boost::iterators::detail::iterator_adaptor_base< // value_type. If not supplied, iterator_traits<Base>::value_type is used
//
// 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
// 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<
typename Derived,
typename Base,
typename Value = use_default,
typename Traversal = use_default,
typename Reference = use_default,
typename Difference = use_default
>
class iterator_adaptor :
public detail::iterator_adaptor_base_t<
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;
{
}
typedef Base base_type; iterator_adaptor() = default;
Base const& base() const explicit iterator_adaptor(Base const& iter) :
{ return m_iterator; } m_iterator(iter)
{
}
protected: base_type const& base() const { return m_iterator; }
// for convenience in derived classes
typedef iterator_adaptor<Derived,Base,Value,Traversal,Reference,Difference> iterator_adaptor_;
// protected:
// lvalue access to the Base object for Derived // for convenience in derived classes
// using iterator_adaptor_ = iterator_adaptor< Derived, Base, Value, Traversal, Reference, Difference >;
Base const& base_reference() const
{ return m_iterator; }
Base& base_reference() //
{ return m_iterator; } // lvalue access to the Base object for Derived
//
Base& base_reference() { return m_iterator; }
Base const& base_reference() const { return m_iterator; }
private: 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(
// (detail::same_category_and_difference<Derived,OtherDerived>::value) // (detail::same_category_and_difference<Derived,OtherDerived>::value)
// ); // );
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;
}
void increment() { ++m_iterator; } void increment() { ++m_iterator; }
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( static_assert(detail::is_traversal_at_least< my_traversal, random_access_traversal_tag >::value,
iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& y) const "Super iterator must support random access traversal.");
{ // Maybe readd with same_distance
static_assert( // BOOST_STATIC_ASSERT(
std::is_convertible<my_traversal, random_access_traversal_tag>::value, // (detail::same_category_and_difference<Derived,OtherDerived>::value)
"Super iterator must support random access traversal." // );
); return y.base() - m_iterator;
// Maybe readd with same_distance }
// BOOST_STATIC_ASSERT(
// (detail::same_category_and_difference<Derived,OtherDerived>::value)
// );
return y.base() - m_iterator;
}
private: // data members private: // data members
Base m_iterator; Base m_iterator;
}; };
} // namespace iterators } // namespace iterators