# std::ranges::reverse

< cpp‎ | algorithm‎ | ranges

定义于头文件 `<algorithm>` |  |
调用签名 |  |
template< std::bidirectional_iterator I, std::sentinel_for<I> S > requires std::permutable<I> constexpr I reverse( I first, S last ); | (1) | (C++20 起)
template< ranges::bidirectional_range R > requires std::permutable<ranges::iterator_t<R>> constexpr ranges::borrowed_iterator_t<R> reverse( R&& r ); | (2) | (C++20 起)

1) 逆转范围 `[first, last)` 中的元素顺序。
表现如同对每个 0 ≤ i < (last-first)/2 中的整数 `i` 应用 ranges::iter_swap 到每对迭代器 `first+i, last-i-1` 。
2) 同 (1) ，但以 `r` 为源范围，如同以 ranges::begin(r) 为 `first` 并以 ranges::end(r) 为 `last` 。

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

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

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

### 参数

first, last | - | 要逆转的元素范围
r | - | 要逆转的元素范围

### 返回值

等于 `last` 的迭代器。

### 复杂度

准确交换 `(last - first)/2` 次。

### 注解

实现（例如 MSVC STL ）可能在迭代器类型实现 `contiguous_iterator` ，并且交换其值类型不调用非平凡的特殊成员函数或 ADL 所找到的 `swap` 时启用向量化。

### 可能的实现

参阅 libstdc++ 与 MSVC STL 中的实现。

    struct reverse_fn {
      template<std::bidirectional_iterator I, std::sentinel_for<I> S>
        requires std::permutable<I>
          constexpr I operator()( I first, S last ) const {
              auto last2{ ranges::next(first, last) };
              for (auto tail{ last2 }; !(first == tail or first == --tail); ++first) {
                  ranges::iter_swap(first, tail);
              }
              return last2;
          }

      template<ranges::bidirectional_range R>
        requires std::permutable<ranges::iterator_t<R>>
          constexpr ranges::borrowed_iterator_t<R>
            operator()( R&& r ) const {
                return (*this)(ranges::begin(r), ranges::end(r));
            }
    };

    inline constexpr reverse_fn reverse{};

### 示例

    #include <algorithm>
    #include <array>
    #include <iostream>
    #include <string>

    int main()
    {
        std::string s{"ABCDEF"};
        std::cout << s << " → ";
        std::ranges::reverse(s.begin(), s.end());
        std::cout << s << " → ";
        std::ranges::reverse(s);
        std::cout << s << " │ ";

        std::array a{1, 2, 3, 4, 5};
        for(auto e : a) { std::cout << e << ' '; }
        std::cout << "→ ";
        std::ranges::reverse(a);
        for(auto e : a) { std::cout << e << ' '; }
        std::cout << '\n';
    }

输出：

    ABCDEF → FEDCBA → ABCDEF │ 1 2 3 4 5 → 5 4 3 2 1

### 参阅

ranges::revserse_copy (C++20) | 创建一个范围的逆向副本 (niebloid)
ranges::reverse_view views::reverse (C++20) | 以逆序迭代另一双向视图上的元素的 `view` (类模板) (范围适配器对象)
reverse | 逆转范围中的元素顺序 (函数模板)