惊讶没有人发布无分支,类型安全的C版本:
template int sgn(T val) {
return (T(0) < val) - (val < T(0));
}
优点:
>实际上实现符号(-1,0或1)。这里使用copysign的实现仅返回-1或1,这不是符号。另外,这里的一些实现是返回一个float(或T)而不是一个int,这似乎是浪费。
>适用于int,浮点数,双精度,无符号短整数,或从整数0构造的任何自定义类型和可排序。
>快! copysign是缓慢的,特别是如果你需要促进,然后再狭窄。这是无分支的和优化的
>符合标准! bitshift hack是整洁的,但只适用于一些位表示,并且不工作,当你有一个无符号类型。在适当时,它可以作为手动专用。
>准确!与零的简单比较可以保持机器的内部高精度表示(例如x87上的80位),并避免过早的轮到零。
注意事项:
>它是一个模板,所以它会永远编译。
>显然有些人认为使用一个新的,有点深奥,和非常缓慢的标准库函数,甚至不真正实现signum是更容易理解。
>& 0部分检查触发GCC的-Wtype-limits警告,当为无符号类型实例化时。你可以通过使用一些重载来避免这种情况:
template inline constexpr
int signum(T x, std::false_type is_signed) {
return T(0) < x;
}
template inline constexpr
int signum(T x, std::true_type is_signed) {
return (T(0) < x) - (x < T(0));
}
template inline constexpr
int signum(T x) {
return signum(x, std::is_signed());
}
(这是第一个警告的一个很好的例子。)