Cri*_*ngo 20 c++ operators spaceship-operator c++20
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. is_transitive_child_of(*this)) return partial_ordering::greater;
return partial_ordering::unordered;
}
// ... other functions, but no other comparisons ...
};
Run Code Online (Sandbox Code Playgroud)
会定义operator>(a,b)为a<=>b > 0不会导致大量开销吗?(虽然形式与他讨论的不同).该代码首先测试相等性,然后测试less,最后greater测试,而不仅仅是直接测试greater.
我在这里错过了什么吗?
das*_*ght 10
会定义
operator>(a,b)为a<=>b > 0不会导致大量开销吗?
这会导致一些开销.然而,开销的大小是相对的 - 在运行比较的成本相对于程序的其余部分可忽略不计的情况下,通过实现一个运算符而不是五个运算符来减少代码重复可能是可接受的权衡.
但是,该提案并未建议删除其他比较运算符以支持<=>:如果要重载其他比较运算符,则可以自由执行:
概括:不要限制固有的东西.不要随意限制一整套用途.避免特殊情况和部分功能.- 例如,本文支持所有七个比较运算符和运算,包括通过添加三向比较
<=>.它还支持所有五个主要比较类别,包括部分订单.
对于一些大的定义.有开销,因为在部分排序,a == biff a <= b和b <= a.复杂性与拓扑排序相同O(V+E).当然,现代C++方法是编写安全,清晰和可读的代码然后进行优化.您可以先选择实施飞船运营商,然后在确定性能瓶颈后进行专业化.
一般来说,<=>当你处理一种类型时,重载是有意义的,在这种类型中,一次性进行所有比较要么过于昂贵,要么与不同地比较它们的成本相同.
使用字符串,<=>似乎比直接==测试更昂贵,因为你必须减去每对两个字符.但是,由于您必须将每对字符加载到内存中,因此在其上添加减法是一项微不足道的费用.实际上,比较两个数字的相等性有时会被编译器实现为减法和零测试.即使对于那些不这样做的编译器,减法和与零进行比较也可能没有明显低效.
所以对于像这样的基本类型,你或多或少都很好.
当你处理树木订购之类的事情时,你真的需要事先知道你关心的操作.如果你要求的只是==,你真的不想要搜索树的其余部分,只是为了知道它们是不平等的.
但是个人......我永远不会用比较运算符来实现像树排序这样的东西.为什么?因为我认为这样的比较应该是逻辑上快速的操作.树搜索是一个如此缓慢的操作,你真的不想偶然或在绝对必要之外的任何时间进行搜索.
看看这个案子吧.说一个家谱中的人"少于"另一个人,这究竟意味着什么?这意味着一个人是另一个人的孩子.在代码中直接问这个问题不是更具可读性is_transitive_child_of吗?
您的比较逻辑越复杂,您所做的事实就越不可能是"比较".可能有一些文本描述可以调用这种"比较"操作,这种操作更具可读性.
哦,当然,这样的类可以有一个返回partial_order表示两个对象之间关系的函数.但我不会称之为该功能operator<=>.
但无论如何,是<=>一个零开销的比较抽象?没有; 您可以构建一些案例,其中计算订单的成本要比检测您要求的特定关系的成本高得多.但个人如果是这样的话,还有,你不应该通过运营商比较这些类型的好机会可言.