24 Ranges library [ranges]

24.6 Range factories [range.factories]

This subclause defines range factories, which are utilities to create a View.
Range factories are declared in namespace std::ranges::view.

24.6.1 Empty view [range.empty]

24.6.1.1 Overview [range.empty.overview]

empty_­view produces a View of no elements of a particular type.
[Example
:
empty_view<int> e;
static_assert(ranges::empty(e));
static_assert(0 == e.size());
end example
]

24.6.1.2 Class template empty_­view [range.empty.view]

namespace std::ranges {
  template<class T>
    requires is_object_v<T>
  class empty_view : public view_interface<empty_view<T>> {
  public:
    static constexpr T* begin() noexcept { return nullptr; }
    static constexpr T* end() noexcept { return nullptr; }
    static constexpr T* data() noexcept { return nullptr; }
    static constexpr ptrdiff_t size() noexcept { return 0; }
    static constexpr bool empty() noexcept { return true; }

    friend constexpr T* begin(empty_view) noexcept { return nullptr; }
    friend constexpr T* end(empty_view) noexcept { return nullptr; }
  };
}

24.6.2 Single view [range.single]

24.6.2.1 Overview [range.single.overview]

single_­view produces a View that contains exactly one element of a specified value.
[Example
:
single_view s{4};
for (int i : s)
  cout << i; // prints 4
end example
]

24.6.2.2 Class template single_­view [range.single.view]

namespace std::ranges {
  template<CopyConstructible T>
    requires is_object_v<T>
  class single_view : public view_interface<single_view<T>> {
  private:
    semiregular-box<T> value_;      // exposition only (see [range.semi.wrap])
  public:
    single_view() = default;
    constexpr explicit single_view(const T& t);
    constexpr explicit single_view(T&& t);
    template<class... Args>
      requires Constructible<T, Args...>
    constexpr single_view(in_place_t, Args&&... args);

    constexpr T* begin() noexcept;
    constexpr const T* begin() const noexcept;
    constexpr T* end() noexcept;
    constexpr const T* end() const noexcept;
    static constexpr ptrdiff_t size() noexcept;
    constexpr T* data() noexcept;
    constexpr const T* data() const noexcept;
  };
}
constexpr explicit single_view(const T& t);
Effects: Initializes value_­ with t.
constexpr explicit single_view(T&& t);
Effects: Initializes value_­ with std::move(t).
template<class... Args> constexpr single_view(in_place_t, Args&&... args);
Effects: Initializes value_­ as if by value_­{in_­place, std::forward<Args>(args)...}.
constexpr T* begin() noexcept; constexpr const T* begin() const noexcept;
Effects: Equivalent to: return data();
constexpr T* end() noexcept; constexpr const T* end() const noexcept;
Effects: Equivalent to: return data() + 1;
static constexpr ptrdiff_t size() noexcept;
Effects: Equivalent to: return 1;
constexpr T* data() noexcept; constexpr const T* data() const noexcept;
Effects: Equivalent to: return value_­.operator->();

24.6.2.3 view​::​single [range.single.adaptor]

The name view::single denotes a customization point object ([customization.point.object]).
For some subexpression E, the expression view::single(E) is expression-equivalent to single_­view{E}.

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.
[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<WeaklyIncrementable W, Semiregular Bound = unreachable_sentinel_t>
    requires weakly-equality-comparable-with<W, Bound>
  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 iterator begin() const;
    constexpr sentinel end() const;
    constexpr iterator end() const requires Same<W, Bound>;

    constexpr auto size() const
      requires (Same<W, Bound> && Advanceable<W>) ||
               (Integral<W> && Integral<Bound>) ||
               SizedSentinel<Bound, W>
    { return bound_ - value_; }
  };

  template<class W, class Bound>
    requires (!Integral<W> || !Integral<Bound> || is_signed_v<W> == is_signed_v<Bound>)
  iota_view(W, Bound) -> iota_view<W, Bound>;
}
The exposition-only Decrementable concept is equivalent to:
template<class I> concept Decrementable = Incrementable<I> && requires(I i) { { --i } -> Same<I&>; { i-- } -> Same<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> && StrictTotallyOrdered<I> && requires(I i, const I j, const iter_difference_t<I> n) { { i += n } -> Same<I&>; { i -= n } -> Same<I&>; { j + n } -> Same<I>; { n + j } -> Same<I>; { j - n } -> Same<I>; { j - j } -> Same<iter_difference_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 iter_­difference_­t<I>, and let D be iter_­difference_­t<I>.
I models Advanceable only if
  • (a += n) is equal to b.
  • addressof(a += n) is equal to addressof(a).
  • (a + n) is equal to (a += n).
  • For any two positive values x and y of type D, if (a + D(x + y)) is well-defined, then (a + D(x + y)) is equal to ((a + x) + y).
  • (a + D(0)) is equal to a.
  • If (a + D(n - 1)) is well-defined, then (a + n) is equal to ++(a + D(n - 1)).
  • (b += -n) is equal to a.
  • (b -= n) is equal to a.
  • addressof(b -= n) is equal to addressof(b).
  • (b - n) is equal to (b -= n).
  • (b - a) is equal to n.
  • (a - b) is equal to -n.
  • bool(a <= b) is true.
constexpr explicit iota_view(W value);
Expects: 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);
Expects: Bound denotes unreachable_­sentinel_­t or bound is reachable from value.
Effects: Initializes value_­ with value and bound_­ with bound.
constexpr iterator begin() const;
Effects: Equivalent to: return iterator{value_­};
constexpr sentinel end() const;
Effects: Equivalent to: return sentinel{bound_­};
constexpr iterator end() const requires Same<W, Bound>;
Effects: Equivalent to: return iterator{bound_­};

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

namespace std::ranges {
  template<class W, class Bound>
  struct iota_view<W, Bound>::iterator {
  private:
    W value_ = W();             // exposition only
  public:
    using iterator_category = see below;
    using value_type = W;
    using difference_type = iter_difference_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 EqualityComparable<W>;
    friend constexpr bool operator!=(const iterator& x, const iterator& y)
      requires EqualityComparable<W>;

    friend constexpr bool operator<(const iterator& x, const iterator& y)
      requires StrictTotallyOrdered<W>;
    friend constexpr bool operator>(const iterator& x, const iterator& y)
      requires StrictTotallyOrdered<W>;
    friend constexpr bool operator<=(const iterator& x, const iterator& y)
      requires StrictTotallyOrdered<W>;
    friend constexpr bool operator>=(const iterator& x, const iterator& y)
      requires StrictTotallyOrdered<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_­category is defined as follows:
  • If W models Advanceable, then iterator_­category is random_­access_­iterator_­tag.
  • Otherwise, if W models Decrementable, then iterator_­category is bidirectional_­iterator_­tag.
  • Otherwise, if W models Incrementable, then iterator_­category is forward_­iterator_­tag.
  • Otherwise, iterator_­category 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:
value_ += n;
return *this;
constexpr iterator& operator-=(difference_type n) requires Advanceable<W>;
Effects: Equivalent to:
value_ -= n;
return *this;
constexpr W operator[](difference_type n) const requires Advanceable<W>;
Effects: Equivalent to: return value_­ + n;
friend constexpr bool operator==(const iterator& x, const iterator& y) requires EqualityComparable<W>;
Effects: Equivalent to: return x.value_­ == y.value_­;
friend constexpr bool operator!=(const iterator& x, const iterator& y) requires EqualityComparable<W>;
Effects: Equivalent to: return !(x == y);
friend constexpr bool operator<(const iterator& x, const iterator& y) requires StrictTotallyOrdered<W>;
Effects: Equivalent to: return x.value_­ < y.value_­;
friend constexpr bool operator>(const iterator& x, const iterator& y) requires StrictTotallyOrdered<W>;
Effects: Equivalent to: return y < x;
friend constexpr bool operator<=(const iterator& x, const iterator& y) requires StrictTotallyOrdered<W>;
Effects: Equivalent to: return !(y < x);
friend constexpr bool operator>=(const iterator& x, const iterator& y) requires StrictTotallyOrdered<W>;
Effects: Equivalent to: return !(x < y);
friend constexpr iterator operator+(iterator i, difference_type n) requires Advanceable<W>;
Effects: Equivalent to: return iterator{i.value_­ + 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: return x.value_­ - y.value_­;

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

namespace std::ranges {
  template<class W, class 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 bool operator==(const sentinel& x, const iterator& y);
    friend constexpr bool operator!=(const iterator& x, const sentinel& y);
    friend constexpr bool operator!=(const sentinel& x, const iterator& y);
  };
}
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 bool operator==(const sentinel& x, const iterator& y);
Effects: Equivalent to: return y == x;
friend constexpr bool operator!=(const iterator& x, const sentinel& y);
Effects: Equivalent to: return !(x == y);
friend constexpr bool operator!=(const sentinel& x, const iterator& y);
Effects: Equivalent to: return !(y == x);

24.6.3.5 view​::​iota [range.iota.adaptor]

The name view::iota denotes a customization point object ([customization.point.object]).
For some subexpressions E and F, the expressions view::iota(E) and view::iota(E, F) are expression-equivalent to iota_­view{E} and iota_­view{E, F}, respectively.