Namespaces
Variants

std::ranges:: unique

From cppreference.net
Algorithm library
Constrained algorithms and algorithms on ranges (C++20)
Constrained algorithms, e.g. ranges::copy , ranges::sort , ...
Execution policies (C++17)
Non-modifying sequence operations
Batch operations
(C++17)
Search operations
Modifying sequence operations
Copy operations
(C++11)
(C++11)
Swap operations
Transformation operations
Generation operations
Removing operations
Order-changing operations
(until C++17) (C++11)
(C++20) (C++20)
Sampling operations
(C++17)

Sorting and related operations
Partitioning operations
Sorting operations
Binary search operations
(on partitioned ranges)
Set operations (on sorted ranges)
Merge operations (on sorted ranges)
Heap operations
Minimum/maximum operations
Lexicographical comparison operations
Permutation operations
C library
Numeric operations
Operations on uninitialized memory
Constrained algorithms
All names in this menu belong to namespace std::ranges
Non-modifying sequence operations
Modifying sequence operations
Partitioning operations
Sorting operations
Binary search operations (on sorted ranges)
Set operations (on sorted ranges)
Heap operations
Minimum/maximum operations
Permutation operations
Fold operations
Operations on uninitialized storage
Return types
헤더 파일에 정의됨 <algorithm>
함수 시그니처
template < std:: permutable I, std:: sentinel_for < I > S, class Proj = std:: identity ,

std:: indirect_equivalence_relation < std :: projected < I, Proj >>
C = ranges:: equal_to >
constexpr ranges:: subrange < I >

unique ( I first, S last, C comp = { } , Proj proj = { } ) ;
(1) (C++20부터)
template < ranges:: forward_range R, class Proj = std:: identity ,

std:: indirect_equivalence_relation < std :: projected < ranges:: iterator_t < R > , Proj >>
C = ranges:: equal_to >
requires std:: permutable < ranges:: iterator_t < R >>
constexpr ranges:: borrowed_subrange_t < R >

unique ( R && r, C comp = { } , Proj proj = { } ) ;
(2) (C++20부터)
1) 동등한 요소들의 연속된 그룹에서 첫 번째 요소를 제외한 모든 요소를 범위 [ first , last ) 에서 제거하고, [ ret , last ) 서브범위를 반환합니다. 여기서 ret 는 범위의 새로운 끝을 가리키는 past-the-end iterator입니다.
두 개의 연속된 요소 *(i - 1) *i 는 다음 조건이 std:: invoke ( comp, std:: invoke ( proj, * ( i - 1 ) ) , std:: invoke ( proj, * i ) ) == true 일 때 동등한 것으로 간주됩니다. 여기서 i 는 범위 [ first + 1 , last ) 내의 반복자입니다.
2) (1) 과 동일하지만, r 를 범위로 사용하며, 마치 ranges:: begin ( r ) first 로, ranges:: end ( r ) last 로 사용하는 것과 같습니다.

이 페이지에서 설명하는 함수형 개체들은 algorithm function objects (일반적으로 niebloids 로 알려진)입니다. 즉:

목차

매개변수

first, last - 처리할 요소들의 범위 를 정의하는 반복자-감시자 쌍
r - 처리할 요소들의 범위
comp - 투영된 요소들을 비교하기 위한 이항 조건자
proj - 요소들에 적용할 투영

반환값

{ ret, last } 를 반환합니다. 여기서 ret 는 범위의 새로운 끝을 지나는 past-the-end 반복자입니다.

복잡도

비어 있지 않은 범위의 경우, 정확히 ranges:: distance ( first, last ) - 1 번의 해당 predicate comp 적용과, 어떤 projection proj 도 최대 두 배 이하로 적용됩니다.

참고 사항

제거는 범위 내 요소들을 이동 대입(move assignment)을 통해 이동시킴으로써 수행되며, 제거되지 않을 요소들이 범위의 시작 부분에 나타나도록 합니다. 남아 있는 요소들의 상대적 순서는 유지되며 컨테이너의 물리적 크기는 변경되지 않습니다. [ ret , last ) 범위의 반복자(있는 경우)는 여전히 역참조 가능하지만, 요소 자체는 지정되지 않은 값을 가집니다( MoveAssignable 사후 조건에 따름).

ranges::unique 에 대한 호출은 때때로 컨테이너의 erase 멤버 함수 호출 뒤에 이루어지며, 이는 지정되지 않은 값을 지우고 컨테이너의 물리적 크기를 새로운 논리적 크기에 맞게 축소합니다. 이 두 호출을 함께 사용하면 Erase–remove 관용구 를 구현하는 모델이 됩니다.

가능한 구현

struct unique_fn
{
    template<std::permutable I, std::sentinel_for<I> S, class Proj = std::identity,
             std::indirect_equivalence_relation<std::projected<I, Proj>>
                 C = ranges::equal_to>
    constexpr ranges::subrange<I>
        operator()(I first, S last, C comp = {}, Proj proj = {}) const
    {
        first = ranges::adjacent_find(first, last, comp, proj);
        if (first == last)
            return {first, first};
        auto i {first};
        ++first;
        while (++first != last)
            if (!std::invoke(comp, std::invoke(proj, *i), std::invoke(proj, *first)))
                *++i = ranges::iter_move(first);
        return {++i, first};
    }
    template<ranges::forward_range R, class Proj = std::identity,
             std::indirect_equivalence_relation<std::projected<ranges::iterator_t<R>, Proj>>
                 C = ranges::equal_to>
    requires std::permutable<ranges::iterator_t<R>>
    constexpr ranges::borrowed_subrange_t<R>
        operator()(R&& r, C comp = {}, Proj proj = {}) const
    {
        return (*this)(ranges::begin(r), ranges::end(r),
                       std::move(comp), std::move(proj));
    }
};
inline constexpr unique_fn unique {};

예제

#include <algorithm>
#include <cmath>
#include <complex>
#include <iostream>
#include <vector>
struct id {
    int i;
    explicit id(int i) : i {i} {}
};
void print(id i, const auto& v)
{
    std::cout << i.i << ") ";
    std::ranges::for_each(v, [](auto const& e) { std::cout << e << ' '; });
    std::cout << '\n';
}
int main()
{
    // 여러 중복 요소를 포함하는 벡터
    std::vector<int> v {1, 2, 1, 1, 3, 3, 3, 4, 5, 4};
    print(id {1}, v);
    // 연속된 (인접한) 중복 제거
    const auto ret = std::ranges::unique(v);
    // v는 이제 {1 2 1 3 4 5 4 x x x}를 보유, 여기서 'x'는 불확정 값
    v.erase(ret.begin(), ret.end());
    print(id {2}, v);
    // 모든 중복을 제거하기 위한 정렬 후 unique 적용
    std::ranges::sort(v); // {1 1 2 3 4 4 5}
    print(id {3}, v);
    const auto [first, last] = std::ranges::unique(v.begin(), v.end());
    // v는 이제 {1 2 3 4 5 x x}를 보유, 여기서 'x'는 불확정 값
    v.erase(first, last);
    print(id {4}, v);
    // 사용자 정의 비교 및 투영을 사용한 unique
    std::vector<std::complex<int>> vc { {1, 1}, {-1, 2}, {-2, 3}, {2, 4}, {-3, 5} };
    print(id {5}, vc);
    const auto ret2 = std::ranges::unique(vc,
        // 두 복소수가 실수부의 절대값이 같으면 동일한 것으로 간주:
        [](int x, int y) { return std::abs(x) == std::abs(y); }, // comp
        [](std::complex<int> z) { return z.real(); }             // proj
    );
    vc.erase(ret2.begin(), ret2.end());
    print(id {6}, vc);
}

출력:

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
5) (1,1) (-1,2) (-2,3) (2,4) (-3,5)
6) (1,1) (-2,3) (-3,5)

참고 항목

연속적인 중복 요소가 없는 일부 범위의 복사본을 생성합니다
(알고리즘 함수 객체)
서로 인접한 두 항목이 같거나(또는 주어진 조건자를 만족하는) 첫 번째 쌍을 찾습니다
(알고리즘 함수 객체)
특정 기준을 만족하는 요소들을 제거합니다
(알고리즘 함수 객체)
범위에서 연속적인 중복 요소를 제거합니다
(함수 템플릿)
연속적인 중복 요소를 제거합니다
( std::list<T,Allocator> 의 public 멤버 함수)
연속적인 중복 요소를 제거합니다
( std::forward_list<T,Allocator> 의 public 멤버 함수)