std::ranges::replace_copy, std::ranges::replace_copy_if, std::ranges::replace_copy_result, std::ranges::replace_copy_if_result
From cppreference.com
| Defined in header <algorithm>
|
||
| Call signature |
||
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>
replace_copy( I first, S last, O d_first, const T1& old_value,
const T2& new_value, Proj proj = {} );
|
(1) | (since C++20) (until C++26) |
template< std::input_iterator I, std::sentinel_for<I> S,
class O, class Proj = std::identity,
class T1 = std::projected_value_t<I, Proj>,
class T2 = std::iter_value_t<O> >
requires std::indirectly_copyable<I, O> &&
std::indirect_binary_predicate
<ranges::equal_to, std::projected<I, Proj>, const T1*> &&
std::output_iterator<O, const T2&>
constexpr ranges::replace_copy_result<I, O>
replace_copy( I first, S last, O d_first, const T1& old_value,
const T2& new_value, Proj proj = {} );
|
(since C++26) | |
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>
replace_copy( R&& r, O d_first, const T1& old_value,
const T2& new_value, Proj proj = {} );
|
(2) | (since C++20) (until C++26) |
template< ranges::input_range R,
class O, class Proj = std::identity,
class T1 = std::projected_value_t<ranges::iterator_t<R>, Proj>,
class T2 = std::iter_value_t<O> >
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*> &&
std::output_iterator<O, const T2&>
constexpr ranges::replace_copy_result<ranges::borrowed_iterator_t<R>, O>
replace_copy( R&& r, O d_first, const T1& old_value,
const T2& new_value, Proj proj = {} );
|
(since C++26) | |
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>
replace_copy_if( I first, S last, O d_first, Pred pred,
const T& new_value, Proj proj = {} );
|
(3) | (since C++20) (until C++26) |
template< std::input_iterator I, std::sentinel_for<I> S,
class O, class T = std::iter_value_t<O>
class Proj = std::identity,
std::indirect_unary_predicate<std::projected<I, Proj>> Pred >
requires std::indirectly_copyable<I, O> && std::output_iterator<O, const T&>
constexpr ranges::replace_copy_if_result<I, O>
replace_copy_if( I first, S last, O d_first, Pred pred,
const T& new_value, Proj proj = {} );
|
(since C++26) | |
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>
replace_copy_if( R&& r, O d_first, Pred pred,
const T& new_value, Proj proj = {} );
|
(4) | (since C++20) (until C++26) |
template< ranges::input_range R,
class O, class T = std::iter_value_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> &&
std::output_iterator<O, const T&>
constexpr ranges::replace_copy_if_result<ranges::borrowed_iterator_t<R>, O>
replace_copy_if( R&& r, O d_first, Pred pred,
const T& new_value, Proj proj = {} );
|
(since C++26) | |
template< /*execution-policy*/ Ep,
std::random_access_iterator I, std::sized_sentinel_for<I> S,
std::random_access_iterator O, std::sized_sentinel_for<O> OutS,
class Proj = std::identity,
class T1 = std::projected_value_t<I, Proj>,
class T2 = std::iter_value_t<O> >
requires std::indirectly_copyable<I, O> &&
std::indirect_binary_predicate
<ranges::equal_to, std::projected<I, Proj>, const T1*> &&
std::indirectly_writable<O, const T2&>
ranges::replace_copy_result<I, O>
replace_copy( Ep&& policy, I first, S last,
O d_first, OutS d_last, const T1& old_value,
const T2& new_value, Proj proj = {} );
|
(5) | (since C++26) |
template< /*execution-policy*/ Ep,
/*sized-random-access-range*/ R,
/*sized-random-access-range*/ OutR,
class Proj = std::identity,
class T1 = std::projected_value_t<ranges::iterator_t<R>, Proj>,
class T2 = ranges::range_value_t<OutR> >
requires std::indirectly_copyable<ranges::iterator_t<R>,
ranges::iterator_t<OutR>> &&
std::indirect_binary_predicate
<ranges::equal_to,
std::projected<ranges::iterator_t<R>, Proj>, const T1*> &&
std::indirectly_writable<ranges::iterator_t<OutR>, const T2&>
ranges::replace_copy_result<ranges::borrowed_iterator_t<R>,
ranges::borrowed_iterator_t<OutR>>
replace_copy( Ep&& policy, R&& r, OutR&& d_r, const T1& old_value,
const T2& new_value, Proj proj = {} );
|
(6) | (since C++26) |
template< /*execution-policy*/ Ep,
std::random_access_iterator I, std::sized_sentinel_for<I> S,
std::random_access_iterator O, std::sized_sentinel_for<O> OutS,
class T = std::iter_value_t<O>, class Proj = std::identity,
std::indirect_unary_predicate<projected<I, Proj>> Pred >
requires std::indirectly_copyable<I, O> &&
std::indirectly_writable<O, const T&>
ranges::replace_copy_if_result<I, O>
replace_copy_if( Ep&& policy, I first, S last,
O d_first, OutS d_last, Pred pred,
const T& new_value, Proj proj = {} );
|
(7) | (since C++26) |
template< /*execution-policy*/ Ep,
/*sized-random-access-range*/ R,
/*sized-random-access-range*/ OutR,
class T = ranges::range_value_t<OutR>,
class Proj = std::identity,
std::indirect_unary_predicate
<std::projected<ranges::iterator_t<R>, Proj>> Pred >
requires std::indirectly_copyable<ranges::iterator_t<R>,
ranges::iterator_t<OutR>> &&
std::indirectly_writable<OutR, const T& >
ranges::replace_copy_if_result<ranges::borrowed_iterator_t<R>,
ranges::borrowed_iterator_t<OutR>>
replace_copy_if( Ep&& policy, R&& r, OutR&& d_r, Pred pred,
const T& new_value, Proj proj = {} );
|
(8) | (since C++26) |
| Helper types |
||
template< class I, class O >
using replace_copy_result = ranges::in_out_result<I, O>;
|
(9) | (since C++20) |
template< class I, class O >
using replace_copy_if_result = ranges::in_out_result<I, O>;
|
(10) | (since C++20) |
For the definition of /*execution-policy*/, see this page; for the definition of /*sized-random-access-range*/, see this page.
Copies the elements (projected by proj) from the source range [first, last) or r to the destination range, replacing all elements satisfying specific criteria with new_value.
1-4) The destination range is
[d_first, ranges::next(d_first, count)), where count is ranges::distance(first, last) or ranges::distance(r).1,2)
replace_copy replaces all elements that are equal to old_value (using operator==).3,4)
replace_copy_if replaces all elements for which predicate pred returns true.5-8) Same as (1-4), but executed according to
policy, and the destination range is [d_first, d_last) or d_r. If the destination range is exhausted before reaching the end of the source range, the remaining elements in the source range will not be copied.If any of the results of the expressions *first and new_value is not writable to d_first or ranges::begin(d_r), the program is ill-formed.
If the source and destination ranges overlap, the behavior is undefined.
The function-like entities described on this page are algorithm function objects (informally known as 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.
Parameters
| first, last | - | the pair of iterators defining the source range |
| r | - | the source range |
| d_first | - | the beginning of the destination range |
| d_last | - | the sentinel of the destination range |
| d_r | - | the destination range |
| old_value | - | the value of elements to replace |
| new_value | - | the value to use as a replacement |
| pred | - | predicate to be applied to the projected elements |
| proj | - | the projection to be applied to the elements |
| policy | - | the execution policy to use |
Return value
A ranges::replace_copy_result or ranges::replace_copy_if_result object where:
- The data member
inholds the an iterator past the last copied element in the source range (regardless of whether any replacement occurs), or an iterator to the beginning of the source range if no element is copied. - The data member
outholds the an iterator past the last assigned element in the destination range, or an iterator to the beginning of the destination range if no element is assigned.
Complexity
Given
- N1 as
ranges::distance(first, last)orranges::distance(r), - N2 as
ranges::distance(d_first, d_last)orranges::distance(d_r):
1,2) Exactly N1 comparisons using
operator==, and exactly N1 applications of proj.3,4) Exactly N1 applications of
pred and proj.5,6) 𝓞(min(N1,N2)) comparisons using
operator==, and 𝓞(min(N1,N2)) applications of proj.7,8) 𝓞(min(N1,N2)) applications of
pred and proj.Notes
| Feature-test macro | Value | Std | Feature |
|---|---|---|---|
__cpp_lib_algorithm_default_value_type |
202403 |
(C++26) | list-initialization for algorithms (1-4) |
Possible implementation
| replace_copy |
|---|
struct replace_copy_fn
{
template<std::input_iterator I, std::sentinel_for<I> S,
class O, class Proj = std::identity,
class T1 = std::projected_value_t<I, Proj>,
class T2 = std::iter_value_t<O>>
requires std::indirectly_copyable<I, O> &&
std::indirect_binary_predicate
<ranges::equal_to, std::projected<I, Proj>, const T1*> &&
std::output_iterator<O, const T2&>
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 O, class Proj = std::identity,
class T1 = std::projected_value_t<ranges::iterator_t<R>, Proj>,
class T2 = std::iter_value_t<O>>
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));
}
template<ranges::forward_range R, class O, class Proj = std::identity,
class T1 = std::projected_value_t<ranges::iterator_t<R>, Proj>,
class T2 = std::iter_value_t<O>>
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::next(ranges::begin(r), ranges::end(r)),
std::move(result), old_value, new_value, std::move(proj));
}
};
inline constexpr replace_copy_fn replace_copy{};
|
| replace_copy_if |
struct replace_copy_if_fn
{
template<std::input_iterator I, std::sentinel_for<I> S,
class O, class T = std::iter_value_t<O>
class Proj = std::identity,
std::indirect_unary_predicate<std::projected<I, Proj>> Pred>
requires std::indirectly_copyable<I, O> && std::output_iterator<O, const T&>
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 O, class T = std::iter_value_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> &&
std::output_iterator<O, const T&>
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));
}
template<ranges::forward_range R, class O, class T = std::iter_value_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> &&
std::output_iterator<O, const T&>
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::next(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{};
|
Example
Run this code
#include <algorithm>
#include <array>
#include <complex>
#include <iostream>
#include <vector>
void println(const auto rem, const auto& v)
{
for (std::cout << rem << ": "; const auto& e : v)
std::cout << e << ' ';
std::cout << '\n';
}
int main()
{
std::vector<int> o;
std::array p{1, 6, 1, 6, 1, 6};
o.resize(p.size());
println("p", p);
std::ranges::replace_copy(p, o.begin(), 6, 9);
println("o", o);
std::array q{1, 2, 3, 6, 7, 8, 4, 5};
o.resize(q.size());
println("q", q);
std::ranges::replace_copy_if(q, o.begin(), [](int x) { return 5 < x; }, 5);
println("o", o);
std::vector<std::complex<short>> r{{1, 3}, {2, 2}, {4, 8}};
std::vector<std::complex<float>> s(r.size());
println("r", r);
#ifdef __cpp_lib_algorithm_default_value_type
std::ranges::replace_copy(r, s.begin(),
{1, 3}, // T1 gets deduced
{2.2, 4.8}); // T2 gets deduced
#else
std::ranges::replace_copy(r, s.begin(),
std::complex<short>{1, 3},
std::complex<float>{2.2, 4.8});
#endif
println("s", s);
std::vector<std::complex<double>> b{{1, 3}, {2, 2}, {4, 8}},
d(b.size());
println("b", b);
#ifdef __cpp_lib_algorithm_default_value_type
std::ranges::replace_copy_if(b, d.begin(),
[](std::complex<double> z){ return std::abs(z) < 5; },
{4, 2}); // Possible, since the T is deduced.
#else
std::ranges::replace_copy_if(b, d.begin(),
[](std::complex<double> z){ return std::abs(z) < 5; },
std::complex<double>{4, 2});
#endif
println("d", d);
}
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
r: (1,3) (2,2) (4,8)
s: (2.2,4.8) (2,2) (4,8)
b: (1,3) (2,2) (4,8)
d: (4,2) (4,2) (4,8)
See also
| copies a range, replacing elements satisfying specific criteria with another value (function template) | |
(C++20)(C++20) |
replaces all values satisfying specific criteria with another value (algorithm function object) |