3181. split_view::outer_iterator converting constructor is misconstrained

Section: 25.7.16.3 [range.lazy.split.outer] Status: NAD Submitter: Casey Carter Opened: 2019-01-05 Last modified: 2023-02-07

Priority: Not Prioritized

View all other issues in [range.lazy.split.outer].

View all issues with NAD status.

Discussion:

The constraints on split_view::outer_iterator's converting constructor:

constexpr outer_iterator(outer_iterator<!Const> i)
  requires Const && ConvertibleTo<iterator_t<V>, iterator_t<const V>>;
are problematic. Since const V doesn't depend on a template parameter of outer_iterator, compilers want to expand iterator_t<const V> when outer_iterator is instantiated - regardless of the value of Const - which can result in a hard error when iterator_t<const V> is ill-formed. The constraint should instead use iterator_t<Base>, as do the similar converting constructors for the other range adaptor iterator and sentinel types.

[2019-01-20 Reflector prioritization]

Set status to NAD

Proposed resolution:

This wording is relative to N4791.

  1. Change [range.split.outer] as follows:

    namespace std::ranges {
      template<class V, class Pattern>
      template<bool Const>
      struct split_view<V, Pattern>::outer_iterator {
        […]
        constexpr outer_iterator(outer_iterator<!Const> i)
          requires Const && ConvertibleTo<iterator_t<V>, iterator_t<const VBase>>;
        […]
      };
    }
    

    […]

    constexpr outer_iterator(outer_iterator<!Const> i)
      requires Const && ConvertibleTo<iterator_t<V>, iterator_t<const VBase>>;
    

    -4- Effects: Initializes parent_ with i.parent_ and current_ with std::move(i.current_).

    […]