Spec-Zone.ru › C++

std::replace, std::replace_if

Defined in header <algorithm>
(1)
template< class ForwardIt, class T >
void replace( ForwardIt first, ForwardIt last,
              const T& old_value, const T& new_value );
(до C++20)
template< class ForwardIt, class T >
constexpr void replace( ForwardIt first, ForwardIt last,
                        const T& old_value, const T& new_value );
(с C++20)
template< class ExecutionPolicy, class ForwardIt, class T >
void replace( ExecutionPolicy&& policy, ForwardIt first, ForwardIt last,
              const T& old_value, const T& new_value );
(2) (с C++17)
(3)
template< class ForwardIt, class UnaryPredicate, class T >
void replace_if( ForwardIt first, ForwardIt last,
                 UnaryPredicate p, const T& new_value );
(до C++20)
template< class ForwardIt, class UnaryPredicate, class T >
constexpr void replace_if( ForwardIt first, ForwardIt last,
                           UnaryPredicate p, const T& new_value );
(с C++20)
template< class ExecutionPolicy, class ForwardIt,
          class UnaryPredicate, class T >
void replace_if( ExecutionPolicy&& policy, ForwardIt first, ForwardIt last,
                 UnaryPredicate p, const T& new_value );
(4) (с C++17)

Заменяет все элементы, удовлетворяющие определённым критериям, на new_value в диапазоне [first, last).

1) Заменяет все элементы, равные old_value (используя operator==).
3) Заменяет все элементы, для которых предикат p возвращает true.
2,4) То же, что и (1,3), но выполняется в соответствии с policy. Эти перегрузки не участвуют в разрешении перегрузок, если

std::is_execution_policy_v<std::decay_t<ExecutionPolicy>> является true.

(до C++20)

std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>> является true.

(с C++20)

Параметры

first, last - диапазон элементов для обработки
old_value - значение элементов, которые нужно заменить
policy - стратегия выполнения. См. стратегию выполнения для получения более подробной информации.
p - унарный предикат, который возвращает ​true, если значение элемента должно быть заменено.

Выражение p(v) должно быть приводимо к bool для каждого аргумента v типа (возможно const) VT, где VT - тип значения ForwardIt, независимо от категории значения, и не должно изменять v. Таким образом, тип параметра VT& не допускается, также как и VT за исключением случаев, когда для VT перемещение эквивалентно копированию(с C++11). ​

new_value - значение, используемое в качестве замены
Требования к типу
-ForwardIt должно удовлетворять требованиям LegacyForwardIterator.
-UnaryPredicate должно удовлетворять требованиям Predicate.

Выражение *first = new_value должно быть допустимым.

(до C++20)

new_value должно быть изменяемым в first.

(с C++20)

Возвращаемое значение

(нет)

Сложность

Дано N как std::distance(first, last):

1,2) точно N сравнений с old_value с использованием operator==.
3,4) точно N применений предиката p.

Исключения

Перегрузки с параметром шаблона с именем ExecutionPolicy сообщают об ошибках следующим образом:

  • Если выполнение функции, вызванной как часть алгоритма, выбрасывает исключение, и ExecutionPolicy - одна из стандартных стратегий, то std::terminate вызывается. Для любой другой ExecutionPolicy, поведение является определённым реализацией.
  • Если алгоритм не может выделить память, то выбрасывается std::bad_alloc.

Примечания

Поскольку алгоритм принимает old_value и new_value по ссылке, он может иметь непредсказуемое поведение, если любой из них является ссылкой на элемент диапазона [first, last).

Возможная реализация

replace
template<class ForwardIt, class T>
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 UnaryPredicate, class T>
void replace_if(ForwardIt first, ForwardIt last,
                UnaryPredicate p, const T& new_value)
{
    for (; first != last; ++first)
        if (p(*first))
            *first = new_value;
}

Пример

Следующий код сначала заменяет все вхождения 8 на 88 в векторе целых чисел. Затем он заменяет все значения, меньшие 5 на 55.

#include <algorithm>
#include <array>
#include <functional>
#include <iostream>
 
int main()
{
    std::array<int, 10> s{5, 7, 4, 2, 8, 6, 1, 9, 0, 3};
 
    std::replace(s.begin(), s.end(), 8, 88);
 
    for (int a : s)
        std::cout << a << ' ';
    std::cout << '\n';
 
    std::replace_if(s.begin(), s.end(), 
                    std::bind(std::less<int>(), std::placeholders::_1, 5), 55);
 
    for (int a : s)
        std::cout << a << ' ';
    std::cout << '\n';
}

Вывод:

5 7 4 2 88 6 1 9 0 3
5 7 55 55 88 6 55 9 55 55

Отчёты об ошибках

Следующие отчёты об ошибках, меняющие поведение, были применены ретроактивно к ранее опубликованным стандартам C++.

DR Применён к Поведение как опубликовано Правильное поведение
LWG 283 C++98 T должно было быть CopyAssignable (и EqualityComparable
для replace), но тип значения ForwardIt не всегда
является T и T не всегда является изменяемым в ForwardIt
требовалось *first = new_value
быть допустимым вместо

См. также

replace_copyreplace_copy_if
копирует диапазон, заменяя элементы, удовлетворяющие определённым критериям, другим значением
(функция-шаблон)
ranges::replaceranges::replace_if
(C++20)(C++20)
заменяет все значения, удовлетворяющие определённым критериям, другим значением
(niebloid)

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/algorithm/replace

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API