我一直将其精简为仅使用Boost Operators:
#include <boost/operators.hpp>
struct F : boost::totally_ordered1<F, boost::totally_ordered2<F, int>> {
/*implicit*/ F(int t_) : t(t_) {}
bool operator==(F const& o) const { return t == o.t; }
bool operator< (F const& o) const { return t < o.t; }
private: int t;
};
int main() {
#pragma GCC diagnostic ignored "-Wunused"
F { 42 } == F{ 42 }; // OKAY
42 == F{42}; // C++17 OK, C++20 infinite …Run Code Online (Sandbox Code Playgroud)Herb Sutter在他的"宇宙飞船"运营商提案(第12.2节,第12页底部)中说:
基于所有内容
<=>及其返回类型:此模型具有主要优势,与先前的C++提议和其他语言的功能相比,此提案有一些独特之处:[...]
(6)效率,包括最终实现用于比较的零开销抽象:绝大多数比较总是单通道.唯一的例外是生成,
<=并且>=在支持部分排序和相等的类型的情况下.对于<单通是基本实现了零开销的原则,以避免重复平等的比较,如struct Employee { string name; /*more members*/ };在使用的struct Outer { Employeee; /*more members*/ };-今天的对比违反零开销抽象,因为operator<在Outer执行冗余相等比较,因为它执行if (e != that.e) return e < that.e;横贯平等前缀e.name两次(如果名称相同,则遍历Employee两次其他成员的相等前缀),这通常无法优化.正如Kamiński所指出的,零开销抽象是C++的支柱,并且首次实现它的比较是这种设计的一个重要优势<=>.
但他给出了这个例子(第1.4.5节,第6页):
class PersonInFamilyTree { // ...
public:
std::partial_ordering operator<=>(const PersonInFamilyTree& that) const {
if (this->is_the_same_person_as ( that)) return partial_ordering::equivalent;
if (this->is_transitive_child_of( that)) return partial_ordering::less;
if (that. …Run Code Online (Sandbox Code Playgroud) 切换到 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 …Run Code Online (Sandbox Code Playgroud)