std::ranges::subrange(3)

NAME
std::ranges::subrange - std::ranges::subrange

Synopsis
   Defined in header <ranges>
   template<
   std::input_or_output_iterator I,
   std::sentinel_for<I> S = I,
   ranges::subrange_kind K = std::sized_sentinel_for<S, I> ?
   ranges::subrange_kind::sized : ranges::subrange_kind::unsized (since C++20)
   >
   requires (K == ranges::subrange_kind::sized ||
   !std::sized_sentinel_for<S, I>)
   class subrange : public ranges::view_interface<subrange<I, S, K>>
   The subrange class template combines together an iterator and a sentinel into a
   single view.
   Additionally, the subrange is a sized_range whenever the final template parameter is
   subrange_kind::sized (which happens when std::sized_sentinel_for<S, I> is
   satisfied or when size is passed explicitly as a constructor argument). The size
   record is needed to be stored if and only if std::sized_sentinel_for<S, I> is false
   and K is subrange_kind::sized.

Member functions
   constructor creates a new subrange
   (C++20) (public member function)
   operator PairLike converts the subrange to a pair-like type
   (C++20) (public member function)

Observers
   begin obtains the iterator
   (C++20) (public member function)
   end obtains the sentinel
   (C++20) (public member function)
   empty checks whether the subrange is empty
   (C++20) (public member function)
   size obtains the size of the subrange
   (C++20) (public member function)

Iterator operations
   advance advances the iterator by given distance
   (C++20) (public member function)
   prev obtains a copy of the subrange with its iterator decremented by a
   (C++20) given distance
                     (public member function)
   next obtains a copy of the subrange with its iterator advanced by a
   (C++20) given distance
                     (public member function)
         Inherited from std::ranges::view_interface
   operator bool Returns whether the derived view is not empty. Provided if
   (C++20) ranges::empty is applicable to it.
                     (public member function of std::ranges::view_interface<D>)
   data Gets the address of derived view's data. Provided if its iterator
   (C++20) type satisfies contiguous_iterator.
                     (public member function of std::ranges::view_interface<D>)
   front Returns the first element in the derived view. Provided if it
   (C++20) satisfies forward_range.
                     (public member function of std::ranges::view_interface<D>)
   back Returns the last element in the derived view. Provided if it
   (C++20) satisfies bidirectional_range and common_range.
                     (public member function of std::ranges::view_interface<D>)
   operator[] Returns the nth element in the derived view. Provided if it
   (C++20) satisfies random_access_range.
                     (public member function of std::ranges::view_interface<D>)
  Deduction guides

Non-member functions
   get(std::ranges::subrange) obtains iterator or sentinel from a std::ranges::subrange
   (C++20) (function template)

Helper types
   ranges::subrange_kind specifies whether a std::ranges::subrange
   (C++20) models std::ranges::sized_range
                        (enum)
   std::tuple_size<std::ranges::subrange> obtains the number of components of a
   (C++20) std::ranges::subrange
                        (class template specialization)
   std::tuple_element<std::ranges::subrange> obtains the type of the iterator or the
   (C++20) sentinel of a std::ranges::subrange
                        (class template specialization)
  Helper templates
   template<class I, class S, ranges::subrange_kind K>
   inline constexpr bool enable_borrowed_range<ranges::subrange<I, S, K>> = true;
   This specialization of std::ranges::enable_borrowed_range makes subrange satisfy
   borrowed_range.

Example
// Run this code
 #include <iostream>
 #include <map>
 #include <ranges>
 #include <string_view>
 template <class V> void mutate(V& v) { v += 'A' - 'a'; }
 template <class K, class V>
 void mutate_map_values(std::multimap<K, V>& m, K k) {
     auto [first, last] = m.equal_range(k);
     for (auto& [_, v] : std::ranges::subrange(first, last)) {
         mutate(v);
     }
 }
 int main()
 {
     auto print = [](std::string_view rem, auto const& mm) {
         std::cout << rem << "{ ";
         for (const auto& [k, v] : mm) std::cout << "{" << k << ",'" << v << "'} ";
         std::cout << "}\n";
     };
     std::multimap<int,char> mm{ {4,'a'}, {3,'-'}, {4,'b'}, {5,'-'}, {4,'c'} };
     print("Before: ", mm);
     mutate_map_values(mm, 4);
     print("After: ", mm);
 }

Output:
 Before: { {3,'-'} {4,'a'} {4,'b'} {4,'c'} {5,'-'} }
 After: { {3,'-'} {4,'A'} {4,'B'} {4,'C'} {5,'-'} }

See also
   ranges::view_interface helper class template for defining a view, using the
   (C++20) curiously recurring template pattern
                        (class template)