Title
view iterator types have ill-formed <=> operators
Status
c++20
Section
[range.iota.iterator][range.transform.iterator] [range.elements.iterator]
Submitter
Jonathan Wakely

Created on 2020-02-07.00:00:00 last changed 38 months ago

Messages

Date: 2020-02-10.19:13:13

Proposed resolution:

This wording is relative to N4849.

  1. Modify [range.iota.iterator] as indicated:

    namespace std::ranges {
      template<class W, class Bound>
      struct iota_view<W, Bound>::iterator {
        […]
        friend constexpr compare_three_way_result_t<W>auto operator<=>(
            const iterator& x, const iterator& y)
          requires totally_ordered<W> && three_way_comparable<W>;
        […]
      };
      […]
    }
    
    […]
    friend constexpr compare_three_way_result_t<W>auto
      operator<=>(const iterator& x, const iterator& y)
        requires totally_ordered<W> && three_way_comparable<W>;
    

    -19- Effects: Equivalent to: return x.value_ <=> y.value_;

  2. Modify [range.transform.iterator] as indicated:

    namespace std::ranges {
      template<class V, class F>
      template<bool Const>
      class transform_view<V, F>::iterator {
        […]
        friend constexpr compare_three_way_result_t<iterator_t<Base>>auto 
          operator<=>(const iterator& x, const iterator& y)
            requires random_access_range<Base> && three_way_comparable<iterator_t<Base>>;
        […]
      };
      […]
    }
    
    […]
    friend constexpr compare_three_way_result_t<iterator_t<Base>>auto
      operator<=>(const iterator& x, const iterator& y)
        requires random_access_range<Base> && three_way_comparable<iterator_t<Base>>;
    

    -19- Effects: Equivalent to: return x.current_ <=> y.current_;

  3. Modify [range.elements.iterator] as indicated:

    namespace std::ranges {
      template<class V, size_t N>
      template<bool Const>
      class elements_view<V, N>::iterator {
        […]
        friend constexpr compare_three_way_result_t<iterator_t<base-t>>auto 
          operator<=>(const iterator& x, const iterator& y)
            requires random_access_range<base-t> && three_way_comparable<iterator_t<base-t>>;
        […]
      };
      […]
    }
    
    […]
    friend constexpr compare_three_way_result_t<iterator_t<base-t>>auto
      operator<=>(const iterator& x, const iterator& y)
        requires random_access_range<base-t> && three_way_comparable<iterator_t<base-t>>;
    

    -18- Effects: Equivalent to: return x.current_ <=> y.current_;

Date: 2020-02-10.19:13:13

[ 2020-02 Prioritized as IMMEDIATE Monday morning in Prague ]

Date: 2020-02-07.00:00:00

[range.iota.iterator] and [range.transform.iterator] and [range.elements.iterator] all declare operator<=> similar to this:

friend constexpr compare_three_way_result_t<W> operator<=>(
    const iterator& x, const iterator& y)
  requires totally_ordered<W> && three_way_comparable<W>;

Similar to issue 3347 and issue 3387, this is ill-formed if three_way_comparable<W> is not satisfied, because compare_three_way_result_t<W> is invalid. This declaration is instantiated when the enclosing iterator type is instantiated, making any use of iota_view<W, B>::iterator ill-formed when three_way_comparable<W> is not satisfied.

We can either add an exposition-only safe-compare-three-way-result-t alias that denotes void or std::nonesuch for spaceship-less types, so the declaration is valid (and then disabled by the constraints), or simply make them return auto.

History
Date User Action Args
2021-02-25 10:48:01adminsetstatus: wp -> c++20
2020-02-24 16:02:59adminsetstatus: immediate -> wp
2020-02-10 19:13:13adminsetmessages: + msg11023
2020-02-10 19:13:13adminsetstatus: new -> immediate
2020-02-08 13:14:45adminsetmessages: + msg10994
2020-02-07 00:00:00admincreate