std::ranges...nges_result(3)
π NAME π
This is std::ranges...nges_result(3) from the C++ Standard Libary β the manual page for std::ranges::swap_ranges and std::ranges::swap_ranges_result, and the NAME line is literally std::ranges::swap_ranges,std::ranges::swap_ranges_result - std::ranges::swap_ranges,std::ranges::swap_ranges_result. Yes bestie, it said it twice, and honestly? Iconic.
β¨ Synopsis β¨
Defined in header <algorithm>
Call signature
(1) (since C++20)
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 );
(2) (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 );
Helper types
(3) (since C++20)
template< class I1, class I2 >
using swap_ranges_result = ranges::in_in_result<I1, I2>;
Okay so (1) is the iterator-pair version: it exchanges elements between the first range [first1, first1 + M) and the second range [first2, first2 + M) by calling 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. Not a vibe suggestion, bestie β do not overlap them.
(2) is the same as (1), but it uses r1 as the first range and r2 as the second range, as if it were 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}.
That's the return value. Cute, clean, no drama.
π¦ Complexity π¦
Exactly M swaps.
Not "around M", not "M-ish", not "vibes-based". Exactly M. Slay.
π 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)
Source/version: http://cppreference.com, 2024.06.10; date: 2024.06.10 β big mwah to the source, and that's the page, bestie πβ¨π
π¦ where this page comes from
- nixpkgs unstable: stdman 2024.07.05
- opensuse-leap 16.0: stdman 2024.07.05-bp160.1.9 Β· MIT
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms