# std::ranges::adjacent_find

< cpp‎ | algorithm‎ | ranges

定义于头文件 `<algorithm>` |  |
调用签名 |  |
template< std::forward_iterator I, std::sentinel_for<I> S, class Proj = std::identity, std::indirect_binary_predicate< std::projected<I, Proj>, std::projected<I, Proj>> Pred = ranges::equal_to > constexpr I adjacent_find( I first, S last, Pred pred = {}, Proj proj = {} ); | (1) | (C++20 起)
template< ranges::forward_range R, class Proj = std::identity, std::indirect_binary_predicate< std::projected<ranges::iterator_t<R>, Proj>, std::projected<ranges::iterator_t<R>, Proj>> Pred = ranges::equal_to > constexpr ranges::borrowed_iterator_t<R> adjacent_find( R&& r, Pred pred = {}, Proj proj = {} ); | (2) | (C++20 起)

搜索范围 `[first, last)` 中二个连续的相等元素。

1) 用 `pred` （在以投影 `proj` 投影后）比较元素。
2) 同 (1) ，但以 `r` 为源范围，如同以 ranges::begin(r) 为 `first` 并以 ranges::end(r) 为 `last` 。

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

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

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

### 参数

first, last | - | 要检验的范围
r | - | 要检验的范围
pred | - | 应用到投影后元素的谓词
proj | - | 应用到元素的投影

### 返回值

指向首对等同元素的前一者的迭代器，即首个使得 bool(std::invoke(pred, std::invoke(proj1, *it), std::invoke(proj, *(it + 1)))) 为 true 的 `it` 。

若找不到这种元素，则返回等于 `last` 的迭代器。

### 复杂度

准确应用 `min((result-first)+1, (last-first)-1)` 次谓词与投影，其中 `result` 是返回值。

### 可能的实现

    struct adjacent_find_fn {
      template< std::forward_iterator I, std::sentinel_for<I> S, class Proj = std::identity,
                std::indirect_binary_predicate<
                    std::projected<I, Proj>,
                    std::projected<I, Proj>> Pred = ranges::equal_to >
      constexpr I operator()( I first, S last, Pred pred = {}, Proj proj = {} ) const
      {
          if (first == last) {
              return first;
          }
          auto next = ranges::next(first);
          for (; next != last; ++next, ++first) {
              if (std::invoke(pred, std::invoke(proj, *first), std::invoke(proj, *next))) {
                  return first;
              }
          }
          return first;
      }

      template< ranges::forward_range R, class Proj = std::identity,
                std::indirect_binary_predicate<
                    std::projected<ranges::iterator_t<R>, Proj>,
                    std::projected<ranges::iterator_t<R>, Proj>> Pred = ranges::equal_to >
      constexpr ranges::borrowed_iterator_t<R>
        operator()( R&& r, Pred pred = {}, Proj proj = {} ) const
      {
        return (*this)(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj));
      }
    };

    inline constexpr adjacent_find_fn adjacent_find;

### 示例

    #include <algorithm>
    #include <iostream>
    #include <vector>
    #include <functional>

    int main()
    {
        std::vector<int> v1{0, 1, 2, 3, 40, 40, 41, 41, 5};
        //                              ^^          ^^
        namespace ranges = std::ranges;

        auto i1 = ranges::adjacent_find(v1.begin(), v1.end());
        if (i1 == v1.end()) {
            std::cout << "No matching adjacent elements\n";
        } else {
            std::cout << "The first adjacent pair of equal elements is at ["
                      << ranges::distance(v1.begin(), i1) << "] == " << *i1 << '\n';
        }

        auto i2 = ranges::adjacent_find(v1, ranges::greater());
        if (i2 == v1.end()) {
            std::cout << "The entire vector is sorted in ascending order\n";
        } else {
            std::cout << "The last element in the non-decreasing subsequence is at ["
                      << ranges::distance(v1.begin(), i2) << "] == " << *i2 << '\n';
        }
    }

输出：

    The first adjacent pair of equal elements is at [4] == 40
    The last element in the non-decreasing subsequence is at [7] == 41

### 参阅

ranges::unique (C++20) | 移除范围中的连续重复元素 (niebloid)
adjacent_find | 查找首对相邻的相同（或满足给定谓词的）元素 (函数模板)