FreeBSD Manual Pages
std::ranges::unique(3) C++ Standard Libary std::ranges::unique(3) NAME std::ranges::unique - std::ranges::unique Synopsis Defined in header <algorithm> Call signature template< std::permutable I, std::sentinel_for<I> S, class Proj = std::identity, std::indirect_equivalence_relation<std::projected<I, Proj>> (1) (since C = ranges::equal_to > C++20) constexpr ranges::subrange<I> unique( I first, S last, C comp = {}, Proj proj = {} ); template< ranges::forward_range R, class Proj = std::identity, std::indirect_equivalence_relation<std::projected<ranges::itera- tor_t<R>, Proj>> (2) (since C = ranges::equal_to > C++20) requires std::permutable<ranges::iterator_t<R>> constexpr ranges::borrowed_subrange_t<R> unique( R&& r, C comp = {}, Proj proj = {} ); 1) Eliminates all except the first element from every consecutive group of equivalent elements from the range [first, last) and returns a sub- range [ret, last), where ret is a past-the-end iterator for the new end of the range. Two consecutive elements *(i - 1) and *i are considered equivalent if std::invoke(comp, std::invoke(proj, *(i - 1)), std::invoke(proj, *i)) == true, where i is an iterator in the range [first + 1, last). 2) Same as (1), but uses r as the range, as if using ranges::be- gin(r) as first, and ranges::end(r) as last. The function-like entities described on this page are niebloids, that is: * Explicit template argument lists cannot be specified when call- ing any of them. * None of them are visible to argument-dependent lookup. * When any of them are found by normal unqualified lookup as the name to the left of the function-call operator, argument-dependent lookup is in- hibited. In practice, they may be implemented as function objects, or with special compiler extensions. Parameters first, last - the range of elements to process r - the range of elements to process comp - the binary predicate to compare the projected elements proj - the projection to apply to the elements Return value Returns {ret, last}, where ret is a past-the-end iterator for the new end of the range. Complexity For nonempty ranges, exactly ranges::distance(first, last) - 1 ap- plications of the corresponding predicate comp and no more that twice as many applica- tions of any projection proj. Notes Removing is done by shifting (by means of move assignment) the ele- ments in the range in such a way that the elements that are not to be removed appear in the beginning of the range. Relative order of the elements that remain is pre- served and the physical size of the container is unchanged. Iterators in [ret, last) (if any) are still dereferenceable, but the elements themselves have unspecified values (as per MoveAssignable post-condition). A call to ranges::unique is sometimes followed by a call to a con- tainers erase member function, which erases the unspecified values and reduces the physical size of the container to match its new logical size. These two invoca- tions together model the Eraseremove idiom. Possible implementation 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::in- voke(proj, *first))) *++i = ranges::iter_move(first); return {++i, first}; } template<ranges::forward_range R, class Proj = std::identity, std::indirect_equivalence_relation<std::pro- jected<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 {}; Example // Run this code #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() { // a vector containing several duplicated elements std::vector<int> v {1, 2, 1, 1, 3, 3, 3, 4, 5, 4}; print(id {1}, v); // remove consecutive (adjacent) duplicates const auto ret = std::ranges::unique(v); // v now holds {1 2 1 3 4 5 4 x x x}, where 'x' is indeterminate v.erase(ret.begin(), ret.end()); print(id {2}, v); // sort followed by unique, to remove all duplicates 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 now holds {1 2 3 4 5 x x}, where 'x' is indeterminate v.erase(first, last); print(id {4}, v); // unique with custom comparison and projection 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, // consider two complex nums equal if their real parts are equal by module: [](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); } Output: 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) See also ranges::unique_copy creates a copy of some range of elements that contains no (C++20) consecutive duplicates (niebloid) ranges::adjacent_find finds the first two adjacent items that are equal (or satisfy (C++20) a given predicate) (niebloid) ranges::remove ranges::remove_if removes elements satisfying specific criteria (C++20) (niebloid) (C++20) unique removes consecutive duplicate elements in a range (function template) unique removes consecutive duplicate elements (public member function of std::list<T,Alloca- tor>) removes consecutive duplicate elements unique (public member function of std::for- ward_list<T,Allocator>) http://cppreference.com 2024.06.10 std::ranges::unique(3)
NAME | Synopsis | Parameters | Return value | Complexity | Notes | Possible implementation | Example | Output: | See also
Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=std::ranges::unique&sektion=3&manpath=FreeBSD+Ports+15.1.quarterly>
