std::ranges...:replace_if(3)
π NAME π
okay bestie, this is the std::ranges...:replace_if(3) page from the C++ Standard Libary manual (that spelling is the manual's, not mine π
). The name line is:
std::ranges::replace,std::ranges::replace_if β std::ranges::replace,std::ranges::replace_if
πΈ Synopsis πΈ
Defined in header <algorithm>. Call signature time β I reflowed the line breaks so it's readable, but every token, default, requires clause, and since/until tag is still here. No cap.
π
replace β iterator form, (1)
(since C++20) (until C++26)
template< std::input_iterator I, std::sentinel_for<I> S,
class T1, class T2, class Proj = std::identity >
requires std::indirectly_writable<I, const T2&> &&
std::indirect_binary_predicate<ranges::equal_to,
std::projected<I, Proj>, const T1*>
constexpr I replace( I first, S last, const T1& old_value,
const T2& new_value, Proj proj = {} );
(since C++26)
template< std::input_iterator I, std::sentinel_for<I> S,
class Proj = std::identity,
class T1 = std::projected_value_t<I, Proj>, class T2 = T1 >
requires std::indirectly_writable<I, const T2&> &&
std::indirect_binary_predicate<ranges::equal_to,
std::projected<I, Proj>, const T1*>
constexpr I replace( I first, S last, const T1& old_value,
const T2& new_value, Proj proj = {} );
π
replace β range form, (2)
(since C++20) (until C++26)
template< ranges::input_range R,
class T1, class T2, class Proj = std::identity >
requires std::indirectly_writable<ranges::iterator_t<R>, const T2&> &&
std::indirect_binary_predicate<ranges::equal_to,
std::projected<ranges::iterator_t<R>, Proj>, const T1*>
constexpr ranges::borrowed_iterator_t<R>
replace( R&& r, const T1& old_value,
const T2& new_value, Proj proj = {} );
(since C++26)
template< ranges::input_range R,
class Proj = std::identity,
class T1 = std::projected_value_t<ranges::iterator_t<R>, Proj>,
class T2 = T1 >
requires std::indirectly_writable<ranges::iterator_t<R>, const T2&> &&
std::indirect_binary_predicate<ranges::equal_to,
std::projected<ranges::iterator_t<R>, Proj>, const T1*>
constexpr ranges::borrowed_iterator_t<R>
replace( R&& r, const T1& old_value,
const T2& new_value, Proj proj = {} );
π
replace_if β iterator form, (3)
(since C++20) (until C++26)
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 replace_if( I first, S last, Pred pred,
const T& new_value, Proj proj = {} );
(since C++26)
template< std::input_iterator I, std::sentinel_for<I> S,
class Proj = std::identity,
class T = std::projected_value_t<I, Proj>,
std::indirect_unary_predicate<std::projected<I, Proj>> Pred >
requires std::indirectly_writable<I, const T&>
constexpr I replace_if( I first, S last, Pred pred,
const T& new_value, Proj proj = {} );
π
replace_if β range form, (4)
(since C++20) (until C++26)
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>
replace_if( R&& r, Pred pred, const T& new_value, Proj proj = {} );
(since C++26)
template< ranges::input_range R, class Proj = std::identity,
class T = std::projected_value_t<ranges::iterator_t<R>, Proj>,
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>
replace_if( R&& r, Pred pred, const T& new_value, Proj proj = {} );
So the vibe is: these algorithms replace all elements satisfying specific criteria with new_value in the range [first, last).
1)Replaces all elements that are equal toold_value, usingstd::invoke(proj, *i) == old_valueto compare.3)Replaces all elements for which the predicatepredevaluates totrue, where the evaluating expression isstd::invoke(pred, std::invoke(proj, *i)).2,4)Same as(1,3), but usesras the range, as if usingranges::begin(r)asfirstandranges::end(r)aslast.
The function-like entities described on this page are niebloids, that is:
- Explicit template argument lists cannot be specified when calling any of them.
- None of them are visible to argument-dependent lookup.
- When any of them are found by normal unqualified lookup as the name to the left of the function-call operator, argument-dependent lookup is inhibited.
In practice, they may be implemented as function objects, or with special compiler extensions.
π«Ά Parameters π«Ά
first, lastβ the range of elements to processrβ the range of elements to processold_valueβ the value of elements to replacenew_valueβ the value to use as a replacementpredβ predicate to apply to the projected elementsprojβ projection to apply to the elements
π Return value π
An iterator equal to last.
β Complexity β
Exactly ranges::distance(first, last) applications of the corresponding predicate comp and any projection proj.
π Notes π
Because the algorithm takesold_valueandnew_valueby reference, it may have unexpected behavior if either is a reference to an element of the range[first, last).
π Feature-test macro π
__cpp_lib_algorithm_default_value_typeβ value202403, Std(C++26), feature: List-initialization for algorithms(1-4)
π§ Possible implementation π§
π
replace
struct replace_fn
{
template<std::input_iterator I, std::sentinel_for<I> S, class
Proj = std::identity,
class T1 = std::projected_value_t<I, Proj>, class T2 =
T1>
requires std::indirectly_writable<I, const T2&> &&
std::indirect_binary_predicate
<ranges::equal_to, std::projected<I, Proj>, const
T1*>
constexpr I operator()(I first, S last, const T1& old_value,
const T2& new_value, Proj proj = {}) const
{
for (; first != last; ++first)
if (old_value == std::invoke(proj, *first))
*first = new_value;
return first;
}
template<ranges::input_range R, class Proj = std::identity
class T1 = std::projected_value_t<ranges::iterator_t<R>,
Proj>,
class T2 = T1>
requires std::indirectly_writable<ranges::iterator_t<R>, const
T2&> &&
std::indirect_binary_predicate<ranges::equal_to,
std::projected<ranges::iterator_t<R>, Proj>, const T1*>
constexpr ranges::borrowed_iterator_t<R>
operator()(R&& r, const T1& old_value,
const T2& new_value, Proj proj = {}) const
{
return (*this)(ranges::begin(r), ranges::end(r), old_value,
new_value, std::move(proj));
}
};
inline constexpr replace_fn replace {};
π
replace_if
struct replace_if_fn
{
template<std::input_iterator I, std::sentinel_for<I> S,
class Proj = std::identity, class T =
std::projected_value_t<I, Proj>,
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 Proj = std::identity,
class T = std::projected_value_t<ranges::iterator_t<R>,
Proj>
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 {};
π Example π
okay so this is the whole demo, bestie β run it and vibe check the output right after π
// Run this code
#include <algorithm>
#include <array>
#include <complex>
#include <iostream>
void println(const auto& v)
{
for (const auto& e : v)
std::cout << e << ' ';
std::cout << '\n';
}
int main()
{
namespace ranges = std::ranges;
std::array p{1, 6, 1, 6, 1, 6};
println(p);
ranges::replace(p, 6, 9);
println(p);
std::array q{1, 2, 3, 6, 7, 8, 4, 5};
println(q);
ranges::replace_if(q, [](int x) { return 5 < x; }, 5);
println(q);
std::array<std::complex<double>, 2> nums{{{1, 3}, {1, 3}}};
println(nums);
#ifdef __cpp_lib_algorithm_default_value_type
ranges::replace(nums, {1, 3}, {4, 2});
#else
ranges::replace(nums, std::complex<double>{1, 3},
std::complex<double>{4, 2});
#endif
println(nums);
}
π¨οΈ 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
(1,3) (1,3)
(4,2) (4,2)
π See also π
ranges::replace_copy(C++20) β copies a range, replacing elements satisfying specific criteria with another value (niebloid)ranges::replace_copy_if(C++20) β copies a range, replacing elements satisfying specific criteria with another value (niebloid)replaceβ replaces all values satisfying specific criteria with another value (function template)replace_ifβ replaces all values satisfying specific criteria with another value (function template)
π and that's the whole vibe, bestie β source/version: cppreference.com, 2024.06.10. slay! π
π¦ where this page comes from
- nixpkgs unstable: stdman 2024.07.05
- opensuse-leap 16.0: stdman 2024.07.05-bp160.1.9 Β· MIT
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms