std::ranges...copy_result(3)
π¦ std::ranges::unique_copy, std::ranges::unique_copy_result π¦
okay bestie, welcome to the C++ Standard Library manual page (3) for std::ranges::unique_copy and std::ranges::unique_copy_result. Itβs giving algorithm royalty, no cap. π
π NAME π
std::ranges::unique_copy,std::ranges::unique_copy_result β std::ranges::unique_copy,std::ranges::unique_copy_result
β¨ Synopsis β¨
Defined in header <algorithm>
πΈ Call signature πΈ
(1) since C++20
template< std::input_iterator I, std::sentinel_for<I> S,
std::weakly_incrementable O,
class Proj = std::identity,
std::indirect_equivalence_relation<std::projected<I, Proj>>
C = ranges::equal_to >
requires std::indirectly_copyable<I, O> &&
(std::forward_iterator<I> ||
(std::input_iterator<O> &&
std::same_as<std::iter_value_t<I>,
std::iter_value_t<O>>) ||
std::indirectly_copyable_storable<I, O>)
constexpr unique_copy_result<I, O>
unique_copy( I first, S last, O result, C comp = {}, Proj proj = {} );
(2) since C++20
template< ranges::input_range R, std::weakly_incrementable O,
class Proj = std::identity,
std::indirect_equivalence_relation<std::projected<ranges::iterator_t<R>,
Proj>> C = ranges::equal_to >
requires std::indirectly_copyable<ranges::iterator_t<R>, O> &&
(std::forward_iterator<ranges::iterator_t<R>> ||
(std::input_iterator<O> &&
std::same_as<ranges::range_value_t<R>,
std::iter_value_t<O>>) ||
std::indirectly_copyable_storable<ranges::iterator_t<R>, O>)
constexpr unique_copy_result<ranges::borrowed_iterator_t<R>, O>
unique_copy( R&& r, O result, C comp = {}, Proj proj = {} );
π§ Helper types π§
(3) since C++20
template< class I, class O >
using unique_copy_result = ranges::in_out_result<I, O>;
1) Copies the elements from the source range [first, last), to the destination range beginning at result in such a way that there are no consecutive equal elements. Only the first element of each group of equal elements is copied.
The ranges [first, last) and [result, result + N) must not overlap. N = ranges::distance(first, last).
π¨ bestie, this is important: the ranges[first, last)and[result, result + N)must not overlap.N = ranges::distance(first, last). Do not play with that. π
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::begin(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 calling 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 inhibited.
In practice, they may be implemented as function objects, or with special compiler extensions.
π Parameters π
first,lastβ the source range of elementsrβ the source range of elementsresultβ the destination range of elementscompβ the binary predicate to compare the projected elementsprojβ the projection to apply to the elements
π«Ά Return value π«Ά
{last, result + N}
thatβs the whole return vibe, bestie β¨
π₯ Complexity π₯
Exactly N - 1 applications of the corresponding predicate comp and no more than twice as many applications of any projection proj.
π Possible implementation π
See also the implementations in libstdc++ and MSVC STL (and third-party libraries: cmcstl2, NanoRange, and range-v3).
struct unique_copy_fn {
template<std::input_iterator I, std::sentinel_for<I> S, std::weakly_incrementable O,
class Proj = std::identity,
std::indirect_equivalence_relation<std::projected<I,
Proj>> C = ranges::equal_to>
requires std::indirectly_copyable<I, O> && (std::forward_iterator<I>
||
(std::input_iterator<O> &&
std::same_as<std::iter_value_t<I>,
std::iter_value_t<O>>) ||
std::indirectly_copyable_storable<I, O>)
constexpr ranges::unique_copy_result<I, O>
operator()(I first, S last, O result, C comp = {}, Proj proj =
{}) const
{
if (!(first == last))
{
std::iter_value_t<I> value = *first;
*result = value;
++result;
while (!(++first == last))
{
auto&& value2 = *first;
if (!std::invoke(comp, std::invoke(proj, value2),
std::invoke(proj, value)))
{
value = std::forward<decltype(value2)>(value2);
*result = value;
++result;
}
}
}
return {std::move(first), std::move(result)};
}
template<ranges::input_range R, std::weakly_incrementable O, class Proj = std::identity,
std::indirect_equivalence_relation<std::projected<ranges::iterator_t<R>,
Proj>> C = ranges::equal_to>
requires std::indirectly_copyable<ranges::iterator_t<R>, O> &&
(std::forward_iterator<ranges::iterator_t<R>> ||
(std::input_iterator<O> &&
std::same_as<ranges::range_value_t<R>,
std::iter_value_t<O>>) ||
std::indirectly_copyable_storable<ranges::iterator_t<R>,
O>)
constexpr ranges::unique_copy_result<ranges::borrowed_iterator_t<R>,
O>
operator()(R&& r, O result, C comp = {}, Proj proj = {}) const
{
return (*this)(ranges::begin(r), ranges::end(r),
std::move(result),
std::move(comp), std::move(proj));
} };
inline constexpr unique_copy_fn unique_copy {};
π Example π
// Run this code
#include <algorithm>
#include <cmath>
#include <iostream>
#include <iterator>
#include <list>
#include <string>
#include <type_traits>
void print(const auto& rem, const auto& v)
{
using V = std::remove_cvref_t<decltype(v)>;
constexpr bool sep{std::is_same_v<typename V::value_type, int>};
std::cout << rem << std::showpos;
for (const auto& e : v)
std::cout << e << (sep ? " " : "");
std::cout << '\n';
}
int main()
{
std::string s1{"The string with many spaces!"};
print("s1: ", s1);
std::string s2;
std::ranges::unique_copy(
s1.begin(), s1.end(), std::back_inserter(s2),
[](char c1, char c2) { return c1 == ' ' && c2 == ' '; }
);
print("s2: ", s2);
const auto v1 = {-1, +1, +2, -2, -3, +3, -3};
print("v1: ", v1);
std::list<int> v2;
std::ranges::unique_copy(
v1, std::back_inserter(v2),
{}, // default comparator std::ranges::equal_to
[](int x) { return std::abs(x); } // projection
);
print("v2: ", v2);
}
Output:
s1: The string with many spaces!
s2: The string with many spaces!
v1: -1 +1 +2 -2 -3 +3 -3
v2: -1 +2 -3
π See also π
ranges::unique(C++20) (niebloid) β removes consecutive duplicate elements in a rangeranges::copy(C++20) (niebloid) β copies a range of elements to a new locationranges::copy_if(C++20) (niebloid) β copies a range of elements to a new locationranges::adjacent_find(C++20) (niebloid) β finds the first two adjacent items that are equal (or satisfy a given predicate)unique_copy(function template) β creates a copy of some range of elements that contains no consecutive duplicates
okay thatβs the whole page, bestie π
source: http://cppreference.com, version/date: 2024.06.10, and the manual title on the tin is std::ranges...copy_result(3). mwah π«Ά
π¦ where this page comes from
- nixpkgs unstable: stdman 2024.07.05
- opensuse-leap 16.0: stdman 2024.07.05-bp160.1.9 Β· MIT
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms