std::ranges::views::iota, std::ranges::iota_view

< cpp‎ | ranges
template<std::weakly_incrementable W,

         std::semiregular Bound = std::unreachable_sentinel_t>
    requires __WeaklyEqualityComparableWith<W, Bound> && std::semiregular<W>

class iota_view : public ranges::view_interface<iota_view<W, Bound>>
(1) (since C++20)
namespace views {

    inline constexpr /*unspecified*/ iota = /*unspecified*/;

(2) (since C++20)
1) A range factory that generates a sequence of elements by repeatedly incrementing an initial value. Can be both bounded and unbounded (infinite)
2) views::iota(E) and views::iota(E, F) are expression-equivalent to (has the same effect as) iota_view{E} and iota_view{E, F} respectively for any suitable subexpressions E and F


[edit] Expression-equivalent

Expression e is expression-equivalent to expression f, if e and f have the same effects, either are both potentially-throwing or are both not potentially-throwing (i.e. noexcept(e) == noexcept(f)), and either are both constant subexpressions or are both not constant subexpressions.

[edit] Helper templates

template<std::weakly_incrementable W, std::semiregular Bound>
inline constexpr bool enable_borrowed_range<ranges::iota_view<W, Bound>> = true;

This specialization of std::ranges::enable_borrowed_range makes iota_view satisfy borrowed_range.

[edit] Data members


W value_ = W(); /* exposition-only */

the current value


Bound bound_ = Bound(); /* exposition-only */

the bound (defaults to std::unreachable_sentinel_t)

[edit] Member functions


iota_view() = default;
constexpr explicit iota_view(W value);
constexpr iota_view(std::type_identity_t<W> value,
                    std::type_identity_t<Bound> bound);
1) Default-initializes value_ and bound_
2) Initializes value_ with value and expects that Bound is either unreachable_sentinel_t (the default) or Bound() is reachable from value. This constructor is used to create unbounded iota views, e.g. iota(0) yields numbers 0,1,2..., infinitely.
3) Initializes value_ with value and bound_ with bound. This constructor is used to create bounded iota views, e.g. iota(10, 20) yields numbers from 10 to 19.


value - the starting value
bound - the bound


constexpr iterator begin() const;

Returns the iterator initialized with value_


constexpr auto end() const;
constexpr iterator end() const requires std::same_as<W, Bound>;
1) Returns the sentinel initialized with bound_ if this view is bounded, or std::unreachable_sentinel if this view is unbounded.
2) Returns the iterator initialized with bound_.


constexpr auto size() const

  requires (std::same_as<W, Bound> && __Advanceable<W>) ||
           (std::integral<W> && std::integral<Bound>) ||
             std::sized_sentinel_for<Bound, W>
  if constexpr (__is_integer_like<W> && __is_integer_like<Bound>)
    return (value_ < 0)
      ? ((bound_ < 0)
        ? __make_unsigned_like(-value_) - __make_unsigned_like(-bound_)
        : __make_unsigned_like(bound_) + __make_unsigned_like(-value_))
      : __make_unsigned_like(bound_) - __make_unsigned_like(value_);
    return __make_unsigned_like(bound_ - value_);


Returns the size of the view if the view is bounded.

[edit] Deduction guides

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>;

Note that the guide protects itself against signed/unsigned mismatch bugs, like views::iota(0, v.size()), where 0 is a (signed) int and v.size() is an (unsigned) std::size_t.

[edit] Nested classes


template<class W, class Bound>
struct iota_view<W, Bound>::iterator; /* exposition-only */

The return type of iota_view::begin.

This is a random_access_iterator if W models __Advanceable, a bidirectional_iterator if W models __Decrementable, a forward_iterator if W models incrementable, and input_iterator otherwise. However, it is only a LegacyInputIterator.


constexpr explicit iterator(W value);

Initializes exposition-only data member value_ with value. This value will be returned by operator* and incremented by operator++


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

returns the current value, by value (in other words, this is a read-only view)


constexpr iterator& operator++()
constexpr void operator++(int)
constexpr iterator operator++(int) requires std::incrementable<W>;
1) Equivalent to ++value_; return *this;
2) Equivalent to ++value_;
3) Equivalent to auto tmp = *this; ++value_; return tmp;


constexpr iterator& operator--() requires __Decrementable<W>;
constexpr iterator operator--(int) requires __Decrementable<W>;
1) Equivalent to --value_; return *this;
2) Equivalent to auto tmp = *this; --value_; return tmp;


constexpr W operator[](difference_type n) const requires __Advanceable<W>;

Equivalent to return W(value_ + n);

Other members as expected of an iterator.


template<class W, class Bound>
struct iota_view<W, Bound>::sentinel; /* exposition-only */

The return type of iota_view::end.


Bound bound_ = Bound(); /* exposition only */

Exposition-only data member holding the sentinel (typically either a number, for a bounded iota view, or an instance of std::unreachable_sentinel_t for an unbounded iota view.


sentinel() = default;
constexpr explicit sentinel(Bound bound);

Initializes exposition-only data member bound_ with bound.


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

Equivalent to: x.value_ == y.bound_;.


friend constexpr std::iter_difference_t<W>

    operator-(const iterator& x, const sentinel& y)

    requires std::sized_sentinel_for<Bound, W>;
friend constexpr std::iter_difference_t<W>

    operator-(const sentinel& x, const iterator& y)

    requires std::sized_sentinel_for<Bound, W>;
1) Equivalent to return x.value_ - y.bound_;.
2) Equivalent to return -(y.value_ - x.bound_);.

[edit] Example

#include <ranges>
#include <iostream>
int main()
    for (int i : std::ranges::iota_view{1, 10})
        std::cout << i << ' ';
    std::cout << '\n';
    for (int i : std::views::iota(1, 10))
        std::cout << i << ' ';
    std::cout << '\n';
    for (int i : std::views::iota(1) | std::views::take(9))
        std::cout << i << ' ';
    std::cout << '\n';


1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9