当前位置:  开发笔记 > 编程语言 > 正文

模板化无分支int max/min函数

如何解决《模板化无分支intmax/min函数》经验,为你挑选了1个好方法。

我正在尝试编写一个无分支函数来返回两个整数的MAX或MIN而不求助于if(或?:).使用通常的技术,我可以很容易地为给定的字大小做到这一点:

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我真的在那种必要的有序处理器上编写那种应用程序,我的问题是是否有办法使用C++模板将其推广到所有大小的int.

>> 31步仅适用于int32s,当然,虽然我可以对INT8,INT16和Int64的功能复制出来过载,好像我应该用一个模板函数.但是如何以位为单位获取模板参数的大小?

有没有比这更好的方法呢?我可以强制对面具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 );
}

并且,完成上述操作后,我可以阻止它被用于除整数类型之外的任何东西(例如,没有浮点数或类)吗?



1> Evan Teran..:

通常,看起来不错,但是为了100%可移植性,用CHAR_BIT(或numeric_limits :: max())替换8,因为不能保证字符是8位.

任何好的编译器都足够聪明,可以在编译时合并所有数学常量.

您可以使用类型特征库强制对其进行签名.通常看起来像(假设您的numeric_traits库名为numeric_traits):

typename numeric_traits::signed_type x;

手动滚动的numeric_traits标头的示例可能如下所示:http://rafb.net/p/Re7kq478.html(有足够的空间可以添加,但您明白了).

或者更好的是,使用boost:

typename boost::make_signed::type x;

编辑:IIRC,签署右移不必须是算术.这是常见的,我使用的每个编译器都是如此.但是我相信标准会让编译器在签名类型上是右移也不算算.在我的标准草案副本中,写了以下内容:

E1 >> E2的值是E1右移E2位位置.如果E1具有无符号类型或者E1具有有符号类型和非负值,则结果的值是E1的商除以提升到功率E2的数量2的积分.如果E1具有带符号类型和负值,则结果值是实现定义的.

但正如我所说,它将适用于我见过的每个编译器:-p.


我的头脑不禁想象可能存在于选择不保留符号的编译器实现者的核心内容.
推荐阅读
小白也坚强_177
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有