std::ranges::swap_ranges,std::ranges::swap_ranges_result(3)

NAME
std::ranges::swap_ranges,std::ranges::swap_ranges_result - std::ranges::swap_ranges,std::ranges::swap_ranges_result

Synopsis
   Defined in header <algorithm>
   Call signature
   template< std::input_iterator I1, std::sentinel_for<I1> S1,
             std::input_iterator I2, std::sentinel_for<I2> S2 > (since
   requires std::indirectly_swappable<I1, I2> (1) C++20)
   constexpr swap_ranges_result<I1, I2>
       swap_ranges( I1 first1, S1 last1, I2 first2, S2 last2 );
   template< ranges::input_range R1, ranges::input_range R2 >
   requires std::indirectly_swappable<ranges::iterator_t<R1>,
   ranges::iterator_t<R2>> (2) (since
   constexpr swap_ranges_result<ranges::borrowed_iterator_t<R1>, C++20)
                        ranges::borrowed_iterator_t<R2>>
       swap_ranges( R1&& r1, R2&& r2 );

Helper types
   template< class I1, class I2 > (3) (since
   using swap_ranges_result = ranges::in_in_result<I1, I2>; C++20)
   1) Exchanges elements between first range [first1, first1 + M) and second range
   [first2, first2 + M) via ranges::iter_swap(first1 + i, first2 + i), where M =
   ranges::min(ranges::distance(first1, last1), ranges::distance(first2, last2)).
   The ranges [first1, last1) and [first2, last2) must not overlap.
   2) Same as (1), but uses r1 as the first range and r2 as the second range, as if
   using ranges::begin(r1) as first1, ranges::end(r1) as last1, ranges::begin(r2) as
   first2, and ranges::end(r2) as last2.
   The function-like entities described on this page are niebloids, that is:
     * Explicit template argument lists cannot be specified when calling any of them.
     * None of them are visible to argument-dependent lookup.
     * When any of them are found by normal unqualified lookup as the name to the left
       of the function-call operator, argument-dependent lookup is inhibited.
   In practice, they may be implemented as function objects, or with special compiler
   extensions.

Parameters
   first1, last1 - the first range of elements to swap
   first2, last2 - the second range of elements to swap
   r1 - the first range of elements to swap
   r2 - the second range of elements to swap.

Return value
   {first1 + M, first2 + M}.

Complexity
   Exactly M swaps.

Notes
   Implementations (e.g. MSVC STL) may enable vectorization when the iterator type
   models contiguous_iterator and swapping its value type calls neither non-trivial
   special member function nor ADL-found swap.

Possible implementation
   struct swap_ranges_fn
   {
       template<std::input_iterator I1, std::sentinel_for<I1> S1,
                std::input_iterator I2, std::sentinel_for<I2> S2>
       requires std::indirectly_swappable<I1, I2>
       constexpr ranges::swap_ranges_result<I1, I2>
           operator()(I1 first1, S1 last1, I2 first2, S2 last2) const
       {
           for (; !(first1 == last1 or first2 == last2); ++first1, ++first2)
               ranges::iter_swap(first1, first2);
           return {std::move(first1), std::move(first2)};
       }
       template<ranges::input_range R1, ranges::input_range R2>
       requires std::indirectly_swappable<ranges::iterator_t<R1>, ranges::iterator_t<R2>>
       constexpr ranges::swap_ranges_result<ranges::borrowed_iterator_t<R1>,
                        ranges::borrowed_iterator_t<R2>>
           operator()(R1&& r1, R2&& r2) const
       {
           return (*this)(ranges::begin(r1), ranges::end(r1),
                        ranges::begin(r2), ranges::end(r2));
       }
   };
   inline constexpr swap_ranges_fn swap_ranges {};

Example
// Run this code
 #include <algorithm>
 #include <iostream>
 #include <list>
 #include <string_view>
 #include <vector>
 auto print(std::string_view name, auto const& seq, std::string_view term = "\n")
 {
     std::cout << name << " : ";
     for (const auto& elem : seq)
         std::cout << elem << ' ';
     std::cout << term;
 }
 int main()
 {
     std::vector<char> p {'A', 'B', 'C', 'D', 'E'};
     std::list<char> q {'1', '2', '3', '4', '5', '6'};
     print("p", p);
     print("q", q, "\n\n");
     // swap p[0, 2) and q[1, 3):
     std::ranges::swap_ranges(p.begin(),
                        p.begin() + 4,
                        std::ranges::next(q.begin(), 1),
                        std::ranges::next(q.begin(), 3));
     print("p", p);
     print("q", q, "\n\n");
     // swap p[0, 5) and q[0, 5):
     std::ranges::swap_ranges(p, q);
     print("p", p);
     print("q", q);
 }

Output:
 p : A B C D E
 q : 1 2 3 4 5 6
 p : 2 3 C D E
 q : 1 A B 4 5 6
 p : 1 A B 4 5
 q : 2 3 C D E 6

See also
   iter_swap swaps the values referenced by two dereferenceable objects
   (C++20) (customization point object)
   ranges::swap swaps the values of two objects
   (C++20) (customization point object)
   swap_ranges swaps two ranges of elements
                (function template)
   iter_swap swaps the elements pointed to by two iterators
                (function template)
   swap swaps the values of two objects
                (function template)