Skip to main content

std::ranges::move() algorithm

// (1)
constexpr move_result<I, O>
move( I first, S last, O result );

// (2)
constexpr move_result<ranges::borrowed_iterator_t<R>, O>
move( R&& r, O result );

The type of arguments are generic and have following constraints:

  • I - std::input_iterator
  • S - std::sentinel_for<I>
  • O - std::weakly_incrementable
  • (2) - R - std::ranges::input_range

Additionally, each overload has the following contraints:

  • (1) - std::indirectly_movable<I, O>
  • (2) - std::indirectly_movable<ranges::iterator_t<R>, O>

With the helper types defined as follows:

template< class I, class O >
using move_result = ranges::in_out_result<I, O>;
  • (1) Moves the elements in the range, defined by [first; last), to another range beginning at result.

    The elements in the moved-from range will still contain valid values of the appropriate type, but not necessarily the same values as before the move.

    Undefined Behaviour

    The behavior is undefined if result is within the range [first; last). In this case, ranges::move_backward may be used instead.

  • (2) Same as (1), but uses r as the source range, as if using ranges::begin(r) as first and ranges::end(r) as last.

The function-like entities described on this page are niebloids.

Parameters

first
last

The range of elements to move.

r

The range of elements to move.

result

The beginning of the destination range.

Return value

A value of type ranges::move_result initialized as follows:

{
last,
result + N
}

Where N is the size of the range to move elements from.

Complexity

Exactly N move assignments.

Exceptions

(none)

Possible implementation

move(1) and move(2)
struct move_fn
{
template<std::input_iterator I, std::sentinel_for<I> S, std::weakly_incrementable O>
requires std::indirectly_movable<I, O>
constexpr ranges::move_result<I, O>
operator()(I first, S last, O result) const
{
for (; first != last; ++first, ++result)
*result = ranges::iter_move(first);
return {std::move(first), std::move(result)};
}
template<ranges::input_range R, std::weakly_incrementable O>
requires std::indirectly_movable<ranges::iterator_t<R>, O>
constexpr ranges::move_result<ranges::borrowed_iterator_t<R>, O>
operator()(R&& r, O result) const
{
return (*this)(ranges::begin(r), ranges::end(r), std::move(result));
}
};

inline constexpr move_fn move {};

Notes

When moving overlapping ranges, ranges::move is appropriate when moving to the left (beginning of the destination range is outside the source range),
while ranges::move_backward is appropriate when moving to the right (end of the destination range is outside the source range).

Examples

The following code moves thread objects (which themselves are non copyable) from one container to another.

Main.cpp
#include <algorithm>
#include <chrono>
#include <iostream>
#include <iterator>
#include <list>
#include <thread>
#include <vector>
using namespace std::literals::chrono_literals;

void f(std::chrono::milliseconds n)
{
std::this_thread::sleep_for(n);
std::cout << "thread with n=" << n.count() << "ms ended" << std::endl;
}

int main()
{
std::vector<std::jthread> v;
v.emplace_back(f, 400ms);
v.emplace_back(f, 600ms);
v.emplace_back(f, 800ms);

std::list<std::jthread> l;

// std::ranges::copy() would not compile, because std::jthread is non-copyable
std::ranges::move(v, std::back_inserter(l));
}
Output
thread with n=400ms ended
thread with n=600ms ended
thread with n=800ms ended
This article originates from this CppReference page. It was likely altered for improvements or editors' preference. Click "Edit this page" to see all changes made to this document.
Hover to see the original license.

std::ranges::move() algorithm

// (1)
constexpr move_result<I, O>
move( I first, S last, O result );

// (2)
constexpr move_result<ranges::borrowed_iterator_t<R>, O>
move( R&& r, O result );

The type of arguments are generic and have following constraints:

  • I - std::input_iterator
  • S - std::sentinel_for<I>
  • O - std::weakly_incrementable
  • (2) - R - std::ranges::input_range

Additionally, each overload has the following contraints:

  • (1) - std::indirectly_movable<I, O>
  • (2) - std::indirectly_movable<ranges::iterator_t<R>, O>

With the helper types defined as follows:

template< class I, class O >
using move_result = ranges::in_out_result<I, O>;
  • (1) Moves the elements in the range, defined by [first; last), to another range beginning at result.

    The elements in the moved-from range will still contain valid values of the appropriate type, but not necessarily the same values as before the move.

    Undefined Behaviour

    The behavior is undefined if result is within the range [first; last). In this case, ranges::move_backward may be used instead.

  • (2) Same as (1), but uses r as the source range, as if using ranges::begin(r) as first and ranges::end(r) as last.

The function-like entities described on this page are niebloids.

Parameters

first
last

The range of elements to move.

r

The range of elements to move.

result

The beginning of the destination range.

Return value

A value of type ranges::move_result initialized as follows:

{
last,
result + N
}

Where N is the size of the range to move elements from.

Complexity

Exactly N move assignments.

Exceptions

(none)

Possible implementation

move(1) and move(2)
struct move_fn
{
template<std::input_iterator I, std::sentinel_for<I> S, std::weakly_incrementable O>
requires std::indirectly_movable<I, O>
constexpr ranges::move_result<I, O>
operator()(I first, S last, O result) const
{
for (; first != last; ++first, ++result)
*result = ranges::iter_move(first);
return {std::move(first), std::move(result)};
}
template<ranges::input_range R, std::weakly_incrementable O>
requires std::indirectly_movable<ranges::iterator_t<R>, O>
constexpr ranges::move_result<ranges::borrowed_iterator_t<R>, O>
operator()(R&& r, O result) const
{
return (*this)(ranges::begin(r), ranges::end(r), std::move(result));
}
};

inline constexpr move_fn move {};

Notes

When moving overlapping ranges, ranges::move is appropriate when moving to the left (beginning of the destination range is outside the source range),
while ranges::move_backward is appropriate when moving to the right (end of the destination range is outside the source range).

Examples

The following code moves thread objects (which themselves are non copyable) from one container to another.

Main.cpp
#include <algorithm>
#include <chrono>
#include <iostream>
#include <iterator>
#include <list>
#include <thread>
#include <vector>
using namespace std::literals::chrono_literals;

void f(std::chrono::milliseconds n)
{
std::this_thread::sleep_for(n);
std::cout << "thread with n=" << n.count() << "ms ended" << std::endl;
}

int main()
{
std::vector<std::jthread> v;
v.emplace_back(f, 400ms);
v.emplace_back(f, 600ms);
v.emplace_back(f, 800ms);

std::list<std::jthread> l;

// std::ranges::copy() would not compile, because std::jthread is non-copyable
std::ranges::move(v, std::back_inserter(l));
}
Output
thread with n=400ms ended
thread with n=600ms ended
thread with n=800ms ended
This article originates from this CppReference page. It was likely altered for improvements or editors' preference. Click "Edit this page" to see all changes made to this document.
Hover to see the original license.