# std::ranges::remove_copy, std::ranges::remove_copy_if, std::ranges::remove_copy_result, std::ranges::remove_copy_if_result

< cpp‎ | algorithm‎ | ranges

定义于头文件 `<algorithm>` |  |
调用签名 |  |
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 = {} ); | (1) | (C++20 起)
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 = {} ); | (2) | (C++20 起)
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) | (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) | (C++20 起)
辅助类型 |  |
template<class I, class O> using remove_copy_result = ranges::in_out_result<I, O>; | (5) | (C++20 起)
template<class I, class O> using remove_copy_if_result = ranges::in_out_result<I, O>; | (6) | (C++20 起)

复制来自源范围 `[first, last)` 的元素到始于 `result` 的目标范围，忽略（在由 `proj` 投影后）满足特定判别标准的元素。若源范围与目标范围重叠则行为未定义。

1) 忽略所有等于 `value` 的元素。
3) 忽略所有谓词 `pred` 对其返回 true 的元素。
2,4) 同 (1,3) ，但以 `r` 为源范围，如同以 ranges::begin(r) 为 `first` 并以 ranges::end(r) 为 `last` 。

此页面上描述的仿函数实体是 niebloid ，即：

- 调用它们中的任何一者时不可指定显式模板实参。
- 它们无一对实参依赖查找可见。
- 在通常无限定查找寻找函数调用运算符左侧的名称找到它们之一时，它禁止实参依赖查找。

实际上，它们能以函数对象，或以某些特殊编译器扩展实现。

### 参数

first, last | - | 源元素范围
r | - | 源元素范围
result | - | 目标范围的起始
value | - | 不复制的元素的值
comp | - | 比较投影后元素的二元谓词
proj | - | 应用到元素的投影

### 返回值

{last, result + N} ，其中 `N` 是复制的元素数。

### 复杂度

准确应用 ranges::distance(first, last) 次对应的谓词 `comp` 与任何投影 `proj` 。

### 注解

算法是稳定的，即保持被复制元素的相对顺序。

### 可能的实现

版本一
    struct remove_copy_fn {
      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>
      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 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>
      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{};
版本二
    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_{};

### 示例

    #include <algorithm>
    #include <array>
    #include <complex>
    #include <iomanip>
    #include <iostream>
    #include <iterator>
    #include <string_view>
    #include <vector>

    void print(const auto rem, const auto& v) {
        std::cout << rem << ' ';
        for (const auto& e : v) { std::cout << e << ' '; };
        std::cout << '\n';
    }

    int main()
    {
        // 从给定的字符串滤出散列记号。
        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";

        // 仅复制有正虚部的复数
        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(); }
        );

        print("source:", source);
        print("target:", target);
    }

输出：

    before: "#Small #Buffer #Optimization"
    after:  "Small Buffer Optimization"
    source: (1,0) (0,1) (2,-1) (3,2) (4,-3)
    target: (0,1) (3,2)

### 参阅

ranges::remove ranges::remove_if (C++20)(C++20) | 移除满足特定判别标准的元素 (niebloid)
ranges::copy ranges::copy_if (C++20)(C++20) | 将某一范围的元素复制到一个新的位置 (niebloid)
ranges::copy_n (C++20) | 将一定数目的元素复制到一个新的位置 (niebloid)
ranges::copy_backward (C++20) | 按从后往前的顺序复制一个范围内的元素 (niebloid)
ranges::replace_copy ranges::replace_copy_if (C++20)(C++20) | 复制一个范围内的元素，并将满足特定判别标准的元素替换为另一个值 (niebloid)
ranges::revserse_copy (C++20) | 创建一个范围的逆向副本 (niebloid)
ranges::rotate_copy (C++20) | 复制并旋转元素范围 (niebloid)
ranges::unique_copy (C++20) | 创建某范围的不含连续重复元素的副本 (niebloid)
remove_copy remove_copy_if | 复制一个范围的元素，忽略满足特定判别标准的元素 (函数模板)