为什么pair的比较运算符比用户提供的运算符<更喜欢转换?

Osy*_*otr 5 c++ comparison-operators c++20

切换到 C++20 后,我发现我们的一些测试失败了。以下代码的输出在 C++17 和 C++20 模式之间有所不同:

https://godbolt.org/z/hx4a98T13

class MyString
{
public:
    operator char const *() const
    {
        std::printf("convert ");
        return nullptr;
    }

    bool operator<(MyString const & other) const
    {
        std::printf("MyString::operator< ");
        return 1;
    }
};

int main()
{
    MyString s1;
    MyString s2;
    std::printf("s1 < s2 = %d\n", s1 < s2);

    std::pair<MyString, MyString> pair1;
    std::pair<MyString, MyString> pair2;
    std::printf("pair1 < pair2 = %d\n", pair1 < pair2);
}
Run Code Online (Sandbox Code Playgroud)
/// C++17
MyString::operator< s1 < s2 = 1
MyString::operator< pair1 < pair2 = 1
/// C++20
MyString::operator< s1 < s2 = 1
convert convert convert convert pair1 < pair2 = 0
Run Code Online (Sandbox Code Playgroud)

似乎更std::pair::operator<=>喜欢合成operator<而不是用户提供的。为什么会这样?

PS:我确实知道使转换运算符显式解决了这个问题,但我真的很想知道是什么导致了这种行为。

Dre*_*ann 7

这是 C++20 中的一个(可能是意外的)重大更改。

std::pair在 C++20 中,对use进行排序比较operator<=>,反过来将在其组件上使用operator<=> (如果可能)

operator<=>您的类型唯一可用的MyString是转换后的char const *,因此它成为所选的比较。


您可以通过使用MyStringImplementoperator<=>而不是 来解决此问题operator<

或者您可以 make operator char const *() explicit,这将提供 no ,从而导致从您的 中综合operator<=>三向比较。operator<

  • 它只是“破坏”,因为该类型已经被破坏了。您可以在 C++17 中编写 `s1 &gt; s2` (反向比较!),这意味着该类型实际上已经进行了 *all* 比较。C++20 只是在这些东西上调用用户代码。 (2认同)