# std::ranges::mismatch, std::ranges::mismatch_result

< cpp‎ | algorithm‎ | ranges

定义于头文件 `<algorithm>` |  |
调用签名 |  |
template< std::input_iterator I1, std::sentinel_for<I1> S1, std::input_iterator I2, std::sentinel_for<I2> S2, class Pred = ranges::equal_to, class Proj1 = std::identity, class Proj2 = std::identity > requires std::indirectly_comparable<I1, I2, Pred, Proj1, Proj2> constexpr ranges::mismatch_result<I1, I2> mismatch( I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {} ); | (1) | (C++20 起)
template< ranges::input_range R1, ranges::input_range R2, class Pred = ranges::equal_to, class Proj1 = std::identity, class Proj2 = std::identity > requires std::indirectly_comparable< ranges::iterator_t<R1>, ranges::iterator_t<R2>, Pred, Proj1, Proj2> constexpr ranges::mismatch_result<ranges::borrowed_iterator_t<R1>, ranges::borrowed_iterator_t<R2>> mismatch( R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {} ); | (2) | (C++20 起)
辅助类型 |  |
template<class I1, class I2> using mismatch_result = ranges::in_in_result<I1, I2>; | (3) | (C++20 起)

返回首个投影后元素的不匹配对，它们来自两个范围：一个以 `[first1, last1)` 或 `r1` 定义而另一个以 `[first2,last2)` 或 `r2` 定义。

1) 用给定的二元谓词 `p` 比较元素。
2) 同 (1) ，但以 `r` 为源范围，如同以 ranges::begin(r) 为 `first` 并以 ranges::end(r) 为 `last` 。

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

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

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

### 参数

first1, last1 | - | 代表第一待比较元素范围的迭代器-哨位对
r1 | - | 第一待比较元素范围
first2, last2 | - | 代表第二待比较元素范围的迭代器-哨位对
r2 | - | 第二待比较元素范围
pred | - | 应用到投影后元素的谓词
proj1 | - | 应用到第一元素范围的投影
proj2 | - | 应用到第二元素范围的投影

### 返回值

拥有指向首二个不相等元素的迭代器的 `ranges::mismatch_result` 。

若比较抵达 `last1` 或 `last2` ，无论何者先发生，都未找到不匹配，则对象保有尾迭代器与来自另一范围的对应迭代器。

### 复杂度

至多应用 min(`last1` - `first1`, `last2` - `first2`) 次谓词与对应的投影。

### 可能的实现

    struct mismatch_fn {
      template<std::input_iterator I1, std::sentinel_for<I1> S1,
               std::input_iterator I2, std::sentinel_for<I2> S2,
               class Pred = ranges::equal_to,
               class Proj1 = std::identity, class Proj2 = std::identity>
        requires std::indirectly_comparable<I1, I2, Pred, Proj1, Proj2>
      constexpr std::mismatch_result<I1, I2>
      operator()(I1 first1, S1 last1, I2 first2, S2 last2,
                 Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const
      {
          for (; first1 != last1 && first2 != last2; ++first1, (void)++first2) {
              if (!std::invoke(pred, std::invoke(proj1, *first1), std::invoke(proj2, *first2))) {
                break;
              }
          }
          return {first1, first2};
      }

      template<ranges::input_range R1, ranges::input_range R2,
               class Pred = ranges::equal_to,
               class Proj1 = std::identity, class Proj2 = std::identity >
      requires std::indirectly_comparable<ranges::iterator_t<R1>, ranges::iterator_t<R2>,
                                          Pred, Proj1, Proj2>
      constexpr
        ranges::mismatch_result<ranges::borrowed_iterator_t<R1>, ranges::borrowed_iterator_t<R2>>
      operator()(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const
      {
         return (*this)(ranges::begin(r1), ranges::end(r1),
                        ranges::begin(r2), ranges::end(r2),
                        std::ref(pred), std::ref(proj1), std::ref(proj2));
      }
    };

    inline constexpr mismatch_fn mismatch;

### 示例

此程序确定同时在给定字符串的首端与在末端逆序找到的最长子串（可能重叠）

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

    constexpr std::string_view mirror_ends(const std::string_view in)
    {
        const auto end = std::ranges::mismatch(in, in | std::views::reverse).in1;
        const std::size_t length = std::ranges::distance(in.begin(), end);
        return { in.cbegin(), length };
    }

    int main()
    {
        std::cout << mirror_ends("abXYZba") << '\n'
                  << mirror_ends("abca") << '\n'
                  << mirror_ends("ABBA") << '\n'
                  << mirror_ends("level") << '\n';

        using namespace std::literals::string_view_literals;

        static_assert("123"sv == mirror_ends("123!@#321"));
        static_assert("radar"sv == mirror_ends("radar"));
    }

输出：

    ab
    a
    ABBA
    level

### 参阅

ranges::equal (C++20) | 确定两个元素集合是否是相同的 (niebloid)
ranges::find ranges::find_if ranges::find_if_not (C++20)(C++20)(C++20) | 寻找首个满足特定判别标准的元素 (niebloid)
ranges::lexicographical_compare (C++20) | 当一个范围按字典顺序小于另一个范围时，返回 true (niebloid)
ranges::search (C++20) | 搜索一个元素范围 (niebloid)
mismatch | 寻找两个范围出现不同的首个位置 (函数模板)