Skip to main content

std::ranges::replace_if() algorithm

// (1)
constexpr I
replace_if( I first, S last, Pred pred, const T& new_value, Proj proj = {} );

// (2)
constexpr ranges::borrowed_iterator_t<R>
replace_if( R&& r, 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>
  • R - std::ranges::input_range
  • T - (none)
  • Proj - (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_writable<I, const T&>
  • (2) - std::indirectly_writable<ranges::iterator_t<R>, const T&>

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

  • (1) Replaces all elements for which the predicate pred evaluates to true, where evaluating expression is std::invoke(pred, std::invoke(proj, *i)).

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

Removing is done by shifting (by means of move assignment) the elements in the range in such a way that the elements that are not to be replaced appear in the beginning of the range.

important

Relative order of the elements that remain is preserved and the physical size of the container is unchanged.

warning

Iterators pointing to an element between the new logical end and the physical end of the range are still dereferenceable, but the elements themselves have unspecified values (as per MoveAssignable post-condition). (since C++11)

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

Parameters

first
last

The range of elements to process.

r

The range of elements to process.

new_value

The value to use as a replacement.

proj

Projection to apply to the elements.

pred

Unary predicate which returns true if the element value should be replaced.

Return value

An iterator equal to last.

Complexity

Exactly ranges::distance(first, last) applications of the corresponding predicate pred and any projection proj.

Exceptions

(none)

Possible implementation

replace_if(1)
struct replace_if_fn
{
template<std::input_iterator I, std::sentinel_for<I> S, class T,
class Proj = std::identity, std::indirect_unary_predicate<
std::projected<I, Proj>> Pred>
requires std::indirectly_writable<I, const T&>
constexpr I
operator()(I first, S last, Pred pred, const T& new_value, Proj proj = {}) const
{
for (; first != last; ++first)
if (!!std::invoke(pred, std::invoke(proj, *first)))
*first = new_value;
return std::move(first);
}

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

inline constexpr replace_if_fn replace_if {};

Notes

Because the algorithm takes old_value and new_value by reference, it may have unexpected behavior if either is a reference to an element of the range [first; last).

Examples

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

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

std::array p {1, 6, 1, 6, 1, 6};
print(p);
std::ranges::replace(p, 6, 9);
print(p);

std::array q {1, 2, 3, 6, 7, 8, 4, 5};
print(q);
std::ranges::replace_if(q, [](int x) { return 5 < x; }, 5);
print(q);
}
Output
1 6 1 6 1 6
1 9 1 9 1 9
1 2 3 6 7 8 4 5
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_if() algorithm

// (1)
constexpr I
replace_if( I first, S last, Pred pred, const T& new_value, Proj proj = {} );

// (2)
constexpr ranges::borrowed_iterator_t<R>
replace_if( R&& r, 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>
  • R - std::ranges::input_range
  • T - (none)
  • Proj - (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_writable<I, const T&>
  • (2) - std::indirectly_writable<ranges::iterator_t<R>, const T&>

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

  • (1) Replaces all elements for which the predicate pred evaluates to true, where evaluating expression is std::invoke(pred, std::invoke(proj, *i)).

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

Removing is done by shifting (by means of move assignment) the elements in the range in such a way that the elements that are not to be replaced appear in the beginning of the range.

important

Relative order of the elements that remain is preserved and the physical size of the container is unchanged.

warning

Iterators pointing to an element between the new logical end and the physical end of the range are still dereferenceable, but the elements themselves have unspecified values (as per MoveAssignable post-condition). (since C++11)

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

Parameters

first
last

The range of elements to process.

r

The range of elements to process.

new_value

The value to use as a replacement.

proj

Projection to apply to the elements.

pred

Unary predicate which returns true if the element value should be replaced.

Return value

An iterator equal to last.

Complexity

Exactly ranges::distance(first, last) applications of the corresponding predicate pred and any projection proj.

Exceptions

(none)

Possible implementation

replace_if(1)
struct replace_if_fn
{
template<std::input_iterator I, std::sentinel_for<I> S, class T,
class Proj = std::identity, std::indirect_unary_predicate<
std::projected<I, Proj>> Pred>
requires std::indirectly_writable<I, const T&>
constexpr I
operator()(I first, S last, Pred pred, const T& new_value, Proj proj = {}) const
{
for (; first != last; ++first)
if (!!std::invoke(pred, std::invoke(proj, *first)))
*first = new_value;
return std::move(first);
}

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

inline constexpr replace_if_fn replace_if {};

Notes

Because the algorithm takes old_value and new_value by reference, it may have unexpected behavior if either is a reference to an element of the range [first; last).

Examples

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

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

std::array p {1, 6, 1, 6, 1, 6};
print(p);
std::ranges::replace(p, 6, 9);
print(p);

std::array q {1, 2, 3, 6, 7, 8, 4, 5};
print(q);
std::ranges::replace_if(q, [](int x) { return 5 < x; }, 5);
print(q);
}
Output
1 6 1 6 1 6
1 9 1 9 1 9
1 2 3 6 7 8 4 5
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.