23 Ranges library [ranges]

23.8 Range adaptors [range.adaptors]

23.8.5 Transform view [range.transform]

23.8.5.1 Overview [range.transform.overview]

transform_­view presents a View of an underlying sequence after applying a transformation function to each element.
[Example
:
vector<int> is{ 0, 1, 2, 3, 4 };
transform_view squares{is, [](int i) { return i * i; }};
for (int i : squares)
  cout << i << ' '; // prints: 0 1 4 9 16
end example
]

23.8.5.2 Class template transform_­view [range.transform.view]

namespace std::ranges {
  template<InputRange V, CopyConstructible F>
    requires View<V> && is_object_v<F> &&
             RegularInvocable<F&, iter_reference_t<iterator_t<V>>>
  class transform_view : public view_interface<transform_view<V, F>> {
  private:
    template<bool> struct iterator;             // exposition only
    template<bool> struct sentinel;             // exposition only

    V base_ = V();                              // exposition only
    semiregular<F> fun_;                        // exposition only

  public:
    transform_view() = default;
    constexpr transform_view(V base, F fun);
    template<InputRange R>
      requires ViewableRange<R> && Constructible<V, all_view<R>>
    constexpr transform_view(R&& r, F fun);

    constexpr V base() const;

    constexpr iterator<false> begin();
    constexpr iterator<true> begin() const
      requires Range<const V> &&
               RegularInvocable<const F&, iter_reference_t<iterator_t<const V>>>;

    constexpr sentinel<false> end();
    constexpr iterator<false> end() requires CommonRange<V>;
    constexpr sentinel<true> end() const
      requires Range<const V> &&
               RegularInvocable<const F&, iter_reference_t<iterator_t<const V>>>;
    constexpr iterator<true> end() const
      requires CommonRange<const V> &&
               RegularInvocable<const F&, iter_reference_t<iterator_t<const V>>>;

    constexpr auto size() requires SizedRange<V> { return ranges::size(base_); }
    constexpr auto size() const requires SizedRange<const V>
    { return ranges::size(base_); }
  };

  template<class R, class F>
    transform_view(R&&, F) -> transform_view<all_view<R>, F>;
}
constexpr transform_view(V base, F fun);
Effects: Initializes base_­ with std::move(base) and fun_­ with std::move(fun).
template<InputRange R> requires ViewableRange<R> && Constructible<V, all_view<R>> constexpr transform_view(R&& r, F fun);
Effects: Initializes base_­ with view::all(std::forward<R>(r)) and fun_­ with std::move(fun).
constexpr V base() const;
Effects: Equivalent to: return base_­;
constexpr iterator<false> begin();
Effects: Equivalent to:
return iterator<false>{*this, ranges::begin(base_)};
constexpr iterator<true> begin() const requires Range<const V> && RegularInvocable<const F&, iter_reference_t<iterator_t<const V>>>;
Effects: Equivalent to:
return iterator<true>{*this, ranges::begin(base_)};
constexpr sentinel<false> end();
Effects: Equivalent to:
return sentinel<false>{ranges::end(base_)};
constexpr iterator<false> end() requires CommonRange<V>;
Effects: Equivalent to:
return iterator<false>{*this, ranges::end(base_)};
constexpr sentinel<true> end() const requires Range<const V> && RegularInvocable<const F&, iter_reference_t<iterator_t<const V>>>;
Effects: Equivalent to:
return sentinel<true>{ranges::end(base_)};
constexpr iterator<true> end() const requires CommonRange<const V> && RegularInvocable<const F&, iter_reference_t<iterator_t<const V>>>;
Effects: Equivalent to:
return iterator<true>{*this, ranges::end(base_)};

23.8.5.3 Class template transform_­view​::​iterator [range.transform.iterator]

namespace std::ranges {
  template<class V, class F>
  template<bool Const>
  class transform_view<V, F>::iterator {
  private:
    using Parent =                              // exposition only
      conditional_t<Const, const transform_view, transform_view>;
    using Base   =                              // exposition only
      conditional_t<Const, const V, V>;
    iterator_t<Base> current_ =                 // exposition only
      iterator_t<Base>();
    Parent* parent_ = nullptr;                  // exposition only
  public:
    using iterator_concept  = see below;
    using iterator_category = see below;
    using value_type        =
      remove_cvref_t<invoke_result_t<F&, iter_reference_t<iterator_t<Base>>>>;
    using difference_type   = iter_difference_t<iterator_t<Base>>;

    iterator() = default;
    constexpr iterator(Parent& parent, iterator_t<Base> current);
    constexpr iterator(iterator<!Const> i)
      requires Const && ConvertibleTo<iterator_t<V>, iterator_t<Base>>;

    constexpr iterator_t<Base> base() const;
    constexpr decltype(auto) operator*() const
    { return invoke(*parent_->fun_, *current_); }

    constexpr iterator& operator++();
    constexpr void operator++(int);
    constexpr iterator operator++(int) requires ForwardRange<Base>;

    constexpr iterator& operator--() requires BidirectionalRange<Base>;
    constexpr iterator operator--(int) requires BidirectionalRange<Base>;

    constexpr iterator& operator+=(difference_type n)
      requires RandomAccessRange<Base>;
    constexpr iterator& operator-=(difference_type n)
      requires RandomAccessRange<Base>;
    constexpr decltype(auto) operator[](difference_type n) const
      requires RandomAccessRange<Base>
    { return invoke(*parent_->fun_, current_[n]); }

    friend constexpr bool operator==(const iterator& x, const iterator& y)
      requires EqualityComparable<iterator_t<Base>>;
    friend constexpr bool operator!=(const iterator& x, const iterator& y)
      requires EqualityComparable<iterator_t<Base>>;

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

    friend constexpr iterator operator+(iterator i, difference_type n)
      requires RandomAccessRange<Base>;
    friend constexpr iterator operator+(difference_type n, iterator i)
      requires RandomAccessRange<Base>;

    friend constexpr iterator operator-(iterator i, difference_type n)
      requires RandomAccessRange<Base>;
    friend constexpr difference_type operator-(const iterator& x, const iterator& y)
      requires RandomAccessRange<Base>;

    friend constexpr decltype(auto) iter_move(const iterator& i)
      noexcept(noexcept(invoke(*i.parent_->fun_, *i.current_)))
    {
      if constexpr (is_lvalue_reference_v<decltype(*i)>)
        return std::move(*i);
      else
        return *i;
    }

    friend constexpr void iter_swap(const iterator& x, const iterator& y)
      noexcept(noexcept(ranges::iter_swap(x.current_, y.current_)))
      requires IndirectlySwappable<iterator_t<Base>>;
  };
}
iterator::iterator_­concept is defined as follows:
  • If V models RandomAccessRange, then iterator_­concept denotes random_­access_­iterator_­tag.
  • Otherwise, if V models BidirectionalRange, then iterator_­concept denotes bidirectional_­iterator_­tag.
  • Otherwise, if V models ForwardRange, then iterator_­concept denotes forward_­iterator_­tag.
  • Otherwise, iterator_­concept denotes input_­iterator_­tag.
Let C denote the type iterator_­traits<iterator_­t<Base>>::iterator_­category.
If C models DerivedFrom<contiguous_­iterator_­tag>, then iterator_­category denotes random_­access_­iterator_­tag; otherwise, iterator_­category denotes C.
constexpr iterator(Parent& parent, iterator_t<Base> current);
Effects: Initializes current_­ with current and parent_­ with addressof(parent).
constexpr iterator(iterator<!Const> i) requires Const && ConvertibleTo<iterator_t<V>, iterator_t<Base>>;
Effects: Initializes current_­ with std::move(i.current_­) and parent_­ with i.parent_­.
constexpr iterator_t<Base> base() const;
Effects: Equivalent to: return current_­;
constexpr iterator& operator++();
Effects: Equivalent to:
++current_;
return *this;
constexpr void operator++(int);
Effects: Equivalent to ++current_­.
constexpr iterator operator++(int) requires ForwardRange<Base>;
Effects: Equivalent to:
auto tmp = *this;
++*this;
return tmp;
constexpr iterator& operator--() requires BidirectionalRange<Base>;
Effects: Equivalent to:
--current_;
return *this;
constexpr iterator operator--(int) requires BidirectionalRange<Base>;
Effects: Equivalent to:
auto tmp = *this;
--*this;
return tmp;
constexpr iterator& operator+=(difference_type n) requires RandomAccessRange<Base>;
Effects: Equivalent to:
current_ += n;
return *this;
constexpr iterator& operator-=(difference_type n) requires RandomAccessRange<Base>;
Effects: Equivalent to:
current_ -= n;
return *this;
friend constexpr bool operator==(const iterator& x, const iterator& y) requires EqualityComparable<iterator_t<Base>>;
Effects: Equivalent to: return x.current_­ == y.current_­;
friend constexpr bool operator!=(const iterator& x, const iterator& y) requires EqualityComparable<iterator_t<Base>>;
Effects: Equivalent to: return !(x == y);
friend constexpr bool operator<(const iterator& x, const iterator& y) requires RandomAccessRange<Base>;
Effects: Equivalent to: return x.current_­ < y.current_­;
friend constexpr bool operator>(const iterator& x, const iterator& y) requires RandomAccessRange<Base>;
Effects: Equivalent to: return y < x;
friend constexpr bool operator<=(const iterator& x, const iterator& y) requires RandomAccessRange<Base>;
Effects: Equivalent to: return !(y < x);
friend constexpr bool operator>=(const iterator& x, const iterator& y) requires RandomAccessRange<Base>;
Effects: Equivalent to: return !(x < y);
friend constexpr iterator operator+(iterator i, difference_type n) requires RandomAccessRange<Base>; friend constexpr iterator operator+(difference_type n, iterator i) requires RandomAccessRange<Base>;
Effects: Equivalent to: return iterator{*i.parent_­, i.current_­ + n};
friend constexpr iterator operator-(iterator i, difference_type n) requires RandomAccessRange<Base>;
Effects: Equivalent to: return iterator{*i.parent_­, i.current_­ - n};
friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires RandomAccessRange<Base>;
Effects: Equivalent to: return x.current_­ - y.current_­;
friend constexpr void iter_swap(const iterator& x, const iterator& y) noexcept(noexcept(ranges::iter_swap(x.current_, y.current_))) requires IndirectlySwappable<iterator_t<Base>>;
Effects: Equivalent to ranges::iter_­swap(x.current_­, y.current_­).

23.8.5.4 Class template transform_­view​::​sentinel [range.transform.sentinel]

namespace std::ranges {
  template<class V, class F>
  template<bool Const>
  class transform_view<V, F>::sentinel {
  private:
    using Parent =                                      // exposition only
      conditional_t<Const, const transform_view, transform_view>;
    using Base = conditional_t<Const, const V, V>;      // exposition only
    sentinel_t<Base> end_ = sentinel_t<Base>();         // exposition only
  public:
    sentinel() = default;
    constexpr explicit sentinel(sentinel_t<Base> end);
    constexpr sentinel(sentinel<!Const> i)
      requires Const && ConvertibleTo<sentinel_t<V>, sentinel_t<Base>>;

    constexpr sentinel_t<Base> base() const;

    friend constexpr bool operator==(const iterator<Const>& x, const sentinel& y);
    friend constexpr bool operator==(const sentinel& x, const iterator<Const>& y);
    friend constexpr bool operator!=(const iterator<Const>& x, const sentinel& y);
    friend constexpr bool operator!=(const sentinel& x, const iterator<Const>& y);

    friend constexpr iter_difference_t<iterator_t<Base>>
      operator-(const iterator<Const>& x, const sentinel& y)
        requires SizedSentinel<sentinel_t<Base>, iterator_t<Base>>;
    friend constexpr iter_difference_t<iterator_t<Base>>
      operator-(const sentinel& y, const iterator<Const>& x)
        requires SizedSentinel<sentinel_t<Base>, iterator_t<Base>>;
  };
}
constexpr explicit sentinel(sentinel_t<Base> end);
Effects: Initializes end_­ with end.
constexpr sentinel(sentinel<!Const> i) requires Const && ConvertibleTo<sentinel_t<V>, sentinel_t<Base>>;
Effects: Initializes end_­ with std::move(i.end_­).
constexpr sentinel_t<Base> base() const;
Effects: Equivalent to: return end_­;
friend constexpr bool operator==(const iterator<Const>& x, const sentinel& y);
Effects: Equivalent to: return x.current_­ == y.end_­;
friend constexpr bool operator==(const sentinel& x, const iterator<Const>& y);
Effects: Equivalent to: return y == x;
friend constexpr bool operator!=(const iterator<Const>& x, const sentinel& y);
Effects: Equivalent to: return !(x == y);
friend constexpr bool operator!=(const sentinel& x, const iterator<Const>& y);
Effects: Equivalent to: return !(y == x);
friend constexpr iter_difference_t<iterator_t<Base>> operator-(const iterator<Const>& x, const sentinel& y) requires SizedSentinel<sentinel_t<Base>, iterator_t<Base>>;
Effects: Equivalent to: return x.current_­ - y.end_­;
friend constexpr iter_difference_t<iterator_t<Base>> operator-(const sentinel& y, const iterator<Const>& x) requires SizedSentinel<sentinel_t<Base>, iterator_t<Base>>;
Effects: Equivalent to: return x.end_­ - y.current_­;

23.8.5.5 view​::​transform [range.transform.adaptor]

The name view::transform denotes a range adaptor object ([range.adaptor.object]).
For some subexpressions E and F, the expression view::transform(E, F) is expression-equivalent to transform_­view{E, F}.