Spec-Zone.ru › C++

std::remove_copy, std::remove_copy_if

Определено в заголовке <algorithm>
(1)
template< class InputIt, class OutputIt, class T >
OutputIt remove_copy( InputIt first, InputIt last,
                      OutputIt d_first, const T& value );
(до C++20)
template< class InputIt, class OutputIt, class T >
constexpr OutputIt remove_copy( InputIt first, InputIt last,
                                OutputIt d_first, const T& value );
(с C++20)
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2, class T >
ForwardIt2 remove_copy( ExecutionPolicy&& policy,
                        ForwardIt1 first, ForwardIt1 last,
                        ForwardIt2 d_first, const T& value );
(2) (с C++17)
(3)
template< class InputIt, class OutputIt, class UnaryPredicate >
OutputIt remove_copy_if( InputIt first, InputIt last,
                         OutputIt d_first, UnaryPredicate p );
(до C++20)
template< class InputIt, class OutputIt, class UnaryPredicate >
constexpr OutputIt remove_copy_if( InputIt first, InputIt last,
                                   OutputIt d_first, UnaryPredicate p );
(с C++20)
template< class ExecutionPolicy, class ForwardIt1,
          class ForwardIt2, class UnaryPredicate >
ForwardIt2 remove_copy_if( ExecutionPolicy&& policy,
                           ForwardIt1 first, ForwardIt1 last,
                           ForwardIt2 d_first, UnaryPredicate p );
(4) (с C++17)

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

1) Игнорирует все элементы, равные value.
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 - диапазон копируемых элементов
d_first - начало целевого диапазона
value - значение элементов, которые не нужно копировать
policy - используемая политика выполнения. Подробнее см. политика выполнения.
Требования к типам
-InputIt должно удовлетворять требованиям LegacyInputIterator.
-OutputIt должно удовлетворять требованиям LegacyOutputIterator.
-ForwardIt1, ForwardIt2 должно удовлетворять требованиям LegacyForwardIterator.
-UnaryPredicate должно удовлетворять требованиям Предикат.

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

(до C++20)

*first должно быть доступным для записи для d_first.

(с C++20)

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

Итератор, указывающий на элемент после последнего скопированного элемента.

Сложность

Учитывая N как std::distance(first, last):

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

Для перегрузок с политикой выполнения, может возникнуть дополнительная стоимость, если ForwardIt1 тип value_type не MoveConstructible.

Исключения

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

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

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

remove_copy
template<class InputIt, class OutputIt, class T>
OutputIt remove_copy(InputIt first, InputIt last, OutputIt d_first, const T& value)
{
    for (; first != last; ++first)
        if (!(*first == value))
            *d_first++ = *first;
    return d_first;
}
remove_copy_if
template<class InputIt, class OutputIt, class UnaryPredicate>
OutputIt remove_copy_if(InputIt first, InputIt last, OutputIt d_first, UnaryPredicate p)
{
    for (; first != last; ++first)
        if (!p(*first))
            *d_first++ = *first;
    return d_first;
}

Пример

Следующий код выводит строку, удаляя символы '#' на лету.

#include <algorithm>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <string>
 
int main()
{
    std::string str = "#Return #Value #Optimization";
    std::cout << "before: " << std::quoted(str) << '\n';
 
    std::cout << "after:  \"";
    std::remove_copy(str.begin(), str.end(),
                     std::ostream_iterator<char>(std::cout), '#');
    std::cout << "\"\n";
}

Вывод:

before: "#Return #Value #Optimization"
after:  "Return Value Optimization"

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

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

DR Применимо к Опубликованное поведение Корректное поведение
LWG 779 C++98 T должно было быть EqualityComparable, но
тип значения ForwardIt не всегда T
требование *d_first = *first
должно быть допустимым вместо

См. также

removeremove_if
удаляет элементы, удовлетворяющие определённым критериям
(шаблон функции)
copycopy_if
(C++11)
копирует диапазон элементов в новое местоположение
(шаблон функции)
partition_copy
(C++11)
копирует диапазон, разделяя элементы на две группы
(шаблон функции)
ranges::remove_copyranges::remove_copy_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/remove_copy

Spec-Zone.ru

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