Skip to main content

std::ranges::replace_copy() algorithm

// (1)
constexpr replace_copy_result<I, O>
replace_copy( I first, S last, O result, const T1& old_value, const T2& new_value,
Proj proj = {} );

// (2)
constexpr replace_copy_result<ranges::borrowed_iterator_t<R>, O>
replace_copy( R&& r, O result, const T1& old_value, const T2& new_value,
Proj proj = {} );

The type of arguments are generic and have the following constraints:

  • I - std::input_iterator
  • S - std::sentinel_for<I>
  • O - std::output_iterator<const T2&>
  • R - std::input_range
  • T1 - (none)
  • T2 - (none)
  • Proj - (none)

The Proj template argument has a default type of std::identity for all overloads.

Additionally, each overload has the following constraints:

  • (1):
    indirectly_copyable<I, O>
    && indirect_binary_predicate<ranges::equal_to, projected<I, Proj>, const T1*>
  • (2):
    indirectly_copyable<ranges::iterator_t<R>, O>
    && indirect_binary_predicate<ranges::equal_to, projected<ranges::iterator_t<R>, Proj>, const T1*>

(The std:: namespace was ommitted here for readability)

With the helper types defined as follows:

template< class I, class O >
using replace_copy_result = ranges::in_out_result<I, O>;
  • (1) Copies the elements from the source range [first; last) to the destination range beginning at result, replacing all elements that are equal to old_value with new_value.

    Uses std::invoke(proj, *(first + (i - result))) to compare.

  • (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.

Undefined Behaviour

The behavior is undefined

if the source and destination ranges overlap.

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 beginning of the destination range.

old_value

The value of elements to replace.

new_value

The value to use as a replacement.

proj

The projection to apply to the elements.

Return value

{
last,
result + N
}

Where N is the size of the source range.

Complexity

Given N as:

  • (1) - ranges::distance(first, last)
  • (2) - ranges::distance(r)

Exactly N comparisons after projecting with proj.

Exceptions

(none)

Possible implementation

replace_copy(1) and replace_copy(2)
struct replace_copy_fn
{
template<std::input_iterator I, std::sentinel_for<I> S, class T1, class T2,
std::output_iterator<const T2&> O, class Proj = std::identity>
requires std::indirectly_copyable<I, O> &&
std::indirect_binary_predicate<ranges::equal_to,
std::projected<I, Proj>, const T1*>
constexpr ranges::replace_copy_result<I, O>
operator()(I first, S last, O result, const T1& old_value, const T2& new_value,
Proj proj = {}) const
{
for (; first != last; ++first, ++result)
*result = (std::invoke(proj, *first) == old_value) ? new_value : *first;
return {std::move(first), std::move(result)};
}

template<ranges::input_range R, class T1, class T2,
std::output_iterator<const T2&> O, class Proj = std::identity>
requires std::indirectly_copyable<ranges::iterator_t<R>, O> &&
std::indirect_binary_predicate<ranges::equal_to,
std::projected<ranges::iterator_t<R>, Proj>, const T1*>
constexpr ranges::replace_copy_result<ranges::borrowed_iterator_t<R>, O>
operator()(R&& r, O result, const T1& old_value, const T2& new_value,
Proj proj = {}) const
{
return (*this)(ranges::begin(r), ranges::end(r), std::move(result),
old_value, new_value, std::move(proj));
}
};

inline constexpr replace_copy_fn replace_copy {};

Examples

Main.cpp
#include <algorithm>
#include <array>
#include <iostream>
#include <vector>

int main()
{
auto print = [](const auto rem, const auto& v)
{
for (std::cout << rem << ": "; const auto& e : v)
std::cout << e << ' ';
std::cout << '\n';
};

std::vector<int> o;

std::array p {1, 6, 1, 6, 1, 6};
o.resize(p.size());
print("p", p);
std::ranges::replace_copy(p, o.begin(), 6, 9);
print("o", o);

std::array q {1, 2, 3, 6, 7, 8, 4, 5};
o.resize(q.size());
print("q", q);
std::ranges::replace_copy_if(q, o.begin(), [](int x) { return 5 < x; }, 5);
print("o", o);
}
Output

p: 1 6 1 6 1 6
o: 1 9 1 9 1 9
q: 1 2 3 6 7 8 4 5
o: 1 2 3 5 5 5 4 5
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::replace_copy() algorithm

// (1)
constexpr replace_copy_result<I, O>
replace_copy( I first, S last, O result, const T1& old_value, const T2& new_value,
Proj proj = {} );

// (2)
constexpr replace_copy_result<ranges::borrowed_iterator_t<R>, O>
replace_copy( R&& r, O result, const T1& old_value, const T2& new_value,
Proj proj = {} );

The type of arguments are generic and have the following constraints:

  • I - std::input_iterator
  • S - std::sentinel_for<I>
  • O - std::output_iterator<const T2&>
  • R - std::input_range
  • T1 - (none)
  • T2 - (none)
  • Proj - (none)

The Proj template argument has a default type of std::identity for all overloads.

Additionally, each overload has the following constraints:

  • (1):
    indirectly_copyable<I, O>
    && indirect_binary_predicate<ranges::equal_to, projected<I, Proj>, const T1*>
  • (2):
    indirectly_copyable<ranges::iterator_t<R>, O>
    && indirect_binary_predicate<ranges::equal_to, projected<ranges::iterator_t<R>, Proj>, const T1*>

(The std:: namespace was ommitted here for readability)

With the helper types defined as follows:

template< class I, class O >
using replace_copy_result = ranges::in_out_result<I, O>;
  • (1) Copies the elements from the source range [first; last) to the destination range beginning at result, replacing all elements that are equal to old_value with new_value.

    Uses std::invoke(proj, *(first + (i - result))) to compare.

  • (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.

Undefined Behaviour

The behavior is undefined

if the source and destination ranges overlap.

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 beginning of the destination range.

old_value

The value of elements to replace.

new_value

The value to use as a replacement.

proj

The projection to apply to the elements.

Return value

{
last,
result + N
}

Where N is the size of the source range.

Complexity

Given N as:

  • (1) - ranges::distance(first, last)
  • (2) - ranges::distance(r)

Exactly N comparisons after projecting with proj.

Exceptions

(none)

Possible implementation

replace_copy(1) and replace_copy(2)
struct replace_copy_fn
{
template<std::input_iterator I, std::sentinel_for<I> S, class T1, class T2,
std::output_iterator<const T2&> O, class Proj = std::identity>
requires std::indirectly_copyable<I, O> &&
std::indirect_binary_predicate<ranges::equal_to,
std::projected<I, Proj>, const T1*>
constexpr ranges::replace_copy_result<I, O>
operator()(I first, S last, O result, const T1& old_value, const T2& new_value,
Proj proj = {}) const
{
for (; first != last; ++first, ++result)
*result = (std::invoke(proj, *first) == old_value) ? new_value : *first;
return {std::move(first), std::move(result)};
}

template<ranges::input_range R, class T1, class T2,
std::output_iterator<const T2&> O, class Proj = std::identity>
requires std::indirectly_copyable<ranges::iterator_t<R>, O> &&
std::indirect_binary_predicate<ranges::equal_to,
std::projected<ranges::iterator_t<R>, Proj>, const T1*>
constexpr ranges::replace_copy_result<ranges::borrowed_iterator_t<R>, O>
operator()(R&& r, O result, const T1& old_value, const T2& new_value,
Proj proj = {}) const
{
return (*this)(ranges::begin(r), ranges::end(r), std::move(result),
old_value, new_value, std::move(proj));
}
};

inline constexpr replace_copy_fn replace_copy {};

Examples

Main.cpp
#include <algorithm>
#include <array>
#include <iostream>
#include <vector>

int main()
{
auto print = [](const auto rem, const auto& v)
{
for (std::cout << rem << ": "; const auto& e : v)
std::cout << e << ' ';
std::cout << '\n';
};

std::vector<int> o;

std::array p {1, 6, 1, 6, 1, 6};
o.resize(p.size());
print("p", p);
std::ranges::replace_copy(p, o.begin(), 6, 9);
print("o", o);

std::array q {1, 2, 3, 6, 7, 8, 4, 5};
o.resize(q.size());
print("q", q);
std::ranges::replace_copy_if(q, o.begin(), [](int x) { return 5 < x; }, 5);
print("o", o);
}
Output

p: 1 6 1 6 1 6
o: 1 9 1 9 1 9
q: 1 2 3 6 7 8 4 5
o: 1 2 3 5 5 5 4 5
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.