std::unique
Определено в заголовке <algorithm> |
||
|---|---|---|
| (1) | ||
template< class ForwardIt > ForwardIt unique( ForwardIt first, ForwardIt last ); |
(до C++20) | |
template< class ForwardIt > constexpr ForwardIt unique( ForwardIt first, ForwardIt last ); |
(с C++20) | |
template< class ExecutionPolicy, class ForwardIt > ForwardIt unique( ExecutionPolicy&& policy, ForwardIt first, ForwardIt last ); |
(2) | (с C++17) |
| (3) | ||
template< class ForwardIt, class BinaryPredicate > ForwardIt unique( ForwardIt first, ForwardIt last, BinaryPredicate p ); |
(до C++20) | |
template< class ForwardIt, class BinaryPredicate >
constexpr ForwardIt unique( ForwardIt first, ForwardIt last,
BinaryPredicate p );
|
(с C++20) | |
template< class ExecutionPolicy, class ForwardIt, class BinaryPredicate >
ForwardIt unique( ExecutionPolicy&& policy,
ForwardIt first, ForwardIt last, BinaryPredicate p );
|
(4) | (с C++17) |
Удаляет все, кроме первого элемента, из каждой последовательной группы эквивалентных элементов из диапазона [first, last) и возвращает итератор, указывающий на позицию после последнего элемента нового логического конца диапазона.
Удаление выполняется путем перемещения элементов в диапазоне таким образом, что удаляемые элементы перезаписываются.
operator==. Поведение является неопределенным, если это не отношение эквивалентности.p. Поведение является неопределенным, если это не отношение эквивалентности.policy. Эти перегрузки не участвуют в разрешении перегрузки, если |
| (до C++20) |
|
| (с C++20) |
Параметры
| first, last | - | диапазон обрабатываемых элементов |
| policy | - | политика выполнения. Подробности см. в политике выполнения. |
| p | - | бинарный предикат, возвращающий true, если элементы должны рассматриваться как равные. Подпись предикатной функции должна быть эквивалентна следующей:
Хотя подпись не обязательно должна содержать |
| Требования к типу | ||
-ForwardIt должно соответствовать требованиям LegacyForwardIterator. |
||
-Тип де-референсированного ForwardIt должен соответствовать требованиям MoveAssignable. |
||
Возвращаемое значение
Итератор ForwardIt на новый конец диапазона.
Сложность
Для непустых диапазонов, ровно std::distance(first, last) - 1 применений соответствующего предиката.
Исключения
Перегрузки с параметром шаблона под названием ExecutionPolicy сообщают об ошибках следующим образом:
- Если выполнение функции, вызванной в рамках алгоритма, генерирует исключение, и
ExecutionPolicyявляется одной из стандартных политик,std::terminateвызывается. Для любой другойExecutionPolicy, поведение является определённым реализацией. - Если алгоритм не может выделить память, выбрасывается
std::bad_alloc.
Примечания
Относительный порядок оставшихся элементов сохраняется, и физический размер контейнера не изменяется. Итераторы в [r, last) (если таковые имеются), где r является возвращаемым значением, по-прежнему могут быть использованы для доступа к элементам, но сами элементы имеют неопределённые значения. Вызов unique обычно следует за вызовом erase функции контейнера, которая стирает неопределённые значения и уменьшает физический размер контейнера для соответствия его новому логическому размеру.
Возможная реализация
См. также реализации в libstdc++, libc++ и MSVC STL.
| unique (1) |
|---|
template<class ForwardIt>
ForwardIt unique(ForwardIt first, ForwardIt last)
{
if (first == last)
return last;
ForwardIt result = first;
while (++first != last)
if (!(*result == *first) && ++result != first)
*result = std::move(*first);
return ++result;
} |
| unique (3) |
template<class ForwardIt, class BinaryPredicate>
ForwardIt unique(ForwardIt first, ForwardIt last, BinaryPredicate p)
{
if (first == last)
return last;
ForwardIt result = first;
while (++first != last)
if (!p(*result, *first) && ++result != first)
*result = std::move(*first);
return ++result;
} |
Пример
#include <algorithm>
#include <iostream>
#include <vector>
int main()
{
// a vector containing several duplicate elements
std::vector<int> v {1, 2, 1, 1, 3, 3, 3, 4, 5, 4};
auto print = [&](int id)
{
std::cout << "@" << id << ": ";
for (int i : v)
std::cout << i << ' ';
std::cout << '\n';
};
print(1);
// remove consecutive (adjacent) duplicates
auto last = std::unique(v.begin(), v.end());
// v now holds {1 2 1 3 4 5 4 x x x}, where 'x' is indeterminate
v.erase(last, v.end());
print(2);
// sort followed by unique, to remove all duplicates
std::sort(v.begin(), v.end()); // {1 1 2 3 4 4 5}
print(3);
last = std::unique(v.begin(), v.end());
// v now holds {1 2 3 4 5 x x}, where 'x' is indeterminate
v.erase(last, v.end());
print(4);
}Вывод:
@1: 1 2 1 1 3 3 3 4 5 4 @2: 1 2 1 3 4 5 4 @3: 1 1 2 3 4 4 5 @4: 1 2 3 4 5
Отчёты об ошибках
Следующие отчёты об ошибках, изменяющие поведение, были применены ретроактивно к ранее опубликованным стандартам C++.
| DR | Применено к | Поведение, как опубликовано | Корректное поведение |
|---|---|---|---|
| LWG 202 | C++98 | поведение было неясно, если элементы сравниваются с использованием не-отношения эквивалентности | поведение является неопределённым в этом случае |
См. также
| находит первые два смежных элемента, которые равны (или удовлетворяют заданному предикату) (функция-шаблон) |
|
| создаёт копию некоторого диапазона элементов, не содержащего последовательных дубликатов (функция-шаблон) |
|
| удаляет элементы, удовлетворяющие определённым критериям (функция-шаблон) |
|
| удаляет последовательные дублирующие элементы (публичный член-функция std::list<T,Allocator>) |
|
| удаляет последовательные дублирующие элементы (публичный член-функция std::forward_list<T,Allocator>) |
|
|
(C++20) |
удаляет последовательные дублирующие элементы в диапазоне (niebloid) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/algorithm/unique