# std::ranges::copy_backward, std::ranges::copy_backward_result

< cpp‎ | algorithm‎ | ranges

定义于头文件 `<algorithm>` |  |
调用签名 |  |
template< std::bidirectional_iterator I1, std::sentinel_for<I1> S1, std::bidirectional_iterator I2 > requires std::indirectly_copyable<I1, I2> constexpr copy_backward_result<I1, I2> copy_backward( I1 first, S1 last, I2 result ); | (1) | (C++20 起)
template< ranges::bidirectional_range R, std::bidirectional_iterator I > requires std::indirectly_copyable<ranges::iterator_t<R>, I> constexpr copy_backward_result<ranges::borrowed_iterator_t<R>, I> copy_backward( R&& r, I result ); | (2) | (C++20 起)
辅助类型 |  |
template< class I1, class I2 > using copy_backward_result = ranges::in_out_result<I1, I2>; | (3) | (C++20 起)

1) 从 `[first, last)` 所定义的复制移动元素到另一范围 `[result - N, result)` ，其中 N = ranges::distance(first, last) 。按逆序复制元素（首先移动末元素），但保持其相对顺序。若 `result` 在 `(first, last]` 内则行为未定义。此情况下可用 std::ranges::move 代替。
2) 同 (1) ，但以 `r` 为源范围，如同以 ranges::begin(r) 为 `first` 并以 ranges::end(r) 为 `last` 。

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

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

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

### 参数

first | - | 要复制的元素范围的起始
last | - | 要复制元素范围的末尾
r | - | 要复制的元素范围
result | - | 目标范围的末尾

### 返回值

{last, result - N} 。

### 复杂度

准确赋值 N 次。

### 注解

复制重叠的范围时， `ranges::copy` 适合向左复制（目标范围的起始在源范围外），而 ranges::copy_backward 适合向右复制（目标范围的末尾在源范围外）。

### 可能的实现

    struct copy_backward_fn {
        template<std::bidirectional_iterator I1, std::sentinel_for<I1> S1,
                 std::bidirectional_iterator I2>
          requires std::indirectly_copyable<I1, I2>
              constexpr ranges::copy_backward_result<I1, I2>
                  operator()( I1 first, S1 last, I2 result ) const {
                      I1 last1{ ranges::next(first, std::move(last)) };
                      for (I1 i{ last1 }; i != first; *--result = *--i);
                      return { std::move(last1), std::move(result) };
                  }

        template<ranges::bidirectional_range R, std::bidirectional_iterator I>
            requires std::indirectly_copyable<ranges::iterator_t<R>, I>
                constexpr ranges::copy_backward_result<ranges::borrowed_iterator_t<R>, I>
                    operator()( R&& r, I result ) const {
                        return (*this)(ranges::begin(r), ranges::end(r), std::move(result));
                    }
    };

    inline constexpr copy_backward_fn copy_backward{};

### 示例

    #include <algorithm>
    #include <iostream>
    #include <ranges>
    #include <string_view>
    #include <vector>

    void print(std::string_view rem, std::ranges::forward_range auto const& r) {
        for (std::cout << rem << ": "; auto const& elem : r)
            std::cout << elem << ' ';
        std::cout << '\n';
    }

    int main()
    {
        const auto src = {1, 2, 3, 4};
        print("src", src);

        std::vector<int> dst (src.size() + 2);
        std::ranges::copy_backward(src, dst.end());
        print("dst", dst);

        std::ranges::fill(dst, 0);
        const auto [in, out] =
            std::ranges::copy_backward(src.begin(), src.end() - 2, dst.end());
        print("dst", dst);

        std::cout
            << "(in - src.begin) == " << std::distance(src.begin(), in) << '\n'
            << "(out - dst.begin) == " << std::distance(dst.begin(), out) << '\n';
    }

输出：

    src: 1 2 3 4
    dst: 0 0 1 2 3 4
    dst: 0 0 0 0 1 2
    (in - src.begin) == 2
    (out - dst.begin) == 4

### 参阅

ranges::copy ranges::copy_if (C++20)(C++20) | 将某一范围的元素复制到一个新的位置 (niebloid)
ranges::copy_n (C++20) | 将一定数目的元素复制到一个新的位置 (niebloid)
ranges::remove_copy ranges::remove_copy_if (C++20)(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)
ranges::move (C++20) | 将某一范围的元素移动到一个新的位置 (niebloid)
ranges::move_backword (C++20) | 按从后往前的顺序移动某一范围的元素到新的位置 (niebloid)
copy_backward | 按从后往前的顺序复制一个范围内的元素 (函数模板)