为什么较少引入STD::Range::?

2022-05-16 00:00:00 c++ c++20 std-ranges

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

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

但是...为什么?为什么我们要使用std::ranges::less{}而不是std::less{}?如果只定义了<比较运算符,而不是只定义了<比较运算符,那么我们希望less{}的实际情况是什么?


解决方案

如果定义了其他比较运算符,而不仅仅是,实际情况是什么情况下我们想要减{}

并不是Ranges库的所有内容都是纯粹基于实用的。这很大程度上是为了让语言和库具有逻辑意义。

作为语言功能的概念使标准库有机会定义对象功能的有意义的组合。说一个类型有一个operator<从纯实用的角度来说是有用的,它告诉你什么操作对它是可用的。但它并没有真正说明有关该类型的任何有意义的内容。

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

ranges::less::operator()不使用<以外的任何运算符。但该函数仅限于模拟totally_ordered概念的类型。这个约束之所以存在,是因为ranges::less对于是:比较完全有序的类型。它可以有一个更窄的约束,但这将丢弃总排序提供的任何意义。

它还可以防止您向用户公开任意的实现细节。例如,假设您有一个采用某种类型T的模板,并且您希望在基于ranges::less的操作中使用T。如果您将该模板限制为只有operator<,那么您就有效地将您的实现放入了约束中。您不再拥有在内部将实现切换到ranges::greater的自由。然而,如果您将std::totally_ordered放在您的约束中,您将向用户清楚他们需要做什么,同时允许您自己自由地使用您需要的任何函数器。

由于operator<=>的存在并使得在一个函数中实现排序运算符变得容易,因此不存在实用的缺点。除了必须在C++17和C++20上编译的代码。

本质上,您不应该只通过编写operator<来编写排序的类型。

相关文章