Spec-Zone.ru › C++

std::replace_copy, std::replace_copy_if

Определено в заголовочном файле <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 с C++20)
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 );
(2) (constexpr с C++20)
(до 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 );
(начиная с C++26)
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 );
(3) (начиная с C++17)
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 );
(4) (начиная с C++17)
(до 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 );
(начиная с C++26)

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

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

std::is_execution_policy_v<std::decay_t<ExecutionPolicy>>

(до C++20)

std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>

(начиная с C++20)

Если результат любого из выражений *first и new_value нельзя записать в d_first, программа некорректна.

Если исходный диапазон и диапазон назначения перекрываются, поведение не определено.

Параметры

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

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

new_value - значение, используемое для замены
policy - политика выполнения, которую следует использовать
Требования к типам
-InputIt должен удовлетворять требованиям LegacyInputIterator.
-OutputIt должен удовлетворять требованиям LegacyOutputIterator.
-ForwardIt1, ForwardIt2 должен удовлетворять требованиям LegacyForwardIterator.

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

Итератор, следующий за последним элементом диапазона назначения.

Сложность

Пусть \(\scriptsize N\)N — std::distance(first, last):

1) Ровно \(\scriptsize N\)N сравнений с использованием operator==.
2) Ровно \(\scriptsize N\)N вызовов предиката p.
3) \(\scriptsize \mathcal{O}(N)\)𝓞(N) сравнений с использованием operator==.
4) \(\scriptsize \mathcal{O}(N)\)𝓞(N) вызовов предиката p.

Исключения

3,4) Во время выполнения:
  • Если временные ресурсы памяти, необходимые для параллельного выполнения, недоступны, генерируется std::bad_alloc.
  • Если при доступе к объектам через аргумент алгоритма возникает неперехваченное исключение, поведение определяется политикой выполнения (для стандартных политик вызывается std::terminate).

Примечания

Макрос проверки поддержки возможностей Значение Стандарт Возможность
__cpp_lib_algorithm_default_value_type 202403 (C++26) Инициализация списком для алгоритмов (3,4)

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

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;
}

Пример

#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);
}

Вывод:

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)

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

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

DR Применяется к Опубликованное поведение Исправленное поведение
LWG 283 C++98 Для T требовалось соответствие требованиям CopyAssignable (и EqualityComparable для
replace_copy), но тип значения InputIt не всегда является T
требование удалено
LWG 337 C++98 Для replace_copy_if требовалось только, чтобы InputIt
удовлетворял требованиям LegacyIterator[1]
исправлено на
LegacyInputIterator
  1. Фактическая ошибка в стандарте C++ заключается в том, что параметр шаблона InputIterator был ошибочно указан как Iterator. Это влияет на требования к типам, поскольку в стандарте C++ указано, что для шаблонов функций из библиотеки алгоритмов параметры типа шаблона, чье имя оканчивается на Iterator, подразумевают требования к типам соответствующих категорий итераторов.

См. также

ranges::replace_copyranges::replace_copy_if
(C++20)(C++20)
копирует диапазон, заменяя элементы, соответствующие определенным критериям, другим значением
(функциональный объект алгоритма)
replacereplace_if
заменяет все значения, соответствующие определенным критериям, другим значением
(шаблон функции и функциональный объект алгоритма)
ranges::replaceranges::replace_if
(C++20)(C++20)
removeremove_if
удаляет элементы, соответствующие определенным критериям
(шаблон функции и функциональный объект алгоритма)
ranges::removeranges::remove_if
(C++20)(C++20)

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

Spec-Zone.ru

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