# std::basic_string<CharT,Traits,Allocator>::compare

< cpp‎ | string‎ | basic string

| (1) |
int compare( const basic_string& str ) const; |  | (C++11 前)
int compare( const basic_string& str ) const noexcept; |  | (C++11 起) (C++20 前)
constexpr int compare( const basic_string& str ) const noexcept; |  | (C++20 起)
| (2) |
int compare( size_type pos1, size_type count1, const basic_string& str ) const; |  | (C++20 前)
constexpr int compare( size_type pos1, size_type count1, const basic_string& str ) const; |  | (C++20 起)
| (3) |
int compare( size_type pos1, size_type count1, const basic_string& str, size_type pos2, size_type count2 ) const; |  | (C++14 前)
int compare( size_type pos1, size_type count1, const basic_string& str, size_type pos2, size_type count2 = npos ) const; |  | (C++14 起) (C++20 前)
constexpr int compare( size_type pos1, size_type count1, const basic_string& str, size_type pos2, size_type count2 = npos ) const; |  | (C++20 起)
| (4) |
int compare( const CharT* s ) const; |  | (C++20 前)
constexpr int compare( const CharT* s ) const; |  | (C++20 起)
| (5) |
int compare( size_type pos1, size_type count1, const CharT* s ) const; |  | (C++20 前)
constexpr int compare( size_type pos1, size_type count1, const CharT* s ) const; |  | (C++20 起)
| (6) |
int compare( size_type pos1, size_type count1, const CharT* s, size_type count2 ) const; |  | (C++20 前)
constexpr int compare( size_type pos1, size_type count1, const CharT* s, size_type count2 ) const; |  | (C++20 起)
| (7) |
template < class T > int compare( const T& t ) const noexcept(/* see below */); |  | (C++17 起) (C++20 前)
template < class T > constexpr int compare( const T& t ) const noexcept(/* see below */); |  | (C++20 起)
| (8) |
template < class T > int compare( size_type pos1, size_type count1, const T& t ) const; |  | (C++17 起) (C++20 前)
template < class T > constexpr int compare( size_type pos1, size_type count1, const T& t ) const; |  | (C++20 起)
| (9) |
template < class T > int compare( size_type pos1, size_type count1, const T& t, size_type pos2, size_type count2 = npos) const; |  | (C++17 起) (C++20 前)
template < class T > constexpr int compare( size_type pos1, size_type count1, const T& t, size_type pos2, size_type count2 = npos) const; |  | (C++20 起)

比较二个字符序列。

1) 比较此 string 与 str 。
2) 比较此 string 的 `[pos1, pos1+count1)` 子串与 str 。若 count1 > size() - pos1 则子串为 `[pos1, size())` 。
3) 比较此 string 的 `[pos1, pos1+count1)` 子串与 str 的子串 `[pos2, pos2+count2)` 。若 count1 > size() - pos1 则第一子串为 `[pos1, size())` 。类似地若 count2 > str.size() - pos2 则第二子串为 `[pos2, str.size())` 。
4) 比较此 string 与始于 s 所指向字符的长度为 `Traits::length(s)` 的空终止字符序列。
5) 比较此 string 的 `[pos1, pos1+count1)` 子串与始于 s 所指向字符的长度为 `Traits::length(s)` 的空终止字符序列。若 count1 > size() - pos1 则子串为 `[pos1, size())` 。
6) 比较此 string 的 `[pos1, pos1+count1)` 子串与范围 `[s, s + count2)` 中的字符。（注意：范围 `[s, s + count2)` 中的字符可包含空字符。）
7) 如同用 std::basic_string_view<CharT, Traits> sv = t; 隐式转换 `t` 为 string_view `sv` ，然后比较此 string 与 `sv` 。此重载仅若 std::is_convertible_v<const T&, std::basic_string_view<CharT, Traits>> 为 true 且 std::is_convertible_v<const T&, const CharT*> 为 false 才参与重载决议。
8) 如同用 std::basic_string_view<CharT, Traits> sv = t; 隐式转换 `t` 为 string_view `sv` ，然后比较此 string 的 `[pos1, pos1+count1)` 子串与 `sv` ，如同用 std::basic_string_view<CharT, Traits>(data(), size()).substr(pos1, count1).compare(sv) 。此重载仅若 std::is_convertible_v<const T&, std::basic_string_view<CharT, Traits>> 为 true 且 std::is_convertible_v<const T&, const CharT*> 为 false 才参与重载决议。
9) 如同用 std::basic_string_view<CharT, Traits> sv = t; 隐式转换 `t` 为 string_view `sv` ，然后比较此 string 的 `[pos1, pos1+count1)` 子串与 `sv` 的 `[pos2, pos2+count2)` 子串，如同用 std::basic_string_view<CharT, Traits>(data(), size()).substr(pos1, count1).compare(sv.substr(pos2, count2)); 。此重载仅若 std::is_convertible_v<const T&, std::basic_string_view<CharT, Traits>> 为 true 且 std::is_convertible_v<const T&, const CharT*> 为 false 才参与重载决议。

按下列方式比较始于 `data1` 的 `count1` 个字符组成的字符序列与始于 `data2` 的 `count2` 个字符组成的字符序列。首先，如同用 size_type rlen = std::min(count1, count2) 计算要比较的字符数。然后调用 Traits::compare(data1, data2, rlen) 比较序列。对于标准字符特性，此函数进行逐字符字典序比较。若结果为零（到此为止的字符序列相等），则按下列方式比较其大小：

条件 | 结果 | 返回值
--- | --- | ---
`Traits::compare(data1, data2, rlen) < 0` | data1 小于 data2 | <0
`Traits::compare(data1, data2, rlen) == 0` | size1 < size2 | data1 小于 data2 | <0
size1 == size2 | data1 等于 data2 | ​0​
size1 > size2 | data1 大于 data2 | >0
`Traits::compare(data1, data2, rlen) > 0` | data1 大于 data2 | >0

### 参数

str | - | 要比较的另一 string
s | - | 指向要比较的字符串的指针
count1 | - | 此 string 要比较的字符数
pos1 | - | 此 string 中要比较的首字符的位置
count2 | - | 给定字符串要比较的字符数
pos2 | - | 给定字符串的要比较的首字符位置
t | - | 要比较的对象（可转换为 std::basic_string_view ）

### 返回值

若 *this 在字典序中先出现于参数所指定的字符序列，则为负值。

若两个序列比较等价则为零。

若 *this 在字典序中后出现于参数所指定的字符序列，则为正值。

### 异常

接收名为 `pos1` 或 `pos2` 的参数的重载若参数在范围外则抛出 std::out_of_range 。

7)
`noexcept` 说明：
noexcept(std::is_nothrow_convertible_v<const T&, std::basic_string_view<CharT, Traits>>)
8-9) 抛出任何到 `basic_string_view` 的转换所抛的异常。

### 可能的实现

    template<class CharT, class Traits, class Alloc>
    int basic_string<CharT, Traits, Alloc>::compare(const std::basic_string& s) const noexcept
    {
        size_type lhs_sz = size();
        size_type rhs_sz = s.size();
        if (int result = traits_type::compare(data(), s.data(), std::min(lhs_sz, rhs_sz)))
            return result;
        if (lhs_sz < rhs_sz)
            return -1;
        if (lhs_sz > rhs_sz)
            return 1;
        return 0;
    }

### 注解

对于不要求三路比较的情形， std::basic_string 提供通常关系运算符（ `<` 、 `<=` 、 `==` 、 `>` 等）。

此函数默认（以默认 std::char_traits ）不会考虑本地环境。具本地环境的三路比较见 std::collate::compare 。

### 示例

    #include <cassert>
    #include <string>
    #include <iostream>

    int main()
    {
        // 1) 与另一 string 比较
        {
            int compare_value{
                std::string{"Batman"}.compare(std::string{"Superman"})
            };
            std::cout << (
                compare_value < 0 ? "Batman comes before Superman\n" :
                compare_value > 0 ? "Superman comes before Batman\n" :
                "Superman and Batman are the same.\n"
            );
        }

        // 2) 与另一 string 比较子串
        {
            int compare_value{
                std::string{"Batman"}.compare(3, 3, std::string{"Superman"})
            };
            std::cout << (
                compare_value < 0 ? "man comes before Superman\n" :
                compare_value > 0 ? "Superman comes before man\n" :
                "man and Superman are the same.\n"
            );
        }

        // 3) 与另一子串比较子串
        {
            std::string a{"Batman"};
            std::string b{"Superman"};

            int compare_value{a.compare(3, 3, b, 5, 3)};

            std::cout << (
                compare_value < 0 ? "man comes before man\n" :
                compare_value > 0 ? "man comes before man\n" :
                "man and man are the same.\n"
            );
            // 与另一子串比较子串
            // 默认到为另一 string 的末尾
            assert(compare_value == a.compare(3, 3, b, 5));
        }

        // 4) 与另一 char 指针比较
        {
            int compare_value{std::string{"Batman"}.compare("Superman")};

            std::cout << (
                compare_value < 0 ? "Batman comes before Superman\n" :
                compare_value > 0 ? "Superman comes before Batman\n" :
                "Superman and Batman are the same.\n"
            );
        }

        // 5) 与另一 char 指针比较子串
        {
            int compare_value{std::string{"Batman"}.compare(3, 3, "Superman")};

            std::cout << (
                compare_value < 0 ? "man comes before Superman\n" :
                compare_value > 0 ? "Superman comes before man\n" :
                "man and Superman are the same.\n"
            );
        }

        // 6) 与另一 char 指针子串比较子串
        {
            int compare_value{std::string{"Batman"}.compare(0, 3, "Superman", 5)};

            std::cout << (
                compare_value < 0 ? "Bat comes before Super\n" :
                compare_value > 0 ? "Super comes before Bat\n" :
                "Super and Bat are the same.\n"
            );
        }
    }

输出：

    Batman comes before Superman
    Superman comes before man
    man and man are the same.
    Batman comes before Superman
    Superman comes before man
    Bat comes before Super

### 缺陷报告

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

DR | 应用于 | 出版时的行为 | 正确行为
--- | --- | --- | ---
LWG 2946 | C++17 | `string_view` 重载在某些情况下导致歧义 | 通过使之为模板来避免
P1148R0 | C++17 | 重载 (7) 的 noexcept 被 LWG2946 意外丢弃 | 恢复

### 参阅

operator==operator!=operator<operator>operator<=operator>=operator<=> (C++20 中移除)(C++20 中移除)(C++20 中移除)(C++20 中移除)(C++20 中移除)(C++20) | 以字典序比较两个字符串 (函数模板)
substr | 返回子串 (公开成员函数)
collate | 定义字典序比较和字符串的散列 (类模板)
strcoll | 按照当前本地环境比较两个字符串 (函数)
lexicographical_compare | 当一个范围按字典顺序小于另一个范围时，返回 true (函数模板)