4001. iota_view should provide empty

Section: 25.6.4.2 [range.iota.view] Status: WP Submitter: Hewill Kang Opened: 2023-10-27 Last modified: 2023-11-22

Priority: Not Prioritized

View all other issues in [range.iota.view].

View all issues with WP status.

Discussion:

When iota_view's template parameter is not an integer type and does not model advanceable, its size member will not be provided as constraints are not satisfied.

If the type further fails to model the incrementable, this results in its view_interface base being unable to synthesize a valid empty member as iota_view will just be an input_range (demo):

#include <ranges>
#include <vector>
#include <iostream>

int main() {
  std::vector<int> v;
  auto it = std::back_inserter(v);
  auto s = std::ranges::subrange(it, std::unreachable_sentinel);
  auto r = std::views::iota(it);
  std::cout << s.empty() << "\n"; // 0
  std::cout << r.empty() << "\n"; // ill-formed
}

This seems to be an oversight. I don't see a reason why iota_view doesn't provide empty as it does store the start and end like subrange, in which case it's easy to tell if it's empty just by comparing the two.

[2023-11-02; Reflector poll]

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

[2023-11-11 Approved at November 2023 meeting in Kona. Status changed: Voting → WP.]

Proposed resolution:

This wording is relative to N4964.

  1. Modify 25.6.4.2 [range.iota.view], class template iota_view synopsis, as indicated:

    namespace std::ranges {
      […]
      template<weakly_incrementable W, semiregular Bound = unreachable_sentinel_t>
        requires weakly-equality-comparable-with<W, Bound> && copyable<W>
      class iota_view : public view_interface<iota_view<W, Bound>> {
      private:
        […]
        W value_ = W();                     // exposition only
        Bound bound_ = Bound();             // exposition only
      public:
        […]
        constexpr iterator begin() const;
        constexpr auto end() const;
        constexpr iterator end() const requires same_as<W, Bound>;
    
        constexpr bool empty() const;
        constexpr auto size() const requires see below;
      };
      […]
    }
    

    […]

    constexpr iterator end() const requires same_as<W, Bound>;
    

    -14- Effects: Equivalent to: return iterator{bound_};

    constexpr bool empty() const;
    

    -?- Effects: Equivalent to: return value_ == bound_;

    […]