只使用<泛型编程中的比较

Use only < comparisons in Generic Programming

本文关键字:泛型编程 比较      更新时间:2023-10-16

我正在阅读 c++入门(第5版)中的"模板和泛型编程"部分,但是我对那里的一些东西感到困惑。

当谈到"编写类型无关的代码"在P655 &P656,发件人说"正文中的测试只使用<比较">,因为"只使用<操作符,我们减少了对可以与compare函数一起使用的类型的要求。这些类型必须支持><,但它们也不需要支持>。" .

是否有支持<但不是> ?如果是,为什么?是否优于> ?我在谷歌上搜索了一段时间,但我没有得到答案。谁能给我一些例子或一些推荐链接?

如果是,为什么<优于> ?

仅约定。在ASCII中,字符'<'首先出现,在偏序集合上的小于是可以构造比较的原语(即,该集合被划分为等价群)。

如果我们有a, boperator <:

  • & lt;b if operator <( a, b )
  • a> b if operator <( b, a )
  • 如果! operator <( b, a ) ,则a≤ba = b if ! operator <( a, b ) && ! operator <( b, a )
  • 等。

c++有许多这样的约定,用来描述类型的行为。这些通常被称为概念,一个即将到来的语言扩展,大写- c概念,将允许您查询和指定诸如小于操作符是否定义部分排序之类的事情。

是否存在支持<而不支持>的类型?

是的,很多。惯例是定义operator <,然后忘记>,因为它是多余的。您可以使用std::relops之类的东西来根据<自动定义>,但总的来说,一开始就避免编写>操作符更容易。

标准库中所有依赖于排序的部分,如std::sortstd::map,永远不会使用> .

在某些语言(如Haskell)中,有这个最小完整定义的概念。例如,如果您定义了一个具有总顺序的新类(例如有理数),则定义<=操作符就足够了。其他操作符可以(在某些情况下自动)根据最小定义定义:

x > y可以定义为! (x <= y)

x == y可定义为x <= y && y <= x

x >= y可以定义为x > y || x == y

x < y可以定义为! (x >= y)

在这种情况下,最小定义只有一个操作符。一般来说,您只需要在最小的完整定义中定义操作符,这样做将减少可以"推断"的其他操作符的冗余定义。仅实现最小定义还可以减少在实现非必要操作符(如>)时引入错误或不一致的可能性。关键是实现操作符的最小集合通常是有益的。

关于为什么<>更受欢迎,我认为这是一个选择和惯例的问题。严格地说,可以选择实现任何最小定义。对于全序类型,{<=}和{>=}都是最小完全集。those types must support是这些集合中的一个,but they need not also support是其余的

在某些情况下,一个类型使用operator <可能没有其他原因,只是用作排序键。这个顺序不一定是有意义的,它只是为了支持您正在描述的模板化api。例如,std::map将根据operator <对其所有元素进行排序,除非您给它一个不同的谓词。你可能并不关心顺序是什么,你只想快速(O(log n))查找。否则这个顺序对类来说可能是完全没有意义的。(在这种情况下,您可能需要operator <的自由函数二进制版本,而不是使其成为成员,或者提供显式谓词)。

如果其他操作对你的类是有意义的,那么务必实现它们。它会让你的用户的生活更简单。如果能简化逻辑,你总是可以用operator <来实现它们。

我能想到他们使用operator <而不是operator >的唯一原因是它使顺序更自然(假设您的语言是从左到右书写)。如果你将1到5的整数存储在map中,它们将被排序为1 <2 & lt;3 & lt;4 & lt;5. 因此,在operator <(T left, T right)的情况下,如果谓词返回true,则左操作数将更确切地位于右操作数的"左侧"。

在你引用的文本上再过一遍之后,在我看来,他们更多地是在谈论编写使用 operator <的算法的人,而不是编写实现 operator <的类的人。如果你正在编写一个需要与别人的代码一起工作的算法,并且你希望他们给你一种排序元素的方法,你应该只需要operator <。关键是要简化"客户"端的工作。