This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++23 status.

3702. Should zip_transform_view::iterator remove operator<?

Section: 25.7.26.3 [range.zip.transform.iterator] Status: C++23 Submitter: Hewill Kang Opened: 2022-05-21 Last modified: 2023-11-22

Priority: Not Prioritized

View all issues with C++23 status.

Discussion:

After LWG 3692(i), zip_view::iterator only provides operator<=>. Since the comparison of zip_transform_view::iterator uses zip_view::iterator's operator<=>, it is possible to remove zip_transform_view::iterator's operator<, >, <=, >= and just detect if ziperator's operator<=> is available.

Since the ziperator's operator<=> is valid only when zip_view is a random_access_range, we don't need to additionally constrain the ziperator to be three_way_comparable.

[2022-06-21; Reflector poll]

Set status to Tentatively Ready after five votes in favour during reflector poll.

[2022-07-15; LWG telecon: move to Ready]

[2022-07-25 Approved at July 2022 virtual plenary. Status changed: Ready → WP.]

Proposed resolution:

This wording is relative to N4910.

  1. Modify 25.7.26.3 [range.zip.transform.iterator] as indicated:

    namespace std::ranges {
    […]
    template<copy_constructible F, input_range... Views>
    requires (view<Views> && ...) && (sizeof...(Views) > 0) && is_object_v<F> &&
             regular_invocable<F&, range_reference_t<Views>...> &&
             can-reference<invoke_result_t<F&, range_reference_t<Views>...>>
    template<bool Const>
    class zip_transform_view<F, Views...>::iterator {
      using Parent = maybe-const<Const, zip_transform_view>;        // exposition only
      using Base = maybe-const<Const, InnerView>;                   // exposition only
      Parent* parent_ = nullptr;                                    // exposition only
      ziperator<Const> inner_;                                      // exposition only
    
      constexpr iterator(Parent& parent, ziperator<Const> inner);   // exposition only
    public:
      […]
      friend constexpr bool operator==(const iterator& x, const iterator& y)
        requires equality_comparable<ziperator<Const>>;
      
      friend constexpr bool operator<(const iterator& x, const iterator& y)
        requires random_access_range<Base>;
      friend constexpr bool operator>(const iterator& x, const iterator& y)
        requires random_access_range<Base>;
      friend constexpr bool operator<=(const iterator& x, const iterator& y)
        requires random_access_range<Base>;
      friend constexpr bool operator>=(const iterator& x, const iterator& y)
        requires random_access_range<Base>;
      friend constexpr auto operator<=>(const iterator& x, const iterator& y)
        requires random_access_range<Base>&& three_way_comparable<ziperator<Const>>;
      […]
    };
    […]
    }
    
    […]
    friend constexpr bool operator==(const iterator& x, const iterator& y)
      requires equality_comparable<ziperator<Const>>;
    friend constexpr bool operator<(const iterator& x, const iterator& y)
      requires random_access_range<Base>;
    friend constexpr bool operator>(const iterator& x, const iterator& y)
      requires random_access_range<Base>;
    friend constexpr bool operator<=(const iterator& x, const iterator& y)
      requires random_access_range<Base>;
    friend constexpr bool operator>=(const iterator& x, const iterator& y)
      requires random_access_range<Base>;
    friend constexpr auto operator<=>(const iterator& x, const iterator& y)
      requires random_access_range<Base>&& three_way_comparable<ziperator<Const>>;
    

    -14- Let op be the operator.

    -15- Effects: Equivalent to: return x.inner_ op y.inner_;