Skip to main content

std::ranges::replace_copy_if() algorithm

// (1)
constexpr replace_copy_if_result<I, O>
replace_copy_if( I first, S last, O result, Pred pred, const T& new_value,
Proj proj = {} );

// (2)
constexpr replace_copy_if_result<ranges::borrowed_iterator_t<R>, O>
replace_copy_if( R&& r, O result, Pred pred, const T& 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 T& >
  • R - std::input_range
  • Proj - (none)
  • T - (none)
  • Pred:
    • (1) - std::indirect_unary_predicate<std::projected<I, Proj>>
    • (2) - std::indirect_unary_predicate<std::projected<ranges::iterator_t<R>, Proj>>

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

Additionally, each overload has the following constraints:

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

With the helper types defined as follows:

template< class I, class O >
using replace_copy_if_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 satisfy the predicate pred with new_value.

    Uses std::invoke(pred, std::invoke(proj, *(first + (i - result)))) == true 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 to replace.

pred

Unary predicate which returns true if the element should be ignored.

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 applications of the corresponding predicate pred and any projection proj.

Exceptions

(none)

Possible implementation

replace_copy_if(1)
struct replace_copy_if_fn
{
template<std::input_iterator I, std::sentinel_for<I> S, class T,
std::output_iterator<const T&> O,
class Proj = std::identity, std::indirect_unary_predicate<
std::projected<I, Proj>> Pred>
requires std::indirectly_copyable<I, O>
constexpr ranges::replace_copy_if_result<I, O>
operator()(I first, S last, O result, Pred pred, const T& new_value,
Proj proj = {}) const
{
for (; first != last; ++first, ++result)
*result = std::invoke(pred, std::invoke(proj, *first)) ? new_value : *first;
return {std::move(first), std::move(result)};
}

template<ranges::input_range R, class T, std::output_iterator<const T&> O,
class Proj = std::identity,
std::indirect_unary_predicate<std::projected<ranges::iterator_t<R>, Proj>> Pred>
requires std::indirectly_copyable<ranges::iterator_t<R>, O>
constexpr ranges::replace_copy_if_result<ranges::borrowed_iterator_t<R>, O>
operator()(R&& r, O result, Pred pred, const T& new_value,
Proj proj = {}) const
{
return (*this)(ranges::begin(r), ranges::end(r), std::move(result),
std::move(pred), new_value, std::move(proj));
}
};

inline constexpr replace_copy_if_fn replace_copy_if {};

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_if() algorithm

// (1)
constexpr replace_copy_if_result<I, O>
replace_copy_if( I first, S last, O result, Pred pred, const T& new_value,
Proj proj = {} );

// (2)
constexpr replace_copy_if_result<ranges::borrowed_iterator_t<R>, O>
replace_copy_if( R&& r, O result, Pred pred, const T& 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 T& >
  • R - std::input_range
  • Proj - (none)
  • T - (none)
  • Pred:
    • (1) - std::indirect_unary_predicate<std::projected<I, Proj>>
    • (2) - std::indirect_unary_predicate<std::projected<ranges::iterator_t<R>, Proj>>

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

Additionally, each overload has the following constraints:

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

With the helper types defined as follows:

template< class I, class O >
using replace_copy_if_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 satisfy the predicate pred with new_value.

    Uses std::invoke(pred, std::invoke(proj, *(first + (i - result)))) == true 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 to replace.

pred

Unary predicate which returns true if the element should be ignored.

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 applications of the corresponding predicate pred and any projection proj.

Exceptions

(none)

Possible implementation

replace_copy_if(1)
struct replace_copy_if_fn
{
template<std::input_iterator I, std::sentinel_for<I> S, class T,
std::output_iterator<const T&> O,
class Proj = std::identity, std::indirect_unary_predicate<
std::projected<I, Proj>> Pred>
requires std::indirectly_copyable<I, O>
constexpr ranges::replace_copy_if_result<I, O>
operator()(I first, S last, O result, Pred pred, const T& new_value,
Proj proj = {}) const
{
for (; first != last; ++first, ++result)
*result = std::invoke(pred, std::invoke(proj, *first)) ? new_value : *first;
return {std::move(first), std::move(result)};
}

template<ranges::input_range R, class T, std::output_iterator<const T&> O,
class Proj = std::identity,
std::indirect_unary_predicate<std::projected<ranges::iterator_t<R>, Proj>> Pred>
requires std::indirectly_copyable<ranges::iterator_t<R>, O>
constexpr ranges::replace_copy_if_result<ranges::borrowed_iterator_t<R>, O>
operator()(R&& r, O result, Pred pred, const T& new_value,
Proj proj = {}) const
{
return (*this)(ranges::begin(r), ranges::end(r), std::move(result),
std::move(pred), new_value, std::move(proj));
}
};

inline constexpr replace_copy_if_fn replace_copy_if {};

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.