# std::lexicographical_compare_three_way

< cpp‎ | algorithm

定义于头文件 `<algorithm>` |  |
template< class InputIt1, class InputIt2, class Cmp > constexpr auto lexicographical_compare_three_way( InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, Cmp comp) -> decltype(comp(*first1, *first2)); | (1) | (C++20 起)
template< class InputIt1, class InputIt2 > constexpr auto lexicographical_compare_three_way( InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2); | (2) | (C++20 起)

用三路比较，以字典序比较二个范围 [first1, last1) 和 [first2, last2) ，并产生最强可应用比较类别类型的结果。

1) 返回两个范围中首对按照 `comp` 不等价的元素间的序，若它们存在，否则（若一个范围按照 `comp` 等价于另一个范围的前缀）返回两个范围长度间的序。
2) 等价于：

    return std::lexicographical_compare_three_way(
        first1, last1, first2, last2, std::compare_three_way());

### 参数

first1, last1 | - | 要检验的第一元素范围
first2, last2 | - | 要检验的第二元素范围
comp | - | 函数对象类型。若其返回类型不是三个比较类别类型（ `std::strong_ordering`、 `std::weak_ordering` 或 `std::partial_ordering` ）之一则程序非良构。
类型要求
- `InputIt1, InputIt2` 必须满足老式输入迭代器 (LegacyInputIterator) 的要求。

### 返回值

定义如上的比较类别类型的值。

### 复杂度

至多应用 N 次 `comp` ，其中 N 为两范围长度的较小者。

### 可能的实现

    template< class I1, class I2, class Cmp >
    constexpr auto lexicographical_compare_three_way( I1 f1, I1 l1, I2 f2, I2 l2, Cmp comp )
        -> decltype(comp(*f1, *f2))
    {
        using ret_t = decltype(comp(*f1, *f2));
        static_assert(std::disjunction_v<
                          std::is_same<ret_t, std::strong_ordering>,
                          std::is_same<ret_t, std::weak_ordering>,
                          std::is_same<ret_t, std::partial_ordering>>,
                      "The return type must be a comparison category type.");

        bool exhaust1 = (f1 == l1);
        bool exhaust2 = (f2 == l2);
        for (; !exhaust1 && !exhaust2; exhaust1 = (++f1 == l1), exhaust2 = (++f2 == l2))
            if (auto c = comp(*f1, *f2); c != 0)
                return c;

        return !exhaust1 ? std::strong_ordering::greater :
               !exhaust2 ? std::strong_ordering::less :
                           std::strong_ordering::equal;
    }

### 示例

    #include <algorithm>
    #include <cctype>
    #include <compare>
    #include <iomanip>
    #include <iostream>
    #include <string_view>
    #include <utility>
    using namespace std::literals;

    void show_result(std::string_view s1, std::string_view s2, std::strong_ordering o)
    {
        std::cout << quoted(s1) << " is ";
        (o < 0) ? std::cout << "less than " :
        (o > 0) ? std::cout << "greater than " :
                  std::cout << "equal to ";
        std::cout << quoted(s2) << '\n';
    }

    int main()
    {
        auto cmp_icase = [](char x, char y) {
            const auto ux { std::toupper(x) };
            const auto uy { std::toupper(y) };
            return (ux < uy) ? std::strong_ordering::less:
                   (ux > uy) ? std::strong_ordering::greater:
                               std::strong_ordering::equal;
        };

        for (const auto& [s1, s2] : { std::pair{"one"sv, "ONE"sv},
                                               {"two"sv, "four"sv},
                                               {"three"sv, "two"sv} }) {
            const auto res = std::lexicographical_compare_three_way(
                s1.cbegin(), s1.cend(), s2.cbegin(), s2.cend(), cmp_icase);
            show_result(s1, s2, res);
        }
    }

输出：

    "one" is equal to "ONE"
    "two" is greater than "four"
    "three" is less than "two"

### 缺陷报告

下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。

DR | 应用于 | 出版时的行为 | 正确行为
--- | --- | --- | ---
LWG 3410 | C++20 | 要求了额外的迭代器间比较 | 移除该要求

### 参阅

lexicographical_compare | 当一个范围按字典顺序小于另一个范围时，返回 true (函数模板)
compare_three_way (C++20) | 实现 x <=> y 的函数对象 (类)
ranges::lexicographical_compare (C++20) | 当一个范围按字典顺序小于另一个范围时，返回 true (niebloid)