我正在尝试编写一个无分支函数来返回两个整数的 MAX 或 MIN,而不求助于 if (或 ?:)。使用通常的技术 https://stackoverflow.com/questions/227383/how-do-i-programmatically-return-the-max-of-two-integers-without对于给定的字长,我可以很容易地做到这一点:
inline int32 imax( int32 a, int32 b )
{
// signed for arithmetic shift
int32 mask = a - b;
// mask < 0 means MSB is 1.
return a + ( ( b - a ) & ( mask >> 31 ) );
}
现在,假设arguendo http://en.wikipedia.org/wiki/For_arguing我确实是在必要的有序处理器上编写这种应用程序,我的问题是是否有一种方法可以使用 C++ 模板将其推广到所有大小的 int。
The >>31当然,step 仅适用于 int32,虽然我可以复制 int8、int16 和 int64 函数的重载,但似乎我应该使用模板函数。但是如何获取模板参数的大小bits?
还有比这更好的方法吗?我可以强制在掩码T上签名吗?如果 T 是无符号的,则掩码移位步骤将不起作用(因为它将是逻辑移位而不是算术移位)。
template< typename T >
inline T imax( T a, T b )
{
// how can I force this T to be signed?
T mask = a - b;
// I hope the compiler turns the math below into an immediate constant!
mask = mask >> ( (sizeof(T) * 8) - 1 );
return a + ( ( b - a ) & mask );
}
并且,完成上述操作后,我可以阻止它用于除整数类型之外的任何类型(例如,没有浮点数或类)吗?
EDIT:这个答案来自C++11之前。从那时起,C++11 及更高版本提供了make_signed<T>
以及作为标准库一部分的更多内容
一般来说,看起来不错,但为了 100% 可移植性,请将 8 替换为CHAR_BIT
(or numeric_limits<char>::max()
) 因为不能保证字符是 8 位的。
任何好的编译器都足够聪明,可以在编译时合并所有数学常量。
您可以使用类型特征库强制对其进行签名。通常看起来像这样(假设您的 numeric_traits 库称为 numeric_traits):
typename numeric_traits<T>::signed_type x;
手动滚动 numeric_traits 标头的示例如下所示:http://rafb.net/p/Re7kq478.html http://rafb.net/p/Re7kq478.html(还有很多补充的空间,但你明白了)。
或者更好的是,使用 boost:
typename boost::make_signed<T>::type x;
编辑:IIRC,有符号右移不会不得不算术。这是很常见的,而且我使用过的每个编译器都是如此。但我相信该标准让编译器自行决定右移是否在有符号类型上算术。在我的标准草案副本中,写有以下内容:
E1 >> E2 的值为 E1
右移 E2 位位置。如果E1
具有无符号类型或者如果 E1 有
有符号类型和非负值,
结果的值是
E1 商的整数部分
除以数量 2 得出
电源E2。如果 E1 有符号类型
和一个负值,结果
值是实现定义的.
但正如我所说,它适用于我见过的每个编译器:-p。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)