Namespaces
Variants

std::ranges::replace_copy, std::ranges::replace_copy_if, std::ranges::replace_copy_result, std::ranges::replace_copy_if_result

From cppreference.com
 
 
Algorithm library
Constrained algorithms and algorithms on ranges (C++20)
Constrained algorithms, e.g. ranges::copy, ranges::sort, ...
Non-modifying sequence operations    
Batch operations
(C++17)
Search operations
Modifying sequence operations
Copy operations
(C++11)
(C++11)
Swap operations
Transformation operations
Generation operations
Removing operations
Order-changing operations
(until C++17)(C++11)
(C++20)(C++20)
Sampling operations
(C++17)

Sorting and related operations
Partitioning operations
(C++11)    

Sorting operations
Binary search operations
(on partitioned ranges)
Set operations (on sorted ranges)
Merge operations (on sorted ranges)
Heap operations
Minimum/maximum operations
(C++11)
(C++17)
Lexicographical comparison operations
Permutation operations


 
Constrained algorithms
All names in this menu belong to namespace std::ranges
Non-modifying sequence operations
Fold operations (Helper templates)
Modifying sequence operations
Partitioning operations
Sorting operations
Binary search operations (on sorted ranges)
       
       
Set operations (on sorted ranges)
Heap operations
Minimum/maximum operations
       
       
Permutation operations
Specialized <memory> algorithms
Return types
 
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 [firstlast) or r to the destination range, replacing all elements satisfying specific criteria with new_value.

1-4) The destination range is [d_firstranges::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_firstd_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:

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 in holds 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 out holds 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) or ranges::distance(r),
  • N2 as ranges::distance(d_first, d_last) or ranges::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

#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) [edit]
replaces all values satisfying specific criteria with another value
(algorithm function object)[edit]