# std::experimental::ranges::copy, std::experimental::ranges::copy_if

< cpp‎ | experimental‎ | ranges

定义于头文件 `<experimental/ranges/algorithm>` |  |
template < ranges::InputIterator I, ranges::Sentinel<I> S, ranges::WeaklyIncrementable O > requires ranges::IndirectlyCopyable<I, O> ranges::tagged_pair<ranges::tag::in(I), ranges::tag::out(O)> copy(I first, S last, O result); | (1) | (范围 TS)
template < ranges::InputRange Rng, ranges::WeaklyIncrementable O > requires ranges::IndirectlyCopyable<ranges::iterator_t<Rng>, O> ranges::tagged_pair< ranges::tag::in(ranges::safe_iterator_t<Rng>), ranges::tag::out(O)> copy(Rng&& rng, O result); | (2) | (范围 TS)
template < ranges::InputIterator I, ranges::Sentinel<I> S, ranges::WeaklyIncrementable O, class Proj = ranges::identity, ranges::IndirectUnaryPredicate<ranges::projected<I, Proj>> Pred > requires ranges::IndirectlyCopyable<I, O> ranges::tagged_pair<ranges::tag::in(I), ranges::tag::out(O)> copy_if(I first, S last, O result, Pred pred, Proj proj = Proj{}); | (3) | (范围 TS)
template < ranges::InputRange Rng, ranges::WeaklyIncrementable O, class Proj = ranges::identity, ranges::IndirectUnaryPredicate< ranges::projected<ranges::iterator_t<Rng>, Proj>> Pred > requires ranges::IndirectlyCopyable<iterator_t<Rng>, O> ranges::tagged_pair< ranges::tag::in(ranges::safe_iterator_t<Rng>), ranges::tag::out(O)> copy_if(Rng&& rng, O result, Pred pred, Proj proj = Proj{}); | (4) | (范围 TS)

复制源范围（ `[first,last)` 或 `rng` ）中的元素到始于 `result` 的目标范围中，从源范围的首元素开始，后续到末元素。

1) 复制范围 `[first, last)` 中的所有元素。对每个非负整数 `n < (last - first)` 进行 *(result + n) = *(first + n) 。若 `result` 在范围 `[first, last)` 内则行为未定义。此情况下可用 ranges::copy_backward 代替。
2) 同 (1) ，但以 `rng` 为源范围，如同用 ranges::copy(ranges::begin(rng), ranges::end(rng), result); ，除了不可复制 `result` 。
3) 仅复制应用谓词 `pred` 到投影 `proj` 所投影的元素值时，对其返回 true 的元素。保持复制后的元素顺序。若源与目标范围重叠则行为未定义。
4) 同 (3) ，但以 `rng` 为源范围，如同用 ranges::copy_if(ranges::begin(rng), ranges::end(rng), result, pred, proj); ，除了不可复制 `result` 、 `pred` 和 `proj` 。

### 参数

first, last | - | 要复制的元素范围
rng | - | 要复制的元素范围
result | - | 目标范围的起始
pred | - | 要应用到投影后元素的谓词
proj | - | 要应用到元素的投影

### 返回值

含有以下二个成员的 `tagged_pair` 对象：

- 第一成员有标签 `tag::in` ，为源范围的尾后迭代器（即比较等于哨位 `last` 的 `I` 类型迭代器）。
- 第二成员有标签 `tag::out` ，为结果范围的尾后迭代器。

### 复杂度

1) 准确赋值 ranges::distance(first, last) 次。
2) 准确赋值 ranges::distance(rng) 次。
3) 准确应用 ranges::distance(first, last) 次对应的投影和谓词。
3) 准确应用 ranges::distance(rng) 次对应的投影和谓词。

### 可能的实现

版本一
    template <ranges::InputIterator I, ranges::Sentinel<I> S, ranges::WeaklyIncrementable O>
      requires ranges::IndirectlyCopyable<I, O>()
    ranges::tagged_pair<ranges::tag::in(I), ranges::tag::out(O)>
      copy(I first, S last, O result)
    {
        for (; first != last; ++first, (void)++result)
            *result = *first;
        return {first, result};
    }
版本二
    template <ranges::InputRange Rng, ranges::WeaklyIncrementable O>
      requires ranges::IndirectlyCopyable<ranges::iterator_t<Rng>, O>()
    ranges::tagged_pair<ranges::tag::in(ranges::safe_iterator_t<Rng>), ranges::tag::out(O)>
      copy(Rng&& rng, O result)
    {
       return ranges::copy(ranges::begin(rng), ranges::end(rng), result);
    }
版本三
    template <ranges::InputIterator I, ranges::Sentinel<I> S, ranges::WeaklyIncrementable O,
              class Proj = ranges::identity,
              ranges::IndirectUnaryPredicate<ranges::projected<I, Proj>> Pred>
      requires ranges::IndirectlyCopyable<I, O>()
    ranges::tagged_pair<ranges::tag::in(I), ranges::tag::out(O)>
      copy_if(I first, S last, O result, Pred pred, Proj proj = Proj{})
    {
        for (; first != last; ++first) {
            if (ranges::invoke(pred, ranges::invoke(proj, *first))){
                *result = *first;
                ++result;
            }
        }
        return {first, result};
    }
版本四
    template <ranges::InputRange Rng, ranges::WeaklyIncrementable O,
              class Proj = ranges::identity,
              ranges::IndirectUnaryPredicate<
                  ranges::projected<ranges::iterator_t<Rng>, Proj>> Pred>
      requires ranges::IndirectlyCopyable<ranges::iterator_t<Rng>, O>()
    ranges::tagged_pair<ranges::tag::in(ranges::safe_iterator_t<Rng>), ranges::tag::out(O)>
      copy_if(Rng&& rng, O result, Pred pred, Proj proj = Proj{})
    {
       return ranges::copy_if(ranges::begin(rng), ranges::end(rng), result, pred, proj);
    }

### 示例

下列代码用 copy 复制一个 `vector` 的内容给另一个，并显示结果 `vector` ：

    #include <experimental/ranges/algorithm>
    #include <iostream>
    #include <vector>
    #include <experimental/ranges/iterator>
    #include <numeric>

    int main()
    {
        // 参阅 http://zh.cppreference.com/w/cpp/language/namespace_alias
        namespace ranges = std::experimental::ranges;

        std::vector<int> from_vector(10);
        std::iota(from_vector.begin(), from_vector.end(), 0);

        std::vector<int> to_vector;
        ranges::copy_if(from_vector.begin(), from_vector.end(),
                        ranges::back_inserter(to_vector),
                        [](const auto i) {
                           return i % 3;
                        });
    // 或替用的
    //  std::vector<int> to_vector(from_vector.size());
    //  std::copy(from_vector, to_vector.begin());

        std::cout << "to_vector contains: ";

        ranges::copy(to_vector, ranges::ostream_iterator<int>(std::cout, " "));
        std::cout << '\n';
    }

输出：

    to_vector contains: 1 2 4 5 7 8

### 参阅

copy copy_if (C++11) | 将某一范围的元素复制到一个新的位置 (函数模板)
copy_backward | 按从后往前的顺序复制一个范围内的元素 (函数模板)
reverse_copy | 创建一个范围的逆向副本 (函数模板)
copy_n | 将一定数目的元素复制到一个新的位置 (函数模板)
fill | 将一个特定值赋值给一个元素范围 (函数模板)
remove_copy remove_copy_if | 复制元素范围，忽略满足特定判别标准的元素 (函数模板)