Spec-Zone.ru › C++

std::unique_copy

Определён в заголовочном файле <algorithm>
template< class InputIt, class OutputIt >
OutputIt unique_copy( InputIt first, InputIt last, OutputIt d_first );
(1) (constexpr начиная с C++20)
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2 >
ForwardIt2 unique_copy( ExecutionPolicy&& policy, ForwardIt1 first,
                        ForwardIt1 last, ForwardIt2 d_first );
(2) (начиная с C++17)
template< class InputIt, class OutputIt, class BinaryPred >
OutputIt unique_copy( InputIt first, InputIt last,
                      OutputIt d_first, BinaryPred p );
(3) (constexpr начиная с C++20)
template< class ExecutionPolicy, class ForwardIt1,
          class ForwardIt2, class BinaryPred >
ForwardIt2 unique_copy( ExecutionPolicy&& policy,
                        ForwardIt1 first, ForwardIt1 last,
                        ForwardIt2 d_first, BinaryPred p );
(4) (начиная с C++17)

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

1) Элементы сравниваются с помощью operator==.
Если operator== не задаёт отношение эквивалентности, поведение не определено.
3) Элементы сравниваются с помощью заданного бинарного предиката p.
Если p не задаёт отношение эквивалентности, поведение не определено.
2,4) То же, что и (1,3), но выполняется в соответствии с 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)

Если *d_first = *first некорректно(до C++20)*first нельзя записать в d_first(начиная с C++20), программа некорректна.

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

Пусть T — тип значения InputIt. Если перегрузка (1) или (3) не удовлетворяет всем следующим условиям, поведение не определено:

  • InputIt соответствует требованиям LegacyForwardIterator.
(до C++20)
  • InputIt моделирует forward_iterator.
(начиная с C++20)
  • T удовлетворяет требованиям CopyConstructible и CopyAssignable.
  • Выполняются все следующие условия:
    • OutputIt соответствует требованиям LegacyForwardIterator.
    • Тип значения OutputIt также является T.
    • T удовлетворяет требованиям CopyAssignable.

Параметры

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

Сигнатура функции-предиката должна быть эквивалентна следующей:

boolpred(constType1&a,constType2&b);

Хотя сигнатура не обязана содержать const &, функция не должна изменять переданные ей объекты и должна принимать любые значения типа (возможно, const) Type1 и Type2 независимо от категории значения (следовательно, Type1 & не допускается, как и Type1, за исключением случая, когда для Type1 перемещение эквивалентно копированию(начиная с C++11)).
Типы Type1 и Type2 должны быть такими, чтобы объект типа InputIt можно было разыменовать, а полученное значение неявно преобразовать в каждый из этих типов. ​

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

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

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

Сложность

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

1,2) Ровно \(\scriptsize max(0,N-1)\)max(0,N-1) сравнений с помощью operator==.
3,4) Ровно \(\scriptsize max(0,N-1)\)max(0,N-1) применений предиката p.

Для перегрузок (2,4) возможны дополнительные затраты производительности, если тип значения ForwardIt1 не удовлетворяет одновременно требованиям CopyConstructible и CopyAssignable.

Исключения

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

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

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

См. также реализации в libstdc++ и libc++.

Примечания

Если InputIt удовлетворяет требованиям LegacyForwardIterator, эта функция повторно читает входные данные, чтобы обнаружить дубликаты.

В противном случае, если OutputIt удовлетворяет требованиям LegacyForwardIterator и тип значения InputIt совпадает с типом значения OutputIt, эта функция сравнивает *d_first с *first.

В противном случае эта функция сравнивает *first с локальной копией элемента.

Пример

#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>

int main()
{
    std::string s1 {"A string with mmmany letters!"};
    std::cout << "Before: " << s1 << '\n';

    std::string s2;
    std::unique_copy(s1.begin(), s1.end(), std::back_inserter(s2),
                     [](char c1, char c2) { return c1 == 'm' && 'm' == c2; });

    std::cout << "After:  " << s2 << '\n';
}

Вывод:

Before: A string with mmmany letters!
After:  A string with many letters!

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

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

DR Применён к Опубликованное поведение Корректное поведение
LWG 239 C++98 предикат применялся std::distance(first, last) раз применяется на один раз меньше
(для непустых диапазонов)
LWG 241 C++98 тип значения InputIt не обязан был удовлетворять требованиям CopyConstructible требование предъявляется при определённых условиях
LWG 538 C++98 тип значения InputIt не обязан был удовлетворять требованиям CopyAssignable требование предъявляется при определённых условиях
LWG 2439 C++98 тип значения InputIt не обязан был удовлетворять требованиям
CopyConstructible, если OutputIt является LegacyForwardIterator
требование предъявляется при определённых условиях

См. также

adjacent_find
находит первые два соседних элемента, которые равны (или удовлетворяют заданному предикату)
(шаблон функции и функциональный объект-алгоритм)
ranges::adjacent_find
(C++20)
unique
удаляет соседние повторяющиеся элементы из диапазона
(шаблон функции и функциональный объект-алгоритм)
ranges::unique
(C++20)
copycopy_if
(C++11)
копирует диапазон элементов в новое место
(шаблон функции и функциональный объект-алгоритм)
ranges::copyranges::copy_if
(C++20)(C++20)
ranges::unique_copy
(C++20)
создаёт копию части диапазона элементов, в которой нет соседних дубликатов
(функциональный объект-алгоритм)

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

Spec-Zone.ru

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