Namespaces
Variants
Views
Actions

Difference between revisions of "cpp/algorithm/replace copy"

From cppreference.com
< cpp‎ | algorithm
m (Text replace - "{{example cpp" to "{{example")
m (FTM.)
 
(34 intermediate revisions by 10 users not shown)
Line 1: Line 1:
 
{{cpp/title|replace_copy|replace_copy_if}}
 
{{cpp/title|replace_copy|replace_copy_if}}
{{cpp/algorithm/sidebar}}
+
{{cpp/algorithm/navbar}}
{{ddcl list begin}}
+
{{dcl begin}}
{{ddcl list header | algorithm}}
+
{{dcl header|algorithm}}
{{ddcl list item | num=1 |
+
<!-- P2248R8 does NOT update replace_copy -->
template< class InputIterator, class OutputIterator, class T >
+
{{dcla|num=1|constexpr=c++20|
OutputIterator replace_copy( InputIterator first,
+
template< class InputIt, class OutputIt, class T >
                            InputIterator last,
+
OutputIt replace_copy( InputIt first, InputIt last, OutputIt d_first,
                            OutputIterator d_first,
+
                      const T& old_value, const T& new_value );
                            const T& old_value,
+
                            const T& new_value );
+
 
}}
 
}}
{{ddcl list item | num=2 |
+
{{dcl|num=2|since=c++17|
template< class InputIterator, class OutputIterator, class UnaryPredicate, class T >
+
template< class ExecutionPolicy,
OutputIterator replace_copy_if( InputIterator first,
+
          class ForwardIt1, class ForwardIt2, class T >
                                InputIterator last,
+
ForwardIt2 replace_copy
                                OutputIterator d_first,
+
    ( ExecutionPolicy&& policy,
                                UnaryPredicate p,
+
      ForwardIt1 first, ForwardIt1 last, ForwardIt2 d_first,
                                const T& new_value );
+
      const T& old_value, const T& new_value );
 
}}
 
}}
{{ddcl list end}}
+
{{dcl rev begin|num=3}}
 +
{{dcla|anchor=3|constexpr=c++20|until=c++26|
 +
template< class InputIt, class OutputIt, class UnaryPred, class T >
 +
OutputIt replace_copy_if
 +
    ( InputIt first, InputIt last, OutputIt d_first,
 +
      UnaryPred p, const T& new_value );
 +
}}
 +
{{dcl|since=c++26|1=
 +
template< class InputIt, class OutputIt, class UnaryPred,
 +
          class T = typename std::iterator_traits
 +
                        <OutputIt>::value_type >
 +
constexpr OutputIt replace_copy_if
 +
    ( InputIt first, InputIt last, OutputIt d_first,
 +
      UnaryPred p, const T& new_value );
 +
}}
 +
{{dcl rev end}}
 +
{{dcl rev begin|num=4}}
 +
{{dcl|since=c++17|until=c++26|
 +
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2,
 +
          class UnaryPred, class T >
 +
ForwardIt2 replace_copy_if
 +
    ( ExecutionPolicy&& policy,
 +
      ForwardIt1 first, ForwardIt1 last, ForwardIt2 d_first,
 +
      UnaryPred p, const T& new_value );
 +
}}
 +
{{dcl|since=c++26|1=
 +
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2,
 +
          class UnaryPred, class T = typename std::iterator_traits
 +
                                        <ForwardIt2>::value_type >
 +
ForwardIt2 replace_copy_if
 +
    ( ExecutionPolicy&& policy,
 +
      ForwardIt1 first, ForwardIt1 last, ForwardIt2 d_first,
 +
      UnaryPred p, const T& new_value );
 +
}}
 +
{{dcl end}}
 +
 
 +
Copies the elements from the range {{range|first|last}} to another range beginning at {{c|d_first}}, while replacing all elements satisfying specific criteria with {{c|new_value}}.
 +
 
 +
@1@ Replaces all elements that are equal to {{c|old_value}} (using {{c/core|1=operator==}}).
 +
 
 +
@3@ Replaces all elements for which predicate {{c|p}} returns {{c|true}}.
 +
 
 +
@2,4@ Same as {{v|1,3}}, but executed according to {{c|policy}}.
 +
@@ {{cpp/algorithm/parallel overload precondition|plural=yes}}
 +
 
 +
If any of the results of the expressions {{c|*first}} and {{c|new_value}} is not [[cpp/iterator#Types and writability|writable]] to {{c|d_first}}, the program is ill-formed.
  
Copies the all elements from the range {{tt|[first, last)}} to another range beginning at {{tt|d_first}} replacing all elements satisfying specific criteria with {{tt|new_value}}. The first version replaces the elements that are equal to {{tt|old_value}}, the second version replaces elements for which predicate {{tt|p}} returns {{cpp|true}}. The source and destination ranges cannot overlap.
+
If the source and destination ranges overlap, the behavior is undefined.
  
 
===Parameters===
 
===Parameters===
{{param list begin}}
+
{{par begin}}
{{param list item | first, last | the range of elements to copy}}
+
{{par|first, last|the range of elements to copy}}
{{param list item | d_first | the beginning of the destination range}}
+
{{par|d_first|the beginning of the destination range}}
{{param list item | old_value | the value of elements to replace}}
+
{{par|old_value|the value of elements to replace}}
{{param list pred1 | p | if the element value should be replaced | p1=ForwardIterator}}
+
{{par exec pol}}
{{param list item | new_value | the value to use as replacement}}
+
{{par pred1|p|if the element value should be replaced|p1=InputIt}}
{{param list end}}
+
{{par|new_value|the value to use as replacement}}
 +
{{par hreq}}
 +
{{par req named|InputIt|InputIterator}}
 +
{{par req named|OutputIt|OutputIterator}}
 +
{{par req named|ForwardIt1, ForwardIt2|ForwardIterator}}
 +
{{par end}}
  
 
===Return value===
 
===Return value===
 
+
Iterator to the element past the last element copied.
iterator to the element past the last element copied.
+
  
 
===Complexity===
 
===Complexity===
 +
Given {{mathjax-or|\(\scriptsize N\)|N}} as {{c|std::distance(first, last)}}:
 +
@1,2@ Exactly {{mathjax-or|\(\scriptsize N\)|N}} comparisons using {{c/core|1=operator==}}.
 +
@3,4@ Exactly {{mathjax-or|\(\scriptsize N\)|N}} applications of the predicate {{c|p}}.
  
Exactly {{tt|last - first}} applications of the predicate.
+
===Exceptions===
 +
{{cpp/algorithm/parallel exceptions reporting behavior|singular=no}}
  
 
===Possible implementation===
 
===Possible implementation===
{{eq fun cpp
+
{{eq impl
| 1=
+
|title1=replace_copy|ver1=1|1=
template<class InputIterator, class OutputIterator, class T>
+
template<class InputIt, class OutputIt, class T>
OutputIterator replace_copy(InputIterator first,
+
OutputIt replace_copy(InputIt first, InputIt last, OutputIt d_first,
                            InputIterator last,
+
                      const T& old_value, const T& new_value)
                            OutputIterator d_first,
+
                            const T& old_value,
+
                            const T& new_value)
+
 
{
 
{
     for (; first != last; ++first) {
+
     for (; first != last; ++first)
 
         *d_first++ = (*first == old_value) ? new_value : *first;
 
         *d_first++ = (*first == old_value) ? new_value : *first;
    }
 
 
     return d_first;
 
     return d_first;
 
}
 
}
| 2=
+
|title2=replace_copy_if|ver2=3|2=
template<class InputIterator, class OutputIterator,  
+
template<class InputIt, class OutputIt, class UnaryPred,
         class UnaryPredicate, class T>
+
         class T = typename std::iterator_traits<ForwardIt>::value_type>
OutputIterator replace_copy_if(InputIterator first,
+
OutputIt replace_copy_if(InputIt first, InputIt last, OutputIt d_first,
                              InputIterator last,
+
                        UnaryPred p, const T& new_value)
                              OutputIterator d_first,
+
                              UnaryPredicate p,
+
                              const T& new_value)
+
 
{
 
{
     for (; first != last; ++first) {
+
     for (; first != last; ++first)
         *d_first++ = (p( *first ) ? new_value : *first;
+
         *d_first++ = p(*first) ? new_value : *first;
    }
+
 
     return d_first;
 
     return d_first;
 
}
 
}
 
}}
 
}}
 +
 +
===Notes===
 +
{{feature test macro|__cpp_lib_algorithm_default_value_type|value=202403|std=C++26|[[cpp/language/list initialization|List-initialization]] for algorithms {{vl|3,4}}}}
  
 
===Example===
 
===Example===
 
{{example
 
{{example
| The following copy prints a vector, replacing all values over 5 with 99 on the fly.
+
|code=
| code=
+
 
#include <algorithm>
 
#include <algorithm>
#include <vector>
+
#include <complex>
 
#include <iostream>
 
#include <iostream>
#include <iterator>
+
#include <vector>
#include <functional>
+
  
int main()
+
void println(const auto& seq)
 
{
 
{
     std::vector<int> v{5, 7, 4, 2, 8, 6, 1, 9, 0, 3};
+
     for (const auto& e : seq)
    std::replace_copy_if(v.begin(), v.end(),
+
        std::cout << e << ' ';
                        std::ostream_iterator<int>(std::cout, " "),
+
                        [](int n){return n > 5;}, 99);
+
 
     std::cout << '\n';
 
     std::cout << '\n';
 
}
 
}
  | output=
+
   
5 99 4 2 99 99 1 99 0 3
+
int main()
 +
{
 +
    std::vector<short> src{3, 1, 4, 1, 5, 9, 2, 6, 5};
 +
    println(src);
 +
    std::vector<int> dst(src.size());
 +
    std::replace_copy_if(src.cbegin(), src.cend(),
 +
                        dst.begin(),
 +
                        [](short n){ return n > 5; }, 0);
 +
    println(dst);
 +
 
 +
    std::vector<std::complex<double>> src2{<!---->{1, 3}, {2, 4}, {3, 5}<!---->},
 +
                                      dst2(src2.size());
 +
    println(src2);
 +
    #ifdef __cpp_lib_algorithm_default_value_type
 +
        std::replace_copy_if(src2.cbegin(), src2.cend(), dst2.begin(),
 +
            [](std::complex<double> z){ return std::abs(z) < 5; },
 +
            {4, 2}); // Possible, since the T is deduced.
 +
    #else
 +
        std::replace_copy_if(src2.cbegin(), src2.cend(), dst2.begin(),
 +
            [](std::complex<double> z){ return std::abs(z) < 5; },
 +
            std::complex<double>{4, 2});
 +
    #endif
 +
    println(dst2);
 +
}
 +
|output=
 +
3 1 4 1 5 9 2 6 5
 +
3 1 4 1 5 0 2 0 5
 +
(1,3) (2,4) (3,5)
 +
(4,2) (4,2) (3,5)
 
}}
 
}}
 +
 +
===Defect reports===
 +
{{dr list begin}}
 +
{{dr list item|wg=lwg|dr=283|std=C++98|before={{tt|T}} was required to be {{named req|CopyAssignable}} (and {{named req|EqualityComparable}} for<br>{{tt|replace_copy}}), but the value type of {{tt|InputIt}} is not always {{tt|T}}|after=removed the requirement}}
 +
{{dr list item|wg=lwg|dr=337|std=C++98|before={{tt|replace_copy_if}} only required {{tt|InputIt}} to<br>meet the requirements of {{named req|Iterator}}<ref>The actual defect in the C++ standard is that the template parameter {{tt|InputIterator}} was misspecified as {{tt|Iterator}}. This affects the type requirements because the C++ standard states that for the function templates in the algorithms library, the template type parameters whose name ends with {{tt|Iterator}} imply the type requirements of the corresponding iterator categories.</ref>|after=corrected to<br>{{named req|InputIterator}}}}
 +
{{dr list end}}
 +
<references/>
  
 
===See also===
 
===See also===
{{dcl list begin}}
+
{{dsc begin}}
{{dcl list template | cpp/algorithm/dcl list remove}}
+
{{dsc inc|cpp/algorithm/dsc replace}}
{{dcl list end}}
+
{{dsc inc|cpp/algorithm/dsc remove}}
 +
{{dsc inc|cpp/algorithm/ranges/dsc replace_copy}}
 +
{{dsc end}}
 +
 
 +
{{langlinks|de|es|fr|it|ja|pt|ru|zh}}

Latest revision as of 21:22, 20 May 2024

 
 
Algorithm library
Constrained algorithms and algorithms on ranges (C++20)
Constrained algorithms, e.g. ranges::copy, ranges::sort, ...
Execution policies (C++17)
Non-modifying sequence operations
Batch operations
(C++17)
Search operations
(C++11)                (C++11)(C++11)

Modifying sequence operations
Copy operations
(C++11)
(C++11)
Swap operations
Transformation operations
replace_copyreplace_copy_if

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
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
C library
Numeric operations
Operations on uninitialized memory
 
Defined in header <algorithm>
template< class InputIt, class OutputIt, class T >

OutputIt replace_copy( InputIt first, InputIt last, OutputIt d_first,

                       const T& old_value, const T& new_value );
(1) (constexpr since C++20)
template< class ExecutionPolicy,

          class ForwardIt1, class ForwardIt2, class T >
ForwardIt2 replace_copy
    ( ExecutionPolicy&& policy,
      ForwardIt1 first, ForwardIt1 last, ForwardIt2 d_first,

      const T& old_value, const T& new_value );
(2) (since C++17)
(3)
template< class InputIt, class OutputIt, class UnaryPred, class T >

OutputIt replace_copy_if
    ( InputIt first, InputIt last, OutputIt d_first,

      UnaryPred p, const T& new_value );
(constexpr since C++20)
(until C++26)
template< class InputIt, class OutputIt, class UnaryPred,

          class T = typename std::iterator_traits
                        <OutputIt>::value_type >
constexpr OutputIt replace_copy_if
    ( InputIt first, InputIt last, OutputIt d_first,

      UnaryPred p, const T& new_value );
(since C++26)
(4)
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2,

          class UnaryPred, class T >
ForwardIt2 replace_copy_if
    ( ExecutionPolicy&& policy,
      ForwardIt1 first, ForwardIt1 last, ForwardIt2 d_first,

      UnaryPred p, const T& new_value );
(since C++17)
(until C++26)
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2,

          class UnaryPred, class T = typename std::iterator_traits
                                         <ForwardIt2>::value_type >
ForwardIt2 replace_copy_if
    ( ExecutionPolicy&& policy,
      ForwardIt1 first, ForwardIt1 last, ForwardIt2 d_first,

      UnaryPred p, const T& new_value );
(since C++26)

Copies the elements from the range [firstlast) to another range beginning at d_first, while replacing all elements satisfying specific criteria with new_value.

1) Replaces all elements that are equal to old_value (using operator==).
3) Replaces all elements for which predicate p returns true.
2,4) Same as (1,3), but executed according to policy.
These overloads participate in overload resolution only if

std::is_execution_policy_v<std::decay_t<ExecutionPolicy>> is true.

(until C++20)

std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>> is true.

(since C++20)

If any of the results of the expressions *first and new_value is not writable to d_first, the program is ill-formed.

If the source and destination ranges overlap, the behavior is undefined.

Contents

[edit] Parameters

first, last - the range of elements to copy
d_first - the beginning of the destination range
old_value - the value of elements to replace
policy - the execution policy to use. See execution policy for details.
p - unary predicate which returns ​true if the element value should be replaced.

The expression p(v) must be convertible to bool for every argument v of type (possibly const) VT, where VT is the value type of InputIt, regardless of value category, and must not modify v. Thus, a parameter type of VT&is not allowed, nor is VT unless for VT a move is equivalent to a copy(since C++11). ​

new_value - the value to use as replacement
Type requirements
-
InputIt must meet the requirements of LegacyInputIterator.
-
OutputIt must meet the requirements of LegacyOutputIterator.
-
ForwardIt1, ForwardIt2 must meet the requirements of LegacyForwardIterator.

[edit] Return value

Iterator to the element past the last element copied.

[edit] Complexity

Given N as std::distance(first, last):

1,2) Exactly N comparisons using operator==.
3,4) Exactly N applications of the predicate p.

[edit] Exceptions

The overloads with a template parameter named ExecutionPolicy report errors as follows:

  • If execution of a function invoked as part of the algorithm throws an exception and ExecutionPolicy is one of the standard policies, std::terminate is called. For any other ExecutionPolicy, the behavior is implementation-defined.
  • If the algorithm fails to allocate memory, std::bad_alloc is thrown.

[edit] Possible implementation

replace_copy
template<class InputIt, class OutputIt, class T>
OutputIt replace_copy(InputIt first, InputIt last, OutputIt d_first,
                      const T& old_value, const T& new_value)
{
    for (; first != last; ++first)
        *d_first++ = (*first == old_value) ? new_value : *first;
    return d_first;
}
replace_copy_if
template<class InputIt, class OutputIt, class UnaryPred,
         class T = typename std::iterator_traits<ForwardIt>::value_type>
OutputIt replace_copy_if(InputIt first, InputIt last, OutputIt d_first,
                         UnaryPred p, const T& new_value)
{
    for (; first != last; ++first)
        *d_first++ = p(*first) ? new_value : *first;
    return d_first;
}

[edit] Notes

Feature-test macro Value Std Feature
__cpp_lib_algorithm_default_value_type 202403 (C++26) List-initialization for algorithms (3,4)

[edit] Example

#include <algorithm>
#include <complex>
#include <iostream>
#include <vector>
 
void println(const auto& seq)
{
    for (const auto& e : seq)
        std::cout << e << ' ';
    std::cout << '\n';
}
 
int main()
{
    std::vector<short> src{3, 1, 4, 1, 5, 9, 2, 6, 5};
    println(src);
    std::vector<int> dst(src.size());
    std::replace_copy_if(src.cbegin(), src.cend(),
                         dst.begin(),
                         [](short n){ return n > 5; }, 0);
    println(dst);
 
    std::vector<std::complex<double>> src2{{1, 3}, {2, 4}, {3, 5}},
                                      dst2(src2.size());
    println(src2);
    #ifdef __cpp_lib_algorithm_default_value_type
        std::replace_copy_if(src2.cbegin(), src2.cend(), dst2.begin(),
            [](std::complex<double> z){ return std::abs(z) < 5; },
            {4, 2}); // Possible, since the T is deduced.
    #else
        std::replace_copy_if(src2.cbegin(), src2.cend(), dst2.begin(),
            [](std::complex<double> z){ return std::abs(z) < 5; },
            std::complex<double>{4, 2});
    #endif
    println(dst2);
}

Output:

3 1 4 1 5 9 2 6 5 
3 1 4 1 5 0 2 0 5 
(1,3) (2,4) (3,5) 
(4,2) (4,2) (3,5)

[edit] Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DR Applied to Behavior as published Correct behavior
LWG 283 C++98 T was required to be CopyAssignable (and EqualityComparable for
replace_copy), but the value type of InputIt is not always T
removed the requirement
LWG 337 C++98 replace_copy_if only required InputIt to
meet the requirements of LegacyIterator[1]
corrected to
LegacyInputIterator
  1. The actual defect in the C++ standard is that the template parameter InputIterator was misspecified as Iterator. This affects the type requirements because the C++ standard states that for the function templates in the algorithms library, the template type parameters whose name ends with Iterator imply the type requirements of the corresponding iterator categories.

[edit] See also

replaces all values satisfying specific criteria with another value
(function template) [edit]
removes elements satisfying specific criteria
(function template) [edit]
copies a range, replacing elements satisfying specific criteria with another value
(niebloid)[edit]