cpp / latest / algorithm / ranges / swap_ranges.html /

std::ranges::swap_ranges, std::ranges::swap_ranges_result

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 >
requires  std::indirectly_swappable<I1, I2>
constexpr swap_ranges_result<I1, I2>
          swap_ranges( I1 first1, S1 last1, I2 first2, S2 last2 );
(1) (since C++20)
template< ranges::input_range R1, ranges::input_range R2 >
requires  std::indirectly_swappable<ranges::iterator_t<R1>, ranges::iterator_t<R2>>
constexpr swap_ranges_result<ranges::borrowed_iterator_t<R1>,
                             ranges::borrowed_iterator_t<R2>>
          swap_ranges( R1&& r1, R2&& r2 );
(2) (since C++20)
Helper types
template< class I1, class I2 >
using swap_ranges_result = ranges::in_in_result<I1, I2>;
(3) (since C++20)
1) Exchanges elements between first range [first1, first1 + M) and second range [first2, first2 + M), 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:

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

#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

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

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/algorithm/ranges/swap_ranges