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

问题描述 投票:152回答:3

C++ Templates - The Complete Guide, 2nd Edition介绍了max模板:

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

它解释使用“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”似乎对我有同样的结果。

c++ templates
3个回答
151
投票

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

这被认为是Stepanov和其他人的错误,因为它打破了给予ab的有用属性,你总是可以用{min(a, b), max(a, b)}对它们进行排序;为此,当参数相等时,你需要max(a, b)返回b


63
投票

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

有关上下文解释,请参阅@T.C.'s answer


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

template<class T> constexpr const T& max(const T& a, const T& b);

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

返回:值越大。

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

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

特别是,如果ab是等价的,a < bb < a都是false,所以:右边的值将在条件运算符中返回,所以a必须在右边,所以:

a < b ? b : a

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

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


21
投票

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

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

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

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

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

EG

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
© www.soinside.com 2019 - 2024. All rights reserved.