Namespaces
Variants
Views
Actions

Difference between revisions of "cpp/algorithm/ranges/remove copy"

From cppreference.com
< cpp‎ | algorithm‎ | ranges
m (Possible implementation: ~title; fmt)
m (FTM.)
 
(5 intermediate revisions by 3 users not shown)
Line 4: Line 4:
 
{{dcl header|algorithm}}
 
{{dcl header|algorithm}}
 
{{dcl h|Call signature}}
 
{{dcl h|Call signature}}
{{dcl|num=1|since=c++20|1=
+
{{dcl rev begin|num=1}}
 +
{{dcla|anchor=1|since=c++20|until=c++26|1=
 
template< std::input_iterator I, std::sentinel_for<I> S,
 
template< std::input_iterator I, std::sentinel_for<I> S,
 
           std::weakly_incrementable O, class T, class Proj = std::identity >
 
           std::weakly_incrementable O, class T, class Proj = std::identity >
 
requires std::indirectly_copyable<I, O> &&
 
requires std::indirectly_copyable<I, O> &&
         std::indirect_binary_predicate<ranges::equal_to,
+
         std::indirect_binary_predicate
            std::projected<I, Proj>, const T*>
+
            <ranges::equal_to, std::projected<I, Proj>, const T*>
 
constexpr remove_copy_result<I, O>
 
constexpr remove_copy_result<I, O>
 
     remove_copy( I first, S last, O result, const T& value, Proj proj = {} );
 
     remove_copy( I first, S last, O result, const T& value, Proj proj = {} );
 
}}
 
}}
{{dcl|num=2|since=c++20|1=
+
{{dcl|since=c++26|1=
template< ranges::input_range R, std::weakly_incrementable O, class T,
+
template< std::input_iterator I, std::sentinel_for<I> S,
          class Proj = std::identity >
+
          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 remove_copy_result<I, O>
 +
    remove_copy( I first, S last, O result, const T& value, Proj proj = {} );
 +
}}
 +
{{dcl rev end}}
 +
{{dcl rev begin|num=2}}
 +
{{dcl|since=c++20|until=c++26|1=
 +
template< ranges::input_range R,  
 +
          std::weakly_incrementable O, class T, class Proj = std::identity >
 
requires std::indirectly_copyable<ranges::iterator_t<R>, O> &&
 
requires std::indirectly_copyable<ranges::iterator_t<R>, O> &&
         std::indirect_binary_predicate<ranges::equal_to,
+
         std::indirect_binary_predicate
             std::projected<ranges::iterator_t<R>, Proj>, const T*>
+
            <ranges::equal_to,
 +
              std::projected<ranges::iterator_t<R>, Proj>, const T*>
 +
constexpr remove_copy_result<ranges::borrowed_iterator_t<R>, O>
 +
    remove_copy( R&& r, O result, const T& value, Proj proj = {} );
 +
}}
 +
{{dcl|since=c++26|1=
 +
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 remove_copy_result<ranges::borrowed_iterator_t<R>, O>
 
constexpr remove_copy_result<ranges::borrowed_iterator_t<R>, O>
 
     remove_copy( R&& r, O result, const T& value, Proj proj = {} );
 
     remove_copy( R&& r, O result, const T& value, Proj proj = {} );
 
}}
 
}}
{{dcl|num=3|since=c++20|1=
+
{{dcl rev end}}
 +
{{dcla|num=3|since=c++20|1=
 
template< std::input_iterator I, std::sentinel_for<I> S,
 
template< std::input_iterator I, std::sentinel_for<I> S,
 
           std::weakly_incrementable O, class Proj = std::identity,
 
           std::weakly_incrementable O, class Proj = std::identity,
Line 41: Line 67:
 
{{dcl h|Helper types}}
 
{{dcl h|Helper types}}
 
{{dcl|num=5|since=c++20|1=
 
{{dcl|num=5|since=c++20|1=
template<class I, class O>
+
template< class I, class O >
 
using remove_copy_result = ranges::in_out_result<I, O>;
 
using remove_copy_result = ranges::in_out_result<I, O>;
 
}}
 
}}
 
{{dcl|num=6|since=c++20|1=
 
{{dcl|num=6|since=c++20|1=
template<class I, class O>
+
template< class I, class O >
 
using remove_copy_if_result = ranges::in_out_result<I, O>;
 
using remove_copy_if_result = ranges::in_out_result<I, O>;
 
}}
 
}}
 
{{dcl end}}
 
{{dcl end}}
  
Copies elements from the source range {{tt|[first, last)}}, to the destination range beginning at {{tt|result}}, omitting the elements which (after being projected by {{tt|proj}}) satisfy specific criteria. The behavior is undefined if the source and destination ranges overlap.
+
Copies elements from the source range {{range|first|last}}, to the destination range beginning at {{c|result}}, omitting the elements which (after being projected by {{c|proj}}) satisfy specific criteria. The behavior is undefined if the source and destination ranges overlap.
  
@1@ Ignores all elements that are equal to {{tt|value}}.
+
@1@ Ignores all elements that are equal to {{c|value}}.
  
@3@ Ignores all elements for which predicate {{tt|pred}} returns {{c|true}}.
+
@3@ Ignores all elements for which predicate {{c|pred}} returns {{c|true}}.
  
@2,4@ Same as {{v|1,3}}, but uses {{tt|r}} as the source range, as if using {{c|ranges::begin(r)}} as {{tt|first}}, and {{c|ranges::end(r)}} as {{tt|last}}.
+
@2,4@ Same as {{v|1,3}}, but uses {{c|r}} as the source range, as if using {{c|ranges::begin(r)}} as {{c|first}}, and {{c|ranges::end(r)}} as {{c|last}}.
  
 
{{cpp/ranges/niebloid}}
 
{{cpp/ranges/niebloid}}
Line 65: Line 91:
 
{{par|r|the source range of elements}}
 
{{par|r|the source range of elements}}
 
{{par|result|the beginning of the destination range}}
 
{{par|result|the beginning of the destination range}}
{{par|value|the value of the elements ''not'' to copy}}
+
{{par|value|the value of the elements '''not''' to copy}}
 
{{par|comp|the binary predicate to compare the projected elements}}
 
{{par|comp|the binary predicate to compare the projected elements}}
 
{{par|proj|the projection to apply to the elements}}
 
{{par|proj|the projection to apply to the elements}}
Line 71: Line 97:
  
 
===Return value===
 
===Return value===
{{c|{last, result + N} }}, where {{tt|N}} is the number of elements copied.
+
{{c|{last, result + N} }}, where {{c|N}} is the number of elements copied.
  
 
===Complexity===
 
===Complexity===
Exactly {{c|ranges::distance(first, last)}} applications of the corresponding predicate {{tt|comp}} and any projection {{tt|proj}}.
+
Exactly {{c|ranges::distance(first, last)}} applications of the corresponding predicate {{c|comp}} and any projection {{c|proj}}.
  
 
===Notes===
 
===Notes===
The algorithm is ''stable'', i.e. preserves the relative order of the copied elements.
+
The algorithm is stable, i.e. preserves the relative order of the copied elements.
 +
 
 +
{{feature test macro|__cpp_lib_algorithm_default_value_type|value=202403|std=C++26|[[cpp/language/list initialization|List-initialization]] for algorithms {{vl|1,2}}}}
  
 
===Possible implementation===
 
===Possible implementation===
{{eq impl
+
{{eq impl|title1=remove_copy|ver1=1|1=
|title1=First and second version|1=
+
 
struct remove_copy_fn
 
struct remove_copy_fn
 
{
 
{
     template <std::input_iterator I, std::sentinel_for<I> S, std::weakly_incrementable O,
+
     template<std::input_iterator I, std::sentinel_for<I> S,
             class T, class Proj = std::identity>
+
            std::weakly_incrementable O, class Proj = std::identity,
 +
             class T = std::projected_value_t<I, Proj>>
 
     requires std::indirectly_copyable<I, O> &&
 
     requires std::indirectly_copyable<I, O> &&
 
             std::indirect_binary_predicate<ranges::equal_to,
 
             std::indirect_binary_predicate<ranges::equal_to,
 
                                             std::projected<I, Proj>, const T*>
 
                                             std::projected<I, Proj>, const T*>
 
     constexpr ranges::remove_copy_result<I, O>
 
     constexpr ranges::remove_copy_result<I, O>
    operator()( I first, S last, O result, const T& value, Proj proj = {} ) const
+
        operator()(I first, S last, O result, const T& value, Proj proj = {}) const
 
     {
 
     {
 
         for (; !(first == last); ++first)
 
         for (; !(first == last); ++first)
Line 98: Line 126:
 
                 ++result;
 
                 ++result;
 
             }
 
             }
 
 
         return {std::move(first), std::move(result)};
 
         return {std::move(first), std::move(result)};
 
     }
 
     }
 
+
   
     template <ranges::input_range R, std::weakly_incrementable O, class T,
+
     template<ranges::input_range R,  
             class Proj = std::identity>
+
            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> &&
 
     requires std::indirectly_copyable<ranges::iterator_t<R>, O> &&
 
             std::indirect_binary_predicate<ranges::equal_to,
 
             std::indirect_binary_predicate<ranges::equal_to,
 
             std::projected<ranges::iterator_t<R>, Proj>, const T*>
 
             std::projected<ranges::iterator_t<R>, Proj>, const T*>
 
     constexpr ranges::remove_copy_result<ranges::borrowed_iterator_t<R>, O>
 
     constexpr ranges::remove_copy_result<ranges::borrowed_iterator_t<R>, O>
    operator()( R&& r, O result, const T& value, Proj proj = {} ) const
+
        operator()(R&& r, O result, const T& value, Proj proj = {}) const
 
     {
 
     {
 
         return (*this)(ranges::begin(r), ranges::end(r), std::move(result), value,
 
         return (*this)(ranges::begin(r), ranges::end(r), std::move(result), value,
Line 115: Line 143:
 
};
 
};
  
inline constexpr remove_copy_fn remove_copy{};
+
inline constexpr remove_copy_fn remove_copy {};
|title2=Third and fourth version|2=
+
|title2=remove_copy_if|ver2=3|2=
 
struct remove_copy_if_fn
 
struct remove_copy_if_fn
 
{
 
{
     template <std::input_iterator I, std::sentinel_for<I> S, std::weakly_incrementable O,
+
     template<std::input_iterator I, std::sentinel_for<I> S, std::weakly_incrementable O,
 
             class Proj = std::identity,
 
             class Proj = std::identity,
 
             std::indirect_unary_predicate<std::projected<I, Proj>> Pred>
 
             std::indirect_unary_predicate<std::projected<I, Proj>> Pred>
 
     requires std::indirectly_copyable<I, O>
 
     requires std::indirectly_copyable<I, O>
 
     constexpr ranges::remove_copy_if_result<I, O>
 
     constexpr ranges::remove_copy_if_result<I, O>
    operator()( I first, S last, O result, Pred pred, Proj proj = {} ) const
+
        operator()(I first, S last, O result, Pred pred, Proj proj = {}) const
 
     {
 
     {
 
         for (; first != last; ++first)
 
         for (; first != last; ++first)
Line 132: Line 160:
 
                 ++result;
 
                 ++result;
 
             }
 
             }
 
 
         return {std::move(first), std::move(result)};
 
         return {std::move(first), std::move(result)};
 
     }
 
     }
 
+
   
     template <ranges::input_range R, std::weakly_incrementable O,
+
     template<ranges::input_range R, std::weakly_incrementable O,
              class Proj = std::identity,
+
            class Proj = std::identity,
 
             std::indirect_unary_predicate<
 
             std::indirect_unary_predicate<
                std::projected<ranges::iterator_t<R>, Proj>> Pred>
+
                std::projected<ranges::iterator_t<R>, Proj>> Pred>
 
     requires std::indirectly_copyable<ranges::iterator_t<R>, O>
 
     requires std::indirectly_copyable<ranges::iterator_t<R>, O>
 
     constexpr ranges::remove_copy_if_result<ranges::borrowed_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
+
        operator()(R&& r, O result, Pred pred, Proj proj = {}) const
 
     {
 
     {
 
         return (*this)(ranges::begin(r), ranges::end(r), std::move(result),
 
         return (*this)(ranges::begin(r), ranges::end(r), std::move(result),
Line 149: Line 176:
 
};
 
};
  
inline constexpr remove_copy_if_fn remove_copy_if{};
+
inline constexpr remove_copy_if_fn remove_copy_if {};
 
}}
 
}}
  
 
===Example===
 
===Example===
{{example|code=
+
{{example
 +
|code=
 
#include <algorithm>
 
#include <algorithm>
 
#include <array>
 
#include <array>
Line 163: Line 191:
 
#include <vector>
 
#include <vector>
  
void print(const auto rem, const auto& v)
+
void println(const auto rem, const auto& v)
 
{
 
{
 
     std::cout << rem << ' ';
 
     std::cout << rem << ' ';
     for (const auto& e : v) { std::cout << e << ' '; };
+
     for (const auto& e : v)
 +
        std::cout << e << ' ';
 
     std::cout << '\n';
 
     std::cout << '\n';
 
}
 
}
Line 173: Line 202:
 
{
 
{
 
     // Filter out the hash symbol from the given string.
 
     // Filter out the hash symbol from the given string.
     const std::string_view str{ "#Small #Buffer #Optimization" };
+
     const std::string_view str{"#Small #Buffer #Optimization"};
     std::cout << "before: " << std::quoted(str) << "\n";
+
     std::cout << "before: " << std::quoted(str) << '\n';
 
+
   
 
     std::cout << "after:  \"";
 
     std::cout << "after:  \"";
 
     std::ranges::remove_copy(str.begin(), str.end(),
 
     std::ranges::remove_copy(str.begin(), str.end(),
 
                             std::ostream_iterator<char>(std::cout), '#');
 
                             std::ostream_iterator<char>(std::cout), '#');
 
     std::cout << "\"\n";
 
     std::cout << "\"\n";
 
+
   
 
+
 
     // Copy only the complex numbers with positive imaginary part.
 
     // Copy only the complex numbers with positive imaginary part.
 
     using Ci = std::complex<int>;
 
     using Ci = std::complex<int>;
     constexpr std::array<Ci, 5> source{
+
     constexpr std::array<Ci, 5> source
         Ci{1,0}, Ci{0,1}, Ci{2,-1}, Ci{3,2}, Ci{4,-3}
+
    {
 +
         Ci{1, 0}, Ci{0, 1}, Ci{2, -1}, Ci{3, 2}, Ci{4, -3}
 
     };
 
     };
 
     std::vector<std::complex<int>> target;
 
     std::vector<std::complex<int>> target;
 
+
   
     std::ranges::remove_copy_if(
+
     std::ranges::remove_copy_if
 +
    (
 
         source,
 
         source,
 
         std::back_inserter(target),
 
         std::back_inserter(target),
         [](int imag){ return imag <= 0; },
+
         [](int imag) { return imag <= 0; },
         [](Ci z){ return z.imag(); }
+
         [](Ci z) { return z.imag(); }
 
     );
 
     );
 +
   
 +
    println("source:", source);
 +
    println("target:", target);
  
     print("source:", source);
+
     std::vector<std::complex<float>> nums{<!---->{2, 2}, {1, 3}, {4, 8}, {1, 3}<!---->};
     print("target:", target);
+
    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=
 
|output=
Line 204: Line 246:
 
source: (1,0) (0,1) (2,-1) (3,2) (4,-3)
 
source: (1,0) (0,1) (2,-1) (3,2) (4,-3)
 
target: (0,1) (3,2)
 
target: (0,1) (3,2)
 +
nums:  (2,2) (1,3) (4,8) (1,3)
 +
outs:  (2,2) (4,8)
 
}}
 
}}
  

Latest revision as of 21:30, 20 May 2024

 
 
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
(C++11)                (C++11)(C++11)

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
(C++11)
(C++17)
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
Numeric operations
(C++23)            
Operations on uninitialized storage
Return types
 
Defined in header <algorithm>
Call signature
(1)
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 remove_copy_result<I, O>

    remove_copy( I first, S last, O result, const T& value, Proj proj = {} );
(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 remove_copy_result<I, O>

    remove_copy( I first, S last, O result, const T& value, Proj proj = {} );
(since C++26)
(2)
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 remove_copy_result<ranges::borrowed_iterator_t<R>, O>

    remove_copy( R&& r, O result, const T& value, Proj proj = {} );
(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 remove_copy_result<ranges::borrowed_iterator_t<R>, O>

    remove_copy( R&& r, O result, 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 remove_copy_if_result<I, O>

    remove_copy_if( I first, S last, O result, 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 remove_copy_if_result<ranges::borrowed_iterator_t<R>, O>

    remove_copy_if( R&& r, O result, Pred pred, Proj proj = {} );
(4) (since C++20)
Helper types
template< class I, class O >
using remove_copy_result = ranges::in_out_result<I, O>;
(5) (since C++20)
template< class I, class O >
using remove_copy_if_result = ranges::in_out_result<I, O>;
(6) (since C++20)

Copies elements from the source range [firstlast), to the destination range beginning at result, omitting the elements which (after being projected by proj) satisfy specific criteria. The behavior is undefined if the source and destination ranges overlap.

1) Ignores all elements that are equal to value.
3) Ignores all elements for which predicate pred returns true.
2,4) Same as (1,3), but uses r as the source 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:

In practice, they may be implemented as function objects, or with special compiler extensions.

Contents

[edit] Parameters

first, last - the source range of elements
r - the source range of elements
result - the beginning of the destination range
value - the value of the elements not to copy
comp - the binary predicate to compare the projected elements
proj - the projection to apply to the elements

[edit] Return value

{last, result + N}, where N is the number of elements copied.

[edit] Complexity

Exactly ranges::distance(first, last) applications of the corresponding predicate comp and any projection proj.

[edit] 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)

[edit] 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));
    }
};
 
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));
    }
};
 
inline constexpr remove_copy_if_fn remove_copy_if {};

[edit] Example

#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)

[edit] See also

removes elements satisfying specific criteria
(niebloid)[edit]
copies a range of elements to a new location
(niebloid)[edit]
copies a number of elements to a new location
(niebloid)[edit]
copies a range of elements in backwards order
(niebloid)[edit]
copies a range, replacing elements satisfying specific criteria with another value
(niebloid)[edit]
creates a copy of a range that is reversed
(niebloid)[edit]
copies and rotate a range of elements
(niebloid)[edit]
creates a copy of some range of elements that contains no consecutive duplicates
(niebloid)[edit]
copies a range of elements omitting those that satisfy specific criteria
(function template) [edit]