Namespaces
Variants
Views
Actions

Difference between revisions of "cpp/algorithm/replace"

From cppreference.com
< cpp‎ | algorithm
m (~{range})
m (FTM.)
 
(6 intermediate revisions by 4 users not shown)
Line 3: Line 3:
 
{{dcl begin}}
 
{{dcl begin}}
 
{{dcl header|algorithm}}
 
{{dcl header|algorithm}}
{{dcl rev multi|num=1|anchor=1|until1=c++20|dcl1=
+
{{dcl rev begin|num=1}}
 +
{{dcla|anchor=1|constexpr=c++20|until=c++26|
 
template< class ForwardIt, class T >
 
template< class ForwardIt, class T >
 
void replace( ForwardIt first, ForwardIt last,
 
void replace( ForwardIt first, ForwardIt last,
 
               const T& old_value, const T& new_value );
 
               const T& old_value, const T& new_value );
|dcl2=
+
}}
template< class ForwardIt, class T >
+
{{dcl|since=c++26|1=
 +
template< class ForwardIt, class T = typename std::iterator_traits
 +
                                        <ForwardIt>::value_type >
 
constexpr void replace( ForwardIt first, ForwardIt last,
 
constexpr void replace( ForwardIt first, ForwardIt last,
 
                         const T& old_value, const T& new_value );
 
                         const T& old_value, const T& new_value );
 
}}
 
}}
{{dcl|since=c++17|num=2|1=
+
{{dcl rev end}}
 +
{{dcl rev begin|num=2}}
 +
{{dcl|since=c++17|until=c++26|
 
template< class ExecutionPolicy, class ForwardIt, class T >
 
template< class ExecutionPolicy, class ForwardIt, class T >
void replace( ExecutionPolicy&& policy, ForwardIt first, ForwardIt last,
+
void replace( ExecutionPolicy&& policy,
 +
              ForwardIt first, ForwardIt last,
 
               const T& old_value, const T& new_value );
 
               const T& old_value, const T& new_value );
 
}}
 
}}
{{dcl rev multi|num=3|anchor=3|until1=c++20|dcl1=
+
{{dcl|since=c++26|1=
template< class ForwardIt, class UnaryPredicate, class T >
+
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,
 
void replace_if( ForwardIt first, ForwardIt last,
                 UnaryPredicate p, const T& new_value );
+
                 UnaryPred p, const T& new_value );
|dcl2=
+
}}
template< class ForwardIt, class UnaryPredicate, class T >
+
{{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,
 
constexpr void replace_if( ForwardIt first, ForwardIt last,
                           UnaryPredicate p, const T& new_value );
+
                           UnaryPred p, const T& new_value );
 
}}
 
}}
{{dcl|since=c++17|num=4|1=
+
{{dcl rev end}}
template< class ExecutionPolicy, class ForwardIt,
+
{{dcl rev begin|num=4}}
           class UnaryPredicate, class T >
+
{{dcl|since=c++17|until=c++26|
void replace_if( ExecutionPolicy&& policy, ForwardIt first, ForwardIt last,
+
template< class ExecutionPolicy,
                 UnaryPredicate p, const T& new_value );
+
          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}}
 
{{dcl end}}
  
Replaces all elements satisfying specific criteria with {{c|new_value}} in the range {{range|first| last}}.  
+
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==}}).
  
@1@ Replaces all elements that are equal to {{c|old_value}} (using {{tt|1=operator==}}).
 
 
@3@ Replaces all elements for which predicate {{c|p}} returns {{c|true}}.
 
@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=true}}
+
 
 +
@2,4@ Same as {{v|1,3}}, but executed according to {{c|policy}}.
 +
@@ {{cpp/algorithm/parallel overload precondition|plural=yes}}
 +
 
 +
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===
Line 49: Line 85:
 
{{par hreq}}
 
{{par hreq}}
 
{{par req named|ForwardIt|ForwardIterator}}
 
{{par req named|ForwardIt|ForwardIterator}}
{{par req named|UnaryPredicate|Predicate}}
+
{{par req named|UnaryPred|Predicate}}
 
{{par end}}
 
{{par end}}
{{rrev multi|until1=c++20
 
|rev1=The expression {{c|1=*first = new_value}} must be valid.
 
|rev2={{c|new_value}} must be [[cpp/iterator#Types and writability|writable]] to {{c|first}}.
 
}}
 
  
 
===Return value===
 
===Return value===
Line 60: Line 92:
  
 
===Complexity===
 
===Complexity===
Given {{tt|N}} as {{c|std::distance(first, last)}}:
+
Given {{mathjax-or|\(\scriptsize N\)|N}} as {{c|std::distance(first, last)}}:
@1,2@ exactly {{tt|N}} comparisons with {{c|old_value}} using {{tt|1=operator==}}
+
@1,2@ Exactly {{mathjax-or|\(\scriptsize N\)|N}} comparisons using {{c/core|1=operator==}}.
@3,4@ exactly {{tt|N}} applications of the predicate {{c|p}}
+
@3,4@ Exactly {{mathjax-or|\(\scriptsize N\)|N}} applications of the predicate {{c|p}}.
  
 
===Exceptions===
 
===Exceptions===
Line 68: Line 100:
  
 
===Notes===
 
===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 {{tt|[first, last)}}.
+
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 impl
 
{{eq impl
 
|title1=replace|ver1=1|1=
 
|title1=replace|ver1=1|1=
template<class ForwardIt, class T>
+
template<class ForwardIt,
 +
        class T = typename std::iterator_traits<ForwardIt>::value_type>
 
void replace(ForwardIt first, ForwardIt last,
 
void replace(ForwardIt first, ForwardIt last,
 
             const T& old_value, const T& new_value)
 
             const T& old_value, const T& new_value)
Line 82: Line 117:
 
}
 
}
 
|title2=replace_if|ver2=3|2=
 
|title2=replace_if|ver2=3|2=
template<class ForwardIt, class UnaryPredicate, class T>
+
template<class ForwardIt, class UnaryPred,
 +
        class T = typename std::iterator_traits<ForwardIt>::value_type>
 
void replace_if(ForwardIt first, ForwardIt last,
 
void replace_if(ForwardIt first, ForwardIt last,
                 UnaryPredicate p, const T& new_value)
+
                 UnaryPred p, const T& new_value)
 
{
 
{
 
     for (; first != last; ++first)
 
     for (; first != last; ++first)
Line 94: 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 {{c|55}}.
 
 
|code=
 
|code=
 
#include <algorithm>
 
#include <algorithm>
 
#include <array>
 
#include <array>
 +
#include <complex>
 
#include <functional>
 
#include <functional>
 
#include <iostream>
 
#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)
+
 
        std::cout << a << ' ';
+
     // Replace all values less than 5 with 55.
    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);
      
+
     println(s);
    for (int a : 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 88 6 55 9 55 55
 
5 7 55 55 88 6 55 9 55 55
 +
(4,2), (4,2)
 
}}
 
}}
  

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]