24 Ranges library [ranges]

24.6 Range factories [range.factories]

24.6.3 Iota view [range.iota]

24.6.3.1 Overview [range.iota.overview]

iota_­view generates a sequence of elements by repeatedly incrementing an initial value.
The name views​::​iota denotes a customization point object ([customization.point.object]).
Given subexpressions E and F, the expressions views​::​iota(E) and views​::​iota(E, F) are expression-equivalent to iota_­view{E} and iota_­view{E, F}, respectively.
[Example
:
for (int i : iota_view{1, 10})
  cout << i << ' '; // prints: 1 2 3 4 5 6 7 8 9
— end example
]

24.6.3.2 Class template iota_­view [range.iota.view]

namespace std::ranges {
  template<class I>
    concept decrementable =     // exposition only
      see below;
  template<class I>
    concept advanceable =       // exposition only
      see below;

  template<weakly_incrementable W, semiregular Bound = unreachable_sentinel_t>
    requires weakly-equality-comparable-with<W, Bound> && semiregular<W>
  class iota_view : public view_interface<iota_view<W, Bound>> {
  private:
    // [range.iota.iterator], class iota_­view​::​iterator
    struct iterator;            // exposition only
    // [range.iota.sentinel], class iota_­view​::​sentinel
    struct sentinel;            // exposition only
    W value_ = W();             // exposition only
    Bound bound_ = Bound();     // exposition only
  public:
    iota_view() = default;
    constexpr explicit iota_view(W value);
    constexpr iota_view(type_identity_t<W> value,
                        type_identity_t<Bound> bound);
    constexpr iota_view(iterator first, sentinel last) : iota_view(*first, last.bound_) {}

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

    constexpr auto size() const requires see below;
  };

  template<class W, class Bound>
    requires (!is-integer-like<W> || !is-integer-like<Bound> ||
              (is-signed-integer-like<W> == is-signed-integer-like<Bound>))
    iota_view(W, Bound) -> iota_view<W, Bound>;
}
Let IOTA-DIFF-T(W) be defined as follows:
  • If W is not an integral type, or if it is an integral type and sizeof(iter_­difference_­t<W>) is greater than sizeof(W), then IOTA-DIFF-T(W) denotes iter_­difference_­t<W>.
  • Otherwise, IOTA-DIFF-T(W) is a signed integer type of width greater than the width of W if such a type exists.
  • Otherwise, IOTA-DIFF-T(W) is an unspecified signed-integer-like type ([iterator.concept.winc]) of width not less than the width of W.
    [Note
    : It is unspecified whether this type satisfies weakly_­incrementable. — end note
    ]
The exposition-only decrementable concept is equivalent to:
template<class I> concept decrementable = incrementable<I> && requires(I i) { { --i } -> same_­as<I&>; { i-- } -> same_­as<I>; };
When an object is in the domain of both pre- and post-decrement, the object is said to be decrementable.
Let a and b be equal objects of type I.
I models decrementable only if
  • If a and b are decrementable, then the following are all true:
  • If a and b are incrementable, then bool(--(++a) == b).
The exposition-only advanceable concept is equivalent to:
template<class I> concept advanceable = decrementable<I> && totally_­ordered<I> && requires(I i, const I j, const IOTA-DIFF-T(I) n) { { i += n } -> same_­as<I&>; { i -= n } -> same_­as<I&>; I(j + n); I(n + j); I(j - n); { j - j } -> convertible_­to<IOTA-DIFF-T(I)>; };
Let D be IOTA-DIFF-T(I).
Let a and b be objects of type I such that b is reachable from a after n applications of ++a, for some value n of type D.
I models advanceable only if
  • (a += n) is equal to b.
  • addressof(a += n) is equal to addressof(a).
  • I(a + n) is equal to (a += n).
  • For any two positive values x and y of type D, if I(a + D(x + y)) is well-defined, then I(a + D(x + y)) is equal to I(I(a + x) + y).
  • I(a + D(0)) is equal to a.
  • If I(a + D(n - 1)) is well-defined, then I(a + n) is equal to [](I c) { return ++c; }(I(a + D(n - 1))).
  • (b += -n) is equal to a.
  • (b -= n) is equal to a.
  • addressof(b -= n) is equal to addressof(b).
  • I(b - n) is equal to (b -= n).
  • D(b - a) is equal to n.
  • D(a - b) is equal to D(-n).
  • bool(a <= b) is true.
constexpr explicit iota_view(W value);
Preconditions: Bound denotes unreachable_­sentinel_­t or Bound() is reachable from value.
Effects: Initializes value_­ with value.
constexpr iota_view(type_identity_t<W> value, type_identity_t<Bound> bound);
Preconditions: Bound denotes unreachable_­sentinel_­t or bound is reachable from value.
When W and Bound model totally_­ordered_­with, then bool(value <= bound) is true.
Effects: Initializes value_­ with value and bound_­ with bound.
constexpr iterator begin() const;
Effects: Equivalent to: return iterator{value_­};
constexpr auto end() const;
Effects: Equivalent to:
if constexpr (same_as<Bound, unreachable_sentinel_t>)
  return unreachable_sentinel;
else
  return sentinel{bound_};
constexpr iterator end() const requires same_­as<W, Bound>;
Effects: Equivalent to: return iterator{bound_­};
constexpr auto size() const requires see below;
Effects: Equivalent to:
if constexpr (is-integer-like<W> && is-integer-like<Bound>)
  return (value_ < 0)
    ? ((bound_ < 0)
      ? to-unsigned-like(-value_) - to-unsigned-like(-bound_)
      : to-unsigned-like(bound_) + to-unsigned-like(-value_))
    : to-unsigned-like(bound_) - to-unsigned-like(value_);
else
  return to-unsigned-like(bound_ - value_);
Remarks: The expression in the requires-clause is equivalent to
(same_as<W, Bound> && advanceable<W>) || (integral<W> && integral<Bound>) ||
  sized_sentinel_for<Bound, W>

24.6.3.3 Class iota_­view​::​iterator [range.iota.iterator]

namespace std::ranges {
  template<weakly_incrementable W, semiregular Bound>
    requires weakly-equality-comparable-with<W, Bound>
  struct iota_view<W, Bound>::iterator {
  private:
    W value_ = W();             // exposition only
  public:
    using iterator_concept = see below;
    using iterator_category = input_iterator_tag;
    using value_type = W;
    using difference_type = IOTA-DIFF-T(W);

    iterator() = default;
    constexpr explicit iterator(W value);

    constexpr W operator*() const noexcept(is_nothrow_copy_constructible_v<W>);

    constexpr iterator& operator++();
    constexpr void operator++(int);
    constexpr iterator operator++(int) requires incrementable<W>;

    constexpr iterator& operator--() requires decrementable<W>;
    constexpr iterator operator--(int) requires decrementable<W>;

    constexpr iterator& operator+=(difference_type n)
      requires advanceable<W>;
    constexpr iterator& operator-=(difference_type n)
      requires advanceable<W>;
    constexpr W operator[](difference_type n) const
      requires advanceable<W>;

    friend constexpr bool operator==(const iterator& x, const iterator& y)
      requires equality_comparable<W>;

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

    friend constexpr iterator operator+(iterator i, difference_type n)
      requires advanceable<W>;
    friend constexpr iterator operator+(difference_type n, iterator i)
      requires advanceable<W>;

    friend constexpr iterator operator-(iterator i, difference_type n)
      requires advanceable<W>;
    friend constexpr difference_type operator-(const iterator& x, const iterator& y)
      requires advanceable<W>;
  };
}
iterator​::​iterator_­concept is defined as follows:
  • If W models advanceable, then iterator_­concept is random_­access_­iterator_­tag.
  • Otherwise, if W models decrementable, then iterator_­concept is bidirectional_­iterator_­tag.
  • Otherwise, if W models incrementable, then iterator_­concept is forward_­iterator_­tag.
  • Otherwise, iterator_­concept is input_­iterator_­tag.
[Note
:
Overloads for iter_­move and iter_­swap are omitted intentionally.
— end note
]
constexpr explicit iterator(W value);
Effects: Initializes value_­ with value.
constexpr W operator*() const noexcept(is_nothrow_copy_constructible_v<W>);
Effects: Equivalent to: return value_­;
[Note
:
The noexcept clause is needed by the default iter_­move implementation.
— end note
]
constexpr iterator& operator++();
Effects: Equivalent to:
++value_;
return *this;
constexpr void operator++(int);
Effects: Equivalent to ++*this.
constexpr iterator operator++(int) requires incrementable<W>;
Effects: Equivalent to:
auto tmp = *this;
++*this;
return tmp;
constexpr iterator& operator--() requires decrementable<W>;
Effects: Equivalent to:
--value_;
return *this;
constexpr iterator operator--(int) requires decrementable<W>;
Effects: Equivalent to:
auto tmp = *this;
--*this;
return tmp;
constexpr iterator& operator+=(difference_type n) requires advanceable<W>;
Effects: Equivalent to:
if constexpr (is-integer-like<W> && !is-signed-integer-like<W>) {
  if (n >= difference_type(0))
    value_ += static_cast<W>(n);
  else
    value_ -= static_cast<W>(-n);
} else {
  value_ += n;
}
return *this;
constexpr iterator& operator-=(difference_type n) requires advanceable<W>;
Effects: Equivalent to:
if constexpr (is-integer-like<W> && !is-signed-integer-like<W>) {
  if (n >= difference_type(0))
    value_ -= static_cast<W>(n);
  else
    value_ += static_cast<W>(-n);
} else {
  value_ -= n;
}
return *this;
constexpr W operator[](difference_type n) const requires advanceable<W>;
Effects: Equivalent to: return W(value_­ + n);
friend constexpr bool operator==(const iterator& x, const iterator& y) requires equality_comparable<W>;
Effects: Equivalent to: return x.value_­ == y.value_­;
friend constexpr bool operator<(const iterator& x, const iterator& y) requires totally_­ordered<W>;
Effects: Equivalent to: return x.value_­ < y.value_­;
friend constexpr bool operator>(const iterator& x, const iterator& y) requires totally_­ordered<W>;
Effects: Equivalent to: return y < x;
friend constexpr bool operator<=(const iterator& x, const iterator& y) requires totally_­ordered<W>;
Effects: Equivalent to: return !(y < x);
friend constexpr bool operator>=(const iterator& x, const iterator& y) requires totally_­ordered<W>;
Effects: Equivalent to: return !(x < y);
friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires totally_­ordered<W> && three_­way_­comparable<W>;
Effects: Equivalent to: return x.value_­ <=> y.value_­;
friend constexpr iterator operator+(iterator i, difference_type n) requires advanceable<W>;
Effects: Equivalent to: return i += n;
friend constexpr iterator operator+(difference_type n, iterator i) requires advanceable<W>;
Effects: Equivalent to: return i + n;
friend constexpr iterator operator-(iterator i, difference_type n) requires advanceable<W>;
Effects: Equivalent to: return i -= n;
friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires advanceable<W>;
Effects: Equivalent to:
using D = difference_type;
if constexpr (is-integer-like<W>) {
  if constexpr (is-signed-integer-like<W>)
    return D(D(x.value_) - D(y.value_));
  else
    return (y.value_ > x.value_)
      ? D(-D(y.value_ - x.value_))
      : D(x.value_ - y.value_);
} else {
  return x.value_ - y.value_;
}

24.6.3.4 Class iota_­view​::​sentinel [range.iota.sentinel]

namespace std::ranges {
  template<weakly_incrementable W, semiregular Bound>
    requires weakly-equality-comparable-with<W, Bound>
  struct iota_view<W, Bound>::sentinel {
  private:
    Bound bound_ = Bound();     // exposition only
  public:
    sentinel() = default;
    constexpr explicit sentinel(Bound bound);

    friend constexpr bool operator==(const iterator& x, const sentinel& y);

    friend constexpr iter_difference_t<W> operator-(const iterator& x, const sentinel& y)
      requires sized_sentinel_for<Bound, W>;
    friend constexpr iter_difference_t<W> operator-(const sentinel& x, const iterator& y)
      requires sized_sentinel_for<Bound, W>;
  };
}
constexpr explicit sentinel(Bound bound);
Effects: Initializes bound_­ with bound.
friend constexpr bool operator==(const iterator& x, const sentinel& y);
Effects: Equivalent to: return x.value_­ == y.bound_­;
friend constexpr iter_difference_t<W> operator-(const iterator& x, const sentinel& y) requires sized_­sentinel_­for<Bound, W>;
Effects: Equivalent to: return x.value_­ - y.bound_­;
friend constexpr iter_difference_t<W> operator-(const sentinel& x, const iterator& y) requires sized_­sentinel_­for<Bound, W>;
Effects: Equivalent to: return -(y - x);