Namespaces
Variants
Views
Actions

Difference between revisions of "cpp/algorithm/replace"

From cppreference.com
< cpp‎ | algorithm
m (Text replace - "{{cpp|" to "{{c|")
m (FTM.)
 
(36 intermediate revisions by 11 users not shown)
Line 1: Line 1:
{{cpp/title|replace | replace_if}}
+
{{cpp/title|replace|replace_if}}
{{cpp/algorithm/sidebar}}
+
{{cpp/algorithm/navbar}}
{{ddcl list begin}}
+
{{dcl begin}}
{{ddcl list header | algorithm}}
+
{{dcl header|algorithm}}
{{ddcl list item | num=1 |
+
{{dcl rev begin|num=1}}
template< class ForwardIterator, class T >
+
{{dcla|anchor=1|constexpr=c++20|until=c++26|
void replace( ForwardIterator first, ForwardIterator last,
+
template< class ForwardIt, class T >
 +
void replace( ForwardIt first, ForwardIt last,
 
               const T& old_value, const T& new_value );
 
               const T& old_value, const T& new_value );
 
}}
 
}}
{{ddcl list item | num=2 |
+
{{dcl|since=c++26|1=
template< class ForwardIterator, class UnaryPredicate, class T >
+
template< class ForwardIt, class T = typename std::iterator_traits
void replace_if( ForwardIterator first, ForwardIterator last,
+
                                        <ForwardIt>::value_type >
                UnaryPredicate p, const T& new_value );
+
constexpr void replace( ForwardIt first, ForwardIt last,
 +
                        const T& old_value, const T& new_value );
 
}}
 
}}
{{ddcl list end}}
+
{{dcl rev end}}
 +
{{dcl rev begin|num=2}}
 +
{{dcl|since=c++17|until=c++26|
 +
template< class ExecutionPolicy, class ForwardIt, class T >
 +
void replace( ExecutionPolicy&& policy,
 +
              ForwardIt first, ForwardIt last,
 +
              const T& old_value, const T& new_value );
 +
}}
 +
{{dcl|since=c++26|1=
 +
template< class ExecutionPolicy, class ForwardIt,
 +
          class T = typename std::iterator_traits
 +
                        <ForwardIt>::value_type >
 +
void replace( ExecutionPolicy&& policy,
 +
              ForwardIt first, ForwardIt last,
 +
              const T& old_value, const T& new_value );
 +
}}
 +
{{dcl rev end}}
 +
{{dcl rev begin|num=3}}
 +
{{dcla|anchor=3|constexpr=c++20|until=c++26|
 +
template< class ForwardIt, class UnaryPred, class T >
 +
void replace_if( ForwardIt first, ForwardIt last,
 +
                UnaryPred p, const T& new_value );
 +
}}
 +
{{dcl|since=c++26|1=
 +
template< class ForwardIt, class UnaryPred,
 +
          class T = typename std::iterator_traits
 +
                        <ForwardIt>::value_type> >
 +
constexpr void replace_if( ForwardIt first, ForwardIt last,
 +
                          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 ForwardIt, class UnaryPred, class T >
 +
void replace_if( ExecutionPolicy&& policy,
 +
                ForwardIt first, ForwardIt last,
 +
                UnaryPred p, const T& new_value );
 +
}}
 +
{{dcl|since=c++26|1=
 +
template< class ExecutionPolicy,
 +
          class ForwardIt, class UnaryPred,
 +
          class T = typename std::iterator_traits
 +
                        <ForwardIt>::value_type> >
 +
void replace_if( ExecutionPolicy&& policy,
 +
                ForwardIt first, ForwardIt last,
 +
                UnaryPred p, const T& new_value );
 +
}}
 +
{{dcl end}}
 +
 
 +
Replaces all elements in the range {{range|first|last}} with {{c|new_value}} if they satisfy specific criteria.
 +
 
 +
@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}}
  
Replaces all elements satisfying specific criteria with {{tt|new_value}} in the range {{tt|[first, last)}}. The first version replaces the elements that are equal to {{tt|old_value}}, the second version replaces elements for which predicate {{tt|p}} returns {{c|true}}.  
+
If {{rev inl|until=c++20|{{c|1=*first = new_value}} is invalid}}{{rev inl|since=c++20|{{c|new_value}} is not [[cpp/iterator#Types and writability|writable]] to {{c|first}}}}, the program is ill-formed.
  
 
===Parameters===
 
===Parameters===
{{param list begin}}
+
{{par begin}}
{{param list item | first, last | the range of elements to process}}
+
{{par|first, last|the range of elements to process}}
{{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=ForwardIt}}
{{param list end}}
+
{{par|new_value|the value to use as replacement}}
 +
{{par hreq}}
 +
{{par req named|ForwardIt|ForwardIterator}}
 +
{{par req named|UnaryPred|Predicate}}
 +
{{par end}}
  
 
===Return value===
 
===Return value===
Line 29: Line 92:
  
 
===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}}
 +
 
 +
===Notes===
 +
Because the algorithm takes {{c|old_value}} and {{c|new_value}} by reference, it can have unexpected behavior if either is a reference to an element of the range {{range|first|last}}.
 +
 
 +
{{feature test macro|__cpp_lib_algorithm_default_value_type|value=202403|std=C++26|[[cpp/language/list initialization|List-initialization]] for algorithms {{vl|1-4}}}}
  
 
===Possible implementation===
 
===Possible implementation===
{{eq fun cpp
+
{{eq impl
| 1=
+
|title1=replace|ver1=1|1=
template<class ForwardIterator, class T>
+
template<class ForwardIt,
void replace(ForwardIterator first, ForwardIterator last,
+
        class T = typename std::iterator_traits<ForwardIt>::value_type>
 +
void replace(ForwardIt first, ForwardIt last,
 
             const T& old_value, const T& new_value)
 
             const T& old_value, const T& new_value)
 
{
 
{
     for (; first != last; ++first) {
+
     for (; first != last; ++first)
         if (*first == old_value) {
+
         if (*first == old_value)
 
             *first = new_value;
 
             *first = new_value;
        }
 
    }
 
 
}
 
}
| 2=
+
|title2=replace_if|ver2=3|2=
template<class ForwardIterator, class UnaryPredicate, class T>
+
template<class ForwardIt, class UnaryPred,
void replace_if(ForwardIterator first, ForwardIterator last,
+
        class T = typename std::iterator_traits<ForwardIt>::value_type>
                 UnaryPredicate p, const T& new_value)
+
void replace_if(ForwardIt first, ForwardIt last,
 +
                 UnaryPred p, const T& new_value)
 
{
 
{
     for (; first != last; ++first) {
+
     for (; first != last; ++first)
         if(p(*first)) {
+
         if (p(*first))
 
             *first = new_value;
 
             *first = new_value;
        }
 
    }
 
 
}
 
}
 
}}
 
}}
Line 60: Line 130:
 
===Example===
 
===Example===
 
{{example
 
{{example
| The following code at first replaces all occurrences of {{c|8}} with {{c|88}} in a vector of integers. Then it replaces all values less than {{c|5}} with 55.
+
|code=
| code=
+
 
#include <algorithm>
 
#include <algorithm>
 
#include <array>
 
#include <array>
#include <iostream>
+
#include <complex>
 
#include <functional>
 
#include <functional>
 +
#include <iostream>
 +
 +
void println(const auto& seq)
 +
{
 +
    for (const auto& e : seq)
 +
        std::cout << e << ' ';
 +
    std::cout << '\n';
 +
}
  
 
int main()
 
int main()
 
{
 
{
 
     std::array<int, 10> s{5, 7, 4, 2, 8, 6, 1, 9, 0, 3};
 
     std::array<int, 10> s{5, 7, 4, 2, 8, 6, 1, 9, 0, 3};
 
+
   
 +
    // Replace all occurrences of 8 with 88.
 
     std::replace(s.begin(), s.end(), 8, 88);
 
     std::replace(s.begin(), s.end(), 8, 88);
 +
    println(s);
  
     for (int a : s) {
+
     // Replace all values less than 5 with 55.
        std::cout << a << " ";
+
    }
+
    std::cout << '\n';
+
 
+
 
     std::replace_if(s.begin(), s.end(),  
 
     std::replace_if(s.begin(), s.end(),  
 
                     std::bind(std::less<int>(), std::placeholders::_1, 5), 55);
 
                     std::bind(std::less<int>(), std::placeholders::_1, 5), 55);
     for (int a : s) {
+
     println(s);
        std::cout << a << " ";
+
 
     }
+
    std::array<std::complex<double>, 2> nums{<!---->{<!---->{1, 3}, {1, 3}<!---->}<!---->};
     std::cout << '\n';
+
     #ifdef __cpp_lib_algorithm_default_value_type
 +
        std::replace(nums.begin(), nums.end(), {1, 3}, {4, 2});
 +
     #else
 +
        std::replace(nums.begin(), nums.end(), std::complex<double>{1, 3},
 +
                                              std::complex<double>{4, 2});
 +
    #endif
 +
    println(nums);
 
}
 
}
| output=
+
|output=
 
5 7 4 2 88 6 1 9 0 3
 
5 7 4 2 88 6 1 9 0 3
5 7 55 55 99 6 55 9 55 55
+
5 7 55 55 88 6 55 9 55 55
 +
(4,2), (4,2)
 
}}
 
}}
 +
 +
===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}}<br>for {{tt|replace}}), but the value type of {{tt|ForwardIt}} is not<br>always {{tt|T}} and {{tt|T}} is not always writable to {{tt|ForwardIt}}|after=required {{c|1=*first = new_value}}<br>to be valid instead}}
 +
{{dr list end}}
  
 
===See also===
 
===See also===
{{dcl list begin}}
+
{{dsc begin}}
{{dcl list template | cpp/algorithm/dcl list replace_copy}}
+
{{dsc inc|cpp/algorithm/dsc replace_copy}}
{{dcl list end}}
+
{{dsc inc|cpp/algorithm/ranges/dsc replace}}
 +
{{dsc end}}
 +
 
 +
{{langlinks|de|es|fr|it|ja|pt|ru|zh}}

Latest revision as of 21:20, 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
replacereplace_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>
(1)
template< class ForwardIt, class T >

void replace( ForwardIt first, ForwardIt last,

              const T& old_value, const T& new_value );
(constexpr since C++20)
(until C++26)
template< class ForwardIt, class T = typename std::iterator_traits

                                         <ForwardIt>::value_type >
constexpr void replace( ForwardIt first, ForwardIt last,

                        const T& old_value, const T& new_value );
(since C++26)
(2)
template< class ExecutionPolicy, class ForwardIt, class T >

void replace( ExecutionPolicy&& policy,
              ForwardIt first, ForwardIt last,

              const T& old_value, const T& new_value );
(since C++17)
(until C++26)
template< class ExecutionPolicy, class ForwardIt,

          class T = typename std::iterator_traits
                        <ForwardIt>::value_type >
void replace( ExecutionPolicy&& policy,
              ForwardIt first, ForwardIt last,

              const T& old_value, const T& new_value );
(since C++26)
(3)
template< class ForwardIt, class UnaryPred, class T >

void replace_if( ForwardIt first, ForwardIt last,

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

          class T = typename std::iterator_traits
                        <ForwardIt>::value_type> >
constexpr void replace_if( ForwardIt first, ForwardIt last,

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

          class ForwardIt, class UnaryPred, class T >
void replace_if( ExecutionPolicy&& policy,
                 ForwardIt first, ForwardIt last,

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

          class ForwardIt, class UnaryPred,
          class T = typename std::iterator_traits
                        <ForwardIt>::value_type> >
void replace_if( ExecutionPolicy&& policy,
                 ForwardIt first, ForwardIt last,

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

Replaces all elements in the range [firstlast) with new_value if they satisfy specific criteria.

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 *first = new_value is invalid(until C++20)new_value is not writable to first(since C++20), the program is ill-formed.

Contents

[edit] Parameters

first, last - the range of elements to process
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 ForwardIt, 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
-
ForwardIt must meet the requirements of LegacyForwardIterator.
-
UnaryPred must meet the requirements of Predicate.

[edit] Return value

(none)

[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] Notes

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

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

[edit] Possible implementation

replace
template<class ForwardIt,
         class T = typename std::iterator_traits<ForwardIt>::value_type>
void replace(ForwardIt first, ForwardIt last,
             const T& old_value, const T& new_value)
{
    for (; first != last; ++first)
        if (*first == old_value)
            *first = new_value;
}
replace_if
template<class ForwardIt, class UnaryPred,
         class T = typename std::iterator_traits<ForwardIt>::value_type>
void replace_if(ForwardIt first, ForwardIt last,
                UnaryPred p, const T& new_value)
{
    for (; first != last; ++first)
        if (p(*first))
            *first = new_value;
}

[edit] Example

#include <algorithm>
#include <array>
#include <complex>
#include <functional>
#include <iostream>
 
void println(const auto& seq)
{
    for (const auto& e : seq)
        std::cout << e << ' ';
    std::cout << '\n';
}
 
int main()
{
    std::array<int, 10> s{5, 7, 4, 2, 8, 6, 1, 9, 0, 3};
 
    // Replace all occurrences of 8 with 88.
    std::replace(s.begin(), s.end(), 8, 88);
    println(s);
 
    // Replace all values less than 5 with 55.
    std::replace_if(s.begin(), s.end(), 
                    std::bind(std::less<int>(), std::placeholders::_1, 5), 55);
    println(s);
 
    std::array<std::complex<double>, 2> nums{{{1, 3}, {1, 3}}};
    #ifdef __cpp_lib_algorithm_default_value_type
        std::replace(nums.begin(), nums.end(), {1, 3}, {4, 2});
    #else
        std::replace(nums.begin(), nums.end(), std::complex<double>{1, 3},
                                               std::complex<double>{4, 2});
    #endif
    println(nums);
}

Output:

5 7 4 2 88 6 1 9 0 3
5 7 55 55 88 6 55 9 55 55
(4,2), (4,2)

[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), but the value type of ForwardIt is not
always T and T is not always writable to ForwardIt
required *first = new_value
to be valid instead

[edit] 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
(niebloid)[edit]