11

cppreference on 上std::ranges::less,在注释中我们可以看到:

与 不同std::lessstd::ranges::less要求所有六个比较运算符<<=>>===!=有效(通过totally_ordered_with约束)。

但为什么?为什么我们要使用std::ranges::less{}而不是std::less{}less{}仅当定义了其他比较运算符(而不仅仅是一个)时,我们才想要的实际情况是什么<

4

2 回答 2

8

只有在定义了其他比较运算符(而不仅仅是 < 一个)的情况下,我们才希望减少 {} 的实际情况是什么?

并非 Ranges 库的所有内容都纯粹基于“实用”的内容。其中大部分是关于使语言和库具有逻辑意义。

概念作为语言特征使标准库有机会定义有意义的对象特征组合。从纯粹实用的角度来说,说一个类型有 anoperator<是有用的,即告诉您它可以使用哪些操作。但它并没有真正说明类型的任何意义。

如果一个类型是完全有序的,那么这在逻辑上意味着您可以使用任何比较运算符来比较该类型的两个对象。总序的思想下,a < bb > a都是等价的语句。因此,如果代码仅限于提供总顺序的类型,则应该允许该代码使用任一语句。

ranges::less::operator()使用除 之外的任何运算符<。但是此功能仅限于对totally_ordered概念建模的类型。存在此约束是因为这ranges::less就是:比较完全有序的类型它可以有一个更窄的约束,但这将抛弃全排序提供的任何意义。

它还可以防止您向用户公开任意实现细节。例如,假设您有一个采用某种类型的模板,T并且您想Tranges::less基于 - 的操作中使用。如果您将此模板限制为仅具有一个operator<,那么您已有效地将您的实现置于约束中。您不再有实现在ranges::greater内部切换的自由。然而,如果你设置std::totally_ordered了约束,你就会让用户清楚他们需要做什么,同时让你自己可以自由地使用你需要的任何函子。

并且由于operator<=>存在并且可以很容易地在一个函数中实现排序运算符,因此没有实际的缺点。好吧,除了必须在 C++17 和 C++20 上编译的代码。

从本质上讲,您不应该只写operator<开头就编写“有序”的类型。

于 2020-08-15T05:13:53.353 回答
1

据我所知,根据提案,这个想法只是简化功能对象的设计。std::less是一个模板类,它需要一个模板参数并表示同质比较。此模板参数可以省略,默认为std::less<void>允许异构比较。争论似乎是同构案例是不必要的,因为它可以通过异构方法很好地处理,因此可以大大简化设计并且根本不需要类模板。

至于为什么需要其他运算符operator<,我不完全确定。我最好的猜测是,这只是在 C++ 中定义两个可能不同的类型之间的总顺序的一部分。

于 2020-08-15T02:20:09.153 回答