为什么要用"b <a?a:b"而不是"a <b?b:"实现最大模板?

Nan*_*iao 154 c++ templates

C++模板 - 完整指南,第2版介绍了最大模板:

template<typename T>
T max (T a, T b)
{
  // if b < a then yield a else yield b
  return  b < a ? a : b;
}
Run Code Online (Sandbox Code Playgroud)

它解释了使用“b < a ? a : b”而不是“a < b ? b : a”:

请注意,根据[StepanovNotes]的max()模板有意返回"b <a?a:b"而不是"a <b?b:"确保即使两个值相等但不相等,函数也能正常运行.

怎么理解" even if the two values are equivalent but not equal."?“a < b ? b : a”对我来说似乎有相同的结果.

T.C*_*.C. 150

std::max(a, b)确实指定a在两者相等时返回.

这是考虑了一个错误斯捷潘诺夫和其他人,因为它打破了给出的有用的属性a和b,你可以随时对它们进行排序{min(a, b), max(a, b)}; 为此,你想要在参数相同时max(a, b)返回b.

  • 从那个链接"我很难责怪这样做的人:毕竟,他们只是遵循我写的**max**的C++标准规范.我花了好几年的时间才发现我错了." - 哇! (48认同)
  • 你不能只做`{min(a,b),max(b,a)}`? (23认同)
  • @CaptainMan:是的,但它仍然不那么明显.我认为从逻辑意义上来说,"max(a,b)`将返回if-and-only-if`min(a,b)`返回b,并且_vice versa_以便它们彼此相反和(无序)集`{min(a,b),max(a,b)}`总是等于`{a,b}`. (12认同)
  • @jpmc26:如果有人按时间对事件列表进行排序,则不必关心排序操作是否稳定以关注每个事件在输入中只出现一次,同样在输出中恰好出现一次.某些操作(如查找和消除重复事件)可能需要使用完整的排序,但在许多其他情况下,以任意顺序列出同时事件,但不能复制或省略它们是可以接受的. (5认同)
  • @supercat在那种情况下,除了* timestamp *(排序键)之外,将min和max应用于任何东西都是没有意义的。如果相等并不意味着可互换性,那么事件(对象)本身甚至不应该是可比较的。作为一种排序机制,“ {min(a,b),max(a,b)}”的唯一方法使* any *有意义是对象是可互换的。 (2认同)

Hol*_*olt 62

这个答案解释了为什么从C++标准的观点来看给定的代码是错误的,但它是脱离了上下文的.

有关上下文解释,请参阅@ TC的答案.


标准定义std::max(a, b)如下[alg.min.max](重点是我的):

template<class T> constexpr const T& max(const T& a, const T& b);
Run Code Online (Sandbox Code Playgroud)

要求:类型T是LessThanComparable(表18).

返回:值越大.

备注:当参数等效时返回第一个参数.

等效在这里意味着!(a < b) && !(b < a)是true [alg.sorting#7] .

特别是,如果a和b是等价的,都a < b和b < a都false,等右边的值:将在有条件的经营者退换,所以a必须是在右边,所以:

a < b ? b : a
Run Code Online (Sandbox Code Playgroud)

......似乎是正确的答案.这是libstdc ++和libc ++使用的版本.

因此,根据当前标准,引用中的信息似乎是错误的,但定义它的上下文可能不同.

  • [Godbolt链接](https://godbolt.org/g/NRxiE5)解释了这个问题(感谢@songyuanyao对于`X`的定义). (4认同)

son*_*yao 21

关键是当它们是等价的时候应该归还哪一个; std::max必须a为这种情况返回(即第一个参数).

如果它们是等价的,则返回a.

所以a < b ? b : a应该使用; 另一方面,b < a ? a : b;将返回b错误.

(正如@Holt说的那样,引用似乎相反.)

"这两个值相等但不相等"意味着它们在比较时具有相同的值,但它们在某些其他方面是不同的对象.

例如

struct X { int a; int b; };
bool operator< (X lhs, X rhs) { return lhs.a < rhs.a; }
X x1 {0, 1};
X x2 {0, 2};
auto x3 = std::max(x1, x2); // it's guaranteed that an X which cantains {0, 1} is returned
Run Code Online (Sandbox Code Playgroud)

  • @ネロク - [这只是标准部分的任意选择](https://timsong-cpp.github.io/cppwp/n4659/alg.min.max#11).虽然这是一个很好的问题,但它有点值得商榷. (4认同)
  • @ネロク我认为标准只是想让它确定; 当它们等同于哪一个应该归还. (2认同)