# std::experimental::ranges::equal

< cpp‎ | experimental‎ | ranges

定义于头文件 `<experimental/ranges/algorithm>` |  |
template< InputIterator I1, Sentinel<I1> S1, InputIterator I2, Sentinel<I2> S2, class Pred = ranges::equal_to<>, class Proj1 = ranges::identity, class Proj2 = ranges::identity > requires IndirectlyComparable<I1, I2, Pred, Proj1, Proj2> bool equal(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = Pred{}, Proj1 proj1 = Proj1{}, Proj2 proj2 = Proj2{}); | (1) | (范围 TS)
template< InputRange R1, InputRange R2, class Pred = ranges::equal_to<>, class Proj1 = ranges::identity, class Proj2 = ranges::identity > requires IndirectlyComparable<ranges::iterator_t<R1>, ranges::iterator_t<R2>, Pred, Proj1, Proj2> bool equal(R1&& r1, R2&& r2, Pred pred = Pred{}, Proj1 proj1 = Proj1{}, Proj2 proj2 = Proj2{}); | (2) | (范围 TS)
template< InputIterator I1, Sentinel<I1> S1, class I2, class Pred = ranges::equal_to<>, class Proj1 = ranges::identity, class Proj2 = ranges::identity > requires InputIterator<std::decay_t<I2>> && !Range<I2> && IndirectlyComparable<I1, std::decay_t<I2>, Pred, Proj1, Proj2> bool equal(I1 first1, S1 last1, I2&& first2_, Pred pred = Pred{}, Proj1 proj1 = Proj1{}, Proj2 proj2 = Proj2{}); | (3) | (范围 TS) (弃用)
template< InputRange R1, class I2, class Pred = ranges::equal_to<>, class Proj1 = ranges::identity, class Proj2 = ranges::identity > requires InputIterator<std::decay_t<I2>> && !Range<I2> && IndirectlyComparable<ranges::iterator_t<R1>, std::decay_t<I2>, Pred, Proj1, Proj2> bool equal(R1&& r1, I2&& first2_, Pred pred = Pred{}, Proj1 proj1 = Proj1{}, Proj2 proj2 = Proj2{}); | (4) | (范围 TS) (弃用)

1) 若范围 `[first1, last1)` 等于 `[first2, last2)` 则返回 true ，否则返回 false 。
2) 同 (1) ，但以 `r1` 为第一源范围并以 `r2` 为第二源范围，如同以 ranges::begin(r1) 为 `first1` ，以 ranges::end(r1) 为 `last1` ，以 ranges::begin(r2) 为 `first2` 并以 ranges::end(r2) 为 `last2` 。
3) 同 (1) ，除了在穷尽第一范围或检测到首个不匹配时认为第二范围结束。等价于 return last1 == ranges::mismatch(first1, last1, std::forward<I2>(first2_), comp, proj1, proj2).in1(); 。
4) 同 (3) ，但以 `r1` 为第一源范围，如同以 ranges::begin(r1) 为 `first1` 并以 ranges::end(r1) 为 `last1` 。

若二个范围有相同数量的元素，且对于范围 `[first1,last1)` 中的每个迭代器 `i` ， ranges::invoke(pred, ranges::invoke(proj1, *i), ranges::invoke(proj2, *(first2 + (i - first1)))) 为 `true` ，则认为二个范围相等。

尽管声明描述如上，算法声明的模板形参的实际数量和顺序是未指定的。从而若在调用算法时使用显式模板实参，则程序很可能不可移植。

### 参数

first1, last1 | - | 第一元素范围
r1 | - | 第一元素范围
first2, last2 | - | 第二元素范围
r2 | - | 第二元素范围
first2_ | - | 第二元素范围的起始
pred | - | 应用到投影后元素的谓词
proj1 | - | 应用到第一范围中元素的投影
proj2 | - | 应用到第二范围中元素的投影

### 返回值

若二个范围相等则为 true ，否则返回 false 。

### 注意

不应该用 `ranges::equal` 比较来自 std::unordered_set 、 std::unordered_multiset 、 std::unordered_map 或 std::unordered_multimap 的迭代器所组成的范围，因为即使二个容器存储相同的元素，在容器中存储元素的顺序也可能不同。

比较整个容器是否相等时，通常更偏好使用对应容器的 `operator==` 。

### 复杂度

1-2) 若满足 SizedSentinel<S1, I1> && SizedSentinel<S2, I2> 且 last1 - first1 != last2 - first2 ，则不应用谓词和投影。否则至多应用 min(`last1` - `first1`, `last2` - `first2`) 次谓词及各一次投影。
3-4) 至多应用 `last1` - `first1` 次谓词及各一次投影。

### 可能的实现

    namespace detail
    {
        template< InputIterator I1, SizedSentinel<I1> S1,
                  InputIterator I2, SizedSentinel<I1> S2 >
        bool check_size(I1& first1, S1& last1, I2& first2, S2& last2)
        {
            return last1 - first1 != last2 - first2;
        }

        template< InputIterator I1, Sentinel<I1> S1, InputIterator I2, Sentinel<I1> S2 >
        bool check_size(I1& first1, S1& last1, I2& first2, S2& last2)
        {
            return false;
        }
    }

    template< InputIterator I1, Sentinel<I1> S1, InputIterator I2, Sentinel<I2> S2,
              class Pred = ranges::equal_to<>,
              class Proj1 = ranges::identity, class Proj2 = ranges::identity >
      requires IndirectlyComparable<I1, I2, Pred, Proj1, Proj2>
    bool equal(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = Pred{},
               Proj1 proj1 = Proj1{}, Proj2 proj2 = Proj2{})
    {
        if(detail::check_size(first1, last1, first2, last2)) return false;
        for(; first1 != last1 && first2 != last2; (void) ++first1, (void)++first2) {
            if(!ranges::invoke(pred, ranges::invoke(proj1, *first1),
                                     ranges::invoke(proj2, *first2))) {
                return false;
            }
        }
        return first1 == last1 && first2 == last2;
    }

### 示例

| 本节未完成 原因：暂无示例

### 参阅

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