Skip to main content

std::ranges::copy_backward() algorithm

// (1)
constexpr copy_backward_result<I1, I2>
copy_backward( I1 first, S1 last, I2 result );

// (2)
constexpr copy_backward_result<ranges::borrowed_iterator_t<R>, I>
copy_backward( R&& r, I result );

The type of arguments are generic and have following constraints:

  • I, I2 - std::bidirectonal_iterator
  • S - std::sentinel_for<I1>
  • (2) - R - std::ranges::bidirectional_range

Additionally, each overload has the following constraints:

  • (1) - std::indirectly_copyable<I1, I2>
  • (2) - std::indirectly_copyable<ranges::iterator_t<R>, I>

With the helper types defined as follows:

template< class I1, class I2 >
using copy_backward_result = ranges::in_out_result<I1, I2>;
  • (1) Copies the elements from the range, defined by [first; last), to another range [result - N; result), where N = ranges::distance(first, last).
    The elements are copied in reverse order (the last element is copied first), but their relative order is preserved.

    Undefined Behaviour

    The behavior is undefined if result is within the range [first; last). In this case, ranges::copy_ 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 copy.

r

The range of elements to copy.

result

The destination range.

Return value

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

{
last,
result - N
}

Complexity

Exactly N assignments.

Exceptions

(none)

Possible implementation

copy_backward(1) and copy_backward(2)
struct copy_backward_fn
{
template<std::bidirectional_iterator I1, std::sentinel_for<I1> S1,
std::bidirectional_iterator I2>
requires std::indirectly_copyable<I1, I2>
constexpr ranges::copy_backward_result<I1, I2>
operator()(I1 first, S1 last, I2 result) const
{
I1 last1 {ranges::next(first, std::move(last))};
for (I1 i {last1}; i != first;)
*--result = *--i;
return {std::move(last1), std::move(result)};
}

template<ranges::bidirectional_range R, std::bidirectional_iterator I>
requires std::indirectly_copyable<ranges::iterator_t<R>, I>
constexpr ranges::copy_backward_result<ranges::borrowed_iterator_t<R>, I>
operator()(R&& r, I result) const
{
return (*this)(ranges::begin(r), ranges::end(r), std::move(result));
}
};

inline constexpr copy_backward_fn copy_backward{};

Notes

When copying overlapping ranges, ranges::copy is appropriate when copying to the left (beginning of the destination range is outside the source range),
while ranges::copy_backward is appropriate when copying to the right (end of the destination range is outside the source range).

Examples

Main.cpp
#include <algorithm>
#include <iostream>
#include <ranges>
#include <string_view>
#include <vector>

void print(std::string_view rem, std::ranges::forward_range auto const& r)
{
for (std::cout << rem << ": "; auto const& elem : r)
std::cout << elem << ' ';
std::cout << '\n';
}

int main()
{
const auto src = {1, 2, 3, 4};
print("src", src);

std::vector<int> dst(src.size() + 2);
std::ranges::copy_backward(src, dst.end());
print("dst", dst);

std::ranges::fill(dst, 0);
const auto [in, out] =
std::ranges::copy_backward(src.begin(), src.end() - 2, dst.end());
print("dst", dst);

std::cout
<< "(in - src.begin) == " << std::distance(src.begin(), in) << '\n'
<< "(out - dst.begin) == " << std::distance(dst.begin(), out) << '\n';
}
Output
src: 1 2 3 4
dst: 0 0 1 2 3 4
dst: 0 0 0 0 1 2
(in - src.begin) == 2
(out - dst.begin) == 4
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::copy_backward() algorithm

// (1)
constexpr copy_backward_result<I1, I2>
copy_backward( I1 first, S1 last, I2 result );

// (2)
constexpr copy_backward_result<ranges::borrowed_iterator_t<R>, I>
copy_backward( R&& r, I result );

The type of arguments are generic and have following constraints:

  • I, I2 - std::bidirectonal_iterator
  • S - std::sentinel_for<I1>
  • (2) - R - std::ranges::bidirectional_range

Additionally, each overload has the following constraints:

  • (1) - std::indirectly_copyable<I1, I2>
  • (2) - std::indirectly_copyable<ranges::iterator_t<R>, I>

With the helper types defined as follows:

template< class I1, class I2 >
using copy_backward_result = ranges::in_out_result<I1, I2>;
  • (1) Copies the elements from the range, defined by [first; last), to another range [result - N; result), where N = ranges::distance(first, last).
    The elements are copied in reverse order (the last element is copied first), but their relative order is preserved.

    Undefined Behaviour

    The behavior is undefined if result is within the range [first; last). In this case, ranges::copy_ 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 copy.

r

The range of elements to copy.

result

The destination range.

Return value

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

{
last,
result - N
}

Complexity

Exactly N assignments.

Exceptions

(none)

Possible implementation

copy_backward(1) and copy_backward(2)
struct copy_backward_fn
{
template<std::bidirectional_iterator I1, std::sentinel_for<I1> S1,
std::bidirectional_iterator I2>
requires std::indirectly_copyable<I1, I2>
constexpr ranges::copy_backward_result<I1, I2>
operator()(I1 first, S1 last, I2 result) const
{
I1 last1 {ranges::next(first, std::move(last))};
for (I1 i {last1}; i != first;)
*--result = *--i;
return {std::move(last1), std::move(result)};
}

template<ranges::bidirectional_range R, std::bidirectional_iterator I>
requires std::indirectly_copyable<ranges::iterator_t<R>, I>
constexpr ranges::copy_backward_result<ranges::borrowed_iterator_t<R>, I>
operator()(R&& r, I result) const
{
return (*this)(ranges::begin(r), ranges::end(r), std::move(result));
}
};

inline constexpr copy_backward_fn copy_backward{};

Notes

When copying overlapping ranges, ranges::copy is appropriate when copying to the left (beginning of the destination range is outside the source range),
while ranges::copy_backward is appropriate when copying to the right (end of the destination range is outside the source range).

Examples

Main.cpp
#include <algorithm>
#include <iostream>
#include <ranges>
#include <string_view>
#include <vector>

void print(std::string_view rem, std::ranges::forward_range auto const& r)
{
for (std::cout << rem << ": "; auto const& elem : r)
std::cout << elem << ' ';
std::cout << '\n';
}

int main()
{
const auto src = {1, 2, 3, 4};
print("src", src);

std::vector<int> dst(src.size() + 2);
std::ranges::copy_backward(src, dst.end());
print("dst", dst);

std::ranges::fill(dst, 0);
const auto [in, out] =
std::ranges::copy_backward(src.begin(), src.end() - 2, dst.end());
print("dst", dst);

std::cout
<< "(in - src.begin) == " << std::distance(src.begin(), in) << '\n'
<< "(out - dst.begin) == " << std::distance(dst.begin(), out) << '\n';
}
Output
src: 1 2 3 4
dst: 0 0 1 2 3 4
dst: 0 0 0 0 1 2
(in - src.begin) == 2
(out - dst.begin) == 4
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.