std::ranges::remove_copy, std::ranges::remove_copy_if, std::ranges::remove_copy_result, std::ranges::remove_copy_if_result
From cppreference.com
| Defined in header <algorithm>
|
||
| Call signature |
||
template< std::input_iterator I, std::sentinel_for<I> S,
std::weakly_incrementable O, class T, class Proj = std::identity >
requires std::indirectly_copyable<I, O> &&
std::indirect_binary_predicate
<ranges::equal_to, std::projected<I, Proj>, const T*>
constexpr ranges::remove_copy_result<I, O>
remove_copy( I first, S last, O d_first, const T& value, Proj proj = {} );
|
(1) | (since C++20) (until C++26) |
template< std::input_iterator I, std::sentinel_for<I> S,
std::weakly_incrementable O, class Proj = std::identity,
class T = std::projected_value_t<I, Proj> >
requires std::indirectly_copyable<I, O> &&
std::indirect_binary_predicate
<ranges::equal_to, std::projected<I, Proj>, const T*>
constexpr ranges::remove_copy_result<I, O>
remove_copy( I first, S last, O d_first, const T& value, Proj proj = {} );
|
(since C++26) | |
template< ranges::input_range R,
std::weakly_incrementable O, class T, class Proj = std::identity >
requires std::indirectly_copyable<ranges::iterator_t<R>, O> &&
std::indirect_binary_predicate
<ranges::equal_to,
std::projected<ranges::iterator_t<R>, Proj>, const T*>
constexpr ranges::remove_copy_result<ranges::borrowed_iterator_t<R>, O>
remove_copy( R&& r, O d_first, const T& value, Proj proj = {} );
|
(2) | (since C++20) (until C++26) |
template< ranges::input_range R,
std::weakly_incrementable O, class Proj = std::identity,
class T = std::projected_value_t<ranges::iterator_t<R>, Proj> >
requires std::indirectly_copyable<ranges::iterator_t<R>, O> &&
std::indirect_binary_predicate
<ranges::equal_to,
std::projected<ranges::iterator_t<R>, Proj>, const T*>
constexpr ranges::remove_copy_result<ranges::borrowed_iterator_t<R>, O>
remove_copy( R&& r, O d_first, const T& value, Proj proj = {} );
|
(since C++26) | |
template< std::input_iterator I, std::sentinel_for<I> S,
std::weakly_incrementable O, class Proj = std::identity,
std::indirect_unary_predicate<std::projected<I, Proj>> Pred >
requires std::indirectly_copyable<I, O>
constexpr ranges::remove_copy_if_result<I, O>
remove_copy_if( I first, S last, O d_first, Pred pred, Proj proj = {} );
|
(3) | (since C++20) |
template< ranges::input_range R,
std::weakly_incrementable O, class Proj = std::identity,
std::indirect_unary_predicate
<std::projected<ranges::iterator_t<R>, Proj>> Pred >
requires std::indirectly_copyable<ranges::iterator_t<R>, O>
constexpr ranges::remove_copy_if_result<ranges::borrowed_iterator_t<R>, O>
remove_copy_if( R&& r, O d_first, Pred pred, Proj proj = {} );
|
(4) | (since C++20) |
template< /*execution-policy*/ Ep,
std::random_access_iterator I, std::sized_sentinel_for<I> S,
std::random_access_iterator O, std::sized_sentinel_for<O> OutS,
class Proj = std::identity,
class T = std::projected_value_t<I, Proj>>
requires std::indirectly_copyable<I, O> &&
std::indirect_binary_predicate
<ranges::equal_to, std::projected<I, Proj>, const T*>
ranges::remove_copy_result<I, O>
remove_copy( Ep&& policy, I first, S last, O d_first, OutS d_last,
const T& value, Proj proj = {} );
|
(5) | (since C++26) |
template< /*execution-policy*/ Ep,
/*sized-random-access-range*/ R,
/*sized-random-access-range*/ OutR,
class Proj = std::identity,
class T = std::projected_value_t<ranges::iterator_t<R>, Proj>>
requires std::indirectly_copyable<ranges::iterator_t<R>,
ranges::iterator_t<OutR>> &&
std::indirect_binary_predicate
<ranges::equal_to,
std::projected<ranges::iterator_t<R>, Proj>, const T*>
ranges::remove_copy_result<ranges::borrowed_iterator_t<R>,
ranges::borrowed_iterator_t<OutR>>
remove_copy( Ep&& policy, R&& r, OutR&& d_r,
const T& value, Proj proj = {} );
|
(6) | (since C++26) |
template< /*execution-policy*/ Ep,
std::random_access_iterator I, std::sized_sentinel_for<I> S,
std::random_access_iterator O, std::sized_sentinel_for<O> OutS,
class Proj = std::identity,
std::indirect_unary_predicate<std::projected<I, Proj>> Pred >
requires std::indirectly_copyable<I, O>
ranges::remove_copy_if_result<I, O>
remove_copy_if( Ep&& policy, I first, S last, O d_first, OutS d_last,
Pred pred, Proj proj = {} );
|
(7) | (since C++26) |
template< /*execution-policy*/ Ep,
/*sized-random-access-range*/ R,
/*sized-random-access-range*/ OutR,
class Proj = std::identity,
std::indirect_unary_predicate
<std::projected<ranges::iterator_t<R>, Proj>> Pred >
requires std::indirectly_copyable<ranges::iterator_t<R>,
ranges::iterator_t<OutR>>
ranges::remove_copy_if_result<ranges::borrowed_iterator_t<R>,
ranges::borrowed_iterator_t<OutR>>
remove_copy_if( Ep&& policy, R&& r, OutR&& d_r,
Pred pred, Proj proj = {} );
|
(8) | (since C++26) |
| Helper types |
||
template< class I, class O >
using remove_copy_result = ranges::in_out_result<I, O>;
|
(9) | (since C++20) |
template< class I, class O >
using remove_copy_if_result = ranges::in_out_result<I, O>;
|
(10) | (since C++20) |
For the definition of /*execution-policy*/, see this page; for the definition of /*sized-random-access-range*/, see this page.
Copies elements from the source range [first, last) or r to the destination range, ignoring the elements (projected by proj) which satisfy specific criteria.
1,2)
remove_copy ignores all elements that are equal to value. The destination range begins at d_first.3,4)
remove_copy_if ignores all elements for which predicate pred returns true. The destination range begins at d_first.5-8) Same as (1-4), but executed according to
policy. If the destination range is exhausted before reaching the end of the source range, the remaining elements in the source range will not be copied.5,7) The destination range is
[d_first, d_last).6,8) The destination range is
d_r.If the source and destination ranges overlap, the behavior is undefined.
The function-like entities described on this page are algorithm function objects (informally known as 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.
Parameters
| first, last | - | the iterator-sentinel pair defining the source range |
| r | - | the source range |
| d_first | - | the beginning of the destination range |
| d_last | - | the sentinel of the destination range |
| d_r | - | the destination range |
| pred | - | the predicate to be applied to the (projected) elements |
| proj | - | the projection to be applied to the elements in the source range |
| policy | - | the execution policy to use |
Return value
A ranges::remove_copy_result or ranges::remove_copy_if_result object where:
- The data member
inholds the past-the-end iterator of the source range.
5,6) If the destination range is exhausted before reaching the end of the source range and some of the remaining elements (projected by
proj) are equal to value, in holds an iterator to the first such element instead.7,8) If the destination range is exhausted before reaching the end of the source range and the predicate
pred returns true for some of the remaining elements (projected by proj), in holds an iterator to the first such element instead.- The data member
outholds an iterator past the last copy-assigned element in the destination range, or an iterator to the beginning of the destination range if no element is copied.
Complexity
Given \(\scriptsize N\)N as ranges::distance(first, last) or ranges::distance(r):
1,2) Exactly \(\scriptsize N\)N comparisons using
operator==, and exactly \(\scriptsize N\)N applications of proj.3,4) Exactly \(\scriptsize N\)N applications of
pred and proj.5,6) \(\scriptsize \mathcal{O}(N)\)(N) comparisons using
operator==, and \(\scriptsize \mathcal{O}(N)\)(N) applications of proj.7,8) \(\scriptsize \mathcal{O}(N)\)(N) applications of
pred and proj.Exceptions
5-8) During the execution process:
- If the temporary memory resources required for parallelization are not available, std::bad_alloc is thrown.
- If an uncaught exception is thrown while accessing objects via an algorithm argument, the behavior is determined by the execution policy (for standard policies, std::terminate is invoked).
Notes
The algorithm is stable, i.e. preserves the relative order of the copied elements.
| Feature-test macro | Value | Std | Feature |
|---|---|---|---|
__cpp_lib_algorithm_default_value_type |
202403 |
(C++26) | List-initialization for algorithms (1,2) |
Possible implementation
| remove_copy |
|---|
struct remove_copy_fn
{
template<std::input_iterator I, std::sentinel_for<I> S,
std::weakly_incrementable O, class Proj = std::identity,
class T = std::projected_value_t<I, Proj>>
requires std::indirectly_copyable<I, O> &&
std::indirect_binary_predicate<ranges::equal_to,
std::projected<I, Proj>, const T*>
constexpr ranges::remove_copy_result<I, O>
operator()(I first, S last, O result, const T& value, Proj proj = {}) const
{
for (; !(first == last); ++first)
if (value != std::invoke(proj, *first))
{
*result = *first;
++result;
}
return {std::move(first), std::move(result)};
}
template<ranges::input_range R,
std::weakly_incrementable O, class Proj = std::identity,
class T = std::projected_value_t<ranges::iterator_t<R>, Proj>>
requires std::indirectly_copyable<ranges::iterator_t<R>, O> &&
std::indirect_binary_predicate<ranges::equal_to,
std::projected<ranges::iterator_t<R>, Proj>, const T*>
constexpr ranges::remove_copy_result<ranges::borrowed_iterator_t<R>, O>
operator()(R&& r, O result, const T& value, Proj proj = {}) const
{
return (*this)(ranges::begin(r), ranges::end(r),
std::move(result), value, std::move(proj));
}
template<ranges::forward_range R,
std::weakly_incrementable O, class Proj = std::identity,
class T = std::projected_value_t<ranges::iterator_t<R>, Proj>>
requires std::indirectly_copyable<ranges::iterator_t<R>, O> &&
std::indirect_binary_predicate<ranges::equal_to,
std::projected<ranges::iterator_t<R>, Proj>, const T*>
constexpr ranges::remove_copy_result<ranges::borrowed_iterator_t<R>, O>
operator()(R&& r, O result, const T& value, Proj proj = {}) const
{
return (*this)(ranges::begin(r),
ranges::next(ranges::begin(r), ranges::end(r)),
std::move(result), value, std::move(proj));
}
};
inline constexpr remove_copy_fn remove_copy{};
|
| remove_copy_if |
struct remove_copy_if_fn
{
template<std::input_iterator I, std::sentinel_for<I> S, std::weakly_incrementable O,
class Proj = std::identity,
std::indirect_unary_predicate<std::projected<I, Proj>> Pred>
requires std::indirectly_copyable<I, O>
constexpr ranges::remove_copy_if_result<I, O>
operator()(I first, S last, O result, Pred pred, Proj proj = {}) const
{
for (; first != last; ++first)
if (false == std::invoke(pred, std::invoke(proj, *first)))
{
*result = *first;
++result;
}
return {std::move(first), std::move(result)};
}
template<ranges::input_range R, std::weakly_incrementable O,
class Proj = std::identity,
std::indirect_unary_predicate<
std::projected<ranges::iterator_t<R>, Proj>> Pred>
requires std::indirectly_copyable<ranges::iterator_t<R>, O>
constexpr ranges::remove_copy_if_result<ranges::borrowed_iterator_t<R>, O>
operator()(R&& r, O result, Pred pred, Proj proj = {}) const
{
return (*this)(ranges::begin(r), ranges::end(r),
std::move(result), std::move(pred), std::move(proj));
}
template<ranges::forward_range R, std::weakly_incrementable O,
class Proj = std::identity,
std::indirect_unary_predicate<
std::projected<ranges::iterator_t<R>, Proj>> Pred>
requires std::indirectly_copyable<ranges::iterator_t<R>, O>
constexpr ranges::remove_copy_if_result<ranges::borrowed_iterator_t<R>, O>
operator()(R&& r, O result, Pred pred, Proj proj = {}) const
{
return (*this)(ranges::begin(r),
ranges::next(ranges::begin(r), ranges::end(r)),
std::move(result), std::move(pred), std::move(proj));
}
};
inline constexpr remove_copy_if_fn remove_copy_if{};
|
Example
Run this code
#include <algorithm>
#include <array>
#include <complex>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <string_view>
#include <vector>
void println(const auto rem, const auto& v)
{
std::cout << rem << ' ';
for (const auto& e : v)
std::cout << e << ' ';
std::cout << '\n';
}
int main()
{
// Filter out the hash symbol from the given string.
const std::string_view str{"#Small #Buffer #Optimization"};
std::cout << "before: " << std::quoted(str) << '\n';
std::cout << "after: \"";
std::ranges::remove_copy(str.begin(), str.end(),
std::ostream_iterator<char>(std::cout), '#');
std::cout << "\"\n";
// Copy only the complex numbers with positive imaginary part.
using Ci = std::complex<int>;
constexpr std::array<Ci, 5> source
{
Ci{1, 0}, Ci{0, 1}, Ci{2, -1}, Ci{3, 2}, Ci{4, -3}
};
std::vector<std::complex<int>> target;
std::ranges::remove_copy_if
(
source,
std::back_inserter(target),
[](int imag) { return imag <= 0; },
[](Ci z) { return z.imag(); }
);
println("source:", source);
println("target:", target);
std::vector<std::complex<float>> nums{{2, 2}, {1, 3}, {4, 8}, {1, 3}};
std::vector<std::complex<double>> outs;
#ifdef __cpp_lib_algorithm_default_value_type
std::remove_copy(nums.cbegin(), nums.cend(), std::back_inserter(outs),
{1, 3}); // T gets deduced to std::complex<float>
#else
std::remove_copy(nums.cbegin(), nums.cend(), std::back_inserter(outs),
std::complex<float>{1, 3});
#endif
println("nums: ", nums);
println("outs: ", outs);
}
Output:
before: "#Small #Buffer #Optimization"
after: "Small Buffer Optimization"
source: (1,0) (0,1) (2,-1) (3,2) (4,-3)
target: (0,1) (3,2)
nums: (2,2) (1,3) (4,8) (1,3)
outs: (2,2) (4,8)
See also
| copies a range of elements omitting those that satisfy specific criteria (function template) | |
(C++20)(C++20) |
removes elements satisfying specific criteria (algorithm function object) |
(C++20)(C++20) |
copies a range of elements to a new location (algorithm function object) |
(C++20) |
copies a number of elements to a new location (algorithm function object) |
(C++20) |
copies a range of elements in backwards order (algorithm function object) |
(C++20)(C++20) |
copies a range, replacing elements satisfying specific criteria with another value (algorithm function object) |
(C++20) |
creates a copy of a range that is reversed (algorithm function object) |
(C++20) |
copies and rotate a range of elements (algorithm function object) |
(C++20) |
creates a copy of some range of elements that contains no consecutive duplicates (algorithm function object) |