std::swap_ranges(3)

πŸ“¦ version 2024.07.05, in nixpkgs unstable, opensuse-leap 16.0

✨ std::swap_ranges(3) ✨

okay bestie, welcome to the std::swap_ranges(3) page from the C++ Standard Libary manual πŸ’… this is the algorithm that swaps elements between two ranges, and honestly? it's giving useful, it's giving iconic, it's giving β€œwhy are we not using this already” energy ✨ let's get into it.


🌸 NAME 🌸

std::swap_ranges β€” literally std::swap_ranges, bestie. that's the name, no cap πŸ’–

πŸ¦‹ Synopsis πŸ¦‹

Defined in header <algorithm>

template< class ForwardIt1, class ForwardIt2 >

ForwardIt2 swap_ranges( ForwardIt1 first1, ForwardIt1    (1)
(constexpr since C++20)
last1,

                        ForwardIt2 first2 );
template< class ExecutionPolicy,

          class ForwardIt1, class ForwardIt2 >
ForwardIt2 swap_ranges( ExecutionPolicy&& policy,        (2) (since
C++17)
                        ForwardIt1 first1, ForwardIt1
last1,

                        ForwardIt2 first2 );
  1. swaps the elements in the range [first1, last1) with another range that has std::distance(first1, last1) elements, starting at first2 ✨
  2. same as (1), but it runs according to policy. this overload only joins overload resolution when std::is_execution_policy_v<std::decay_t<ExecutionPolicy>> is true (until C++20), and when std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>> is true (since C++20).

behavior is undefined if either of these is true, and yes this is the dramatic part 😭:

  • the two ranges overlap.
  • there's a pair of corresponding iterators iter1 and iter2 in the two ranges such that *iter1 is not Swappable with *iter2.

πŸ’– Parameters πŸ’–

  • first1, last1 β€” the first range of elements to swap.
  • first2 β€” beginning of the second range of elements to swap.
  • policy β€” the execution policy to use. see execution policy for details.

πŸŽ€ Type requirements πŸŽ€

  • ForwardIt1, ForwardIt2 must meet the requirements of LegacyForwardIterator.

⭐ Return value ⭐

you get back an iterator to the element just past the last element exchanged in the range beginning with first2 🫢

πŸ”₯ Complexity πŸ”₯

exactly std::distance(first1, last1) swaps. that's the count, bestie, no surprises, periodt πŸ’…

🌈 Exceptions 🌈

the overload with a template parameter named ExecutionPolicy reports errors like this:

  • if a function invoked as part of the algorithm throws an exception and ExecutionPolicy is one of the standard policies, std::terminate is called. for any other ExecutionPolicy, the behavior is implementation-defined.
  • if the algorithm fails to allocate memory, std::bad_alloc is thrown.

πŸ‘‘ Notes πŸ‘‘

some implementations (e.g. MSVC STL) may enable vectorization when the iterator type satisfies LegacyContiguousIterator and swapping its value type calls neither a non-trivial special member function nor an ADL-found swap. cute optimization behavior, iykyk 🧚

🧚 Possible implementation 🧚

template<class ForwardIt1, class ForwardIt2>
constexpr //< since C++20
ForwardIt2 swap_ranges(ForwardIt1 first1, ForwardIt1 last1,
ForwardIt2 first2)
{
    for (; first1 != last1; ++first1, ++first2)
        std::iter_swap(first1, first2);

    return first2;
}

πŸ“ Example πŸ“

this one demonstrates swapping subranges from different containers, and it ate, honestly:

// Run this code

#include <algorithm>
#include <iostream>
#include <list>
#include <vector>

auto print = [](auto comment, auto const& seq)
{
    std::cout << comment;
    for (const auto& e : seq)
        std::cout << e << ' ';
    std::cout << '\n';
};

int main()
{
    std::vector<char> v{'a', 'b', 'c', 'd', 'e'};
    std::list<char> l{'1', '2', '3', '4', '5'};

    print("Before swap_ranges:\n" "v: ", v);
    print("l: ", l);

    std::swap_ranges(v.begin(), v.begin() + 3, l.begin());

    print("After swap_ranges:\n" "v: ", v);
    print("l: ", l);
}

πŸ’œ Output πŸ’œ

Before swap_ranges:
v: a b c d e
l: 1 2 3 4 5
After swap_ranges:
v: 1 2 3 d e
l: a b c 4 5

πŸ¦‹ See also πŸ¦‹

  • iter_swap β€” swaps the elements pointed to by two iterators (function template).
  • swap β€” swaps the values of two objects (function template).
  • ranges::swap_ranges β€” swaps two ranges of elements (C++20) (niebloid).

mwah πŸ’– that's the whole page, sourced from http://cppreference.com, dated 2024.06.10 β€” now go swap those ranges and be the main character of your own iterator story, bestie πŸ’…βœ¨

πŸ“¦ where this page comes from