如何在模板函数c ++中更改typename的signed-ness

时间:2015-07-11 12:27:06

标签: c++ bit-shift

所以我一直试图在c ++(11)中进行“循环”按位移位,我已经得到了基本代码:

#include <cstdio>
#include <limits> // is_signed
#include <limits.h> // CHAR_BIT

template<typename T>
T rotl(T input, unsigned int shift)
{
    return (input<<shift)|(input>>(sizeof(T)*CHAR_BIT-shift));
}

template<typename T>
T rotr(T input, unsigned int shift)
{
    return (input>>shift)|(input<<(sizeof(T)*CHAR_BIT-shift));
}

int main()
{
    int i = -5;

    std::printf( "%i\n", i);

    i = rotl(i, 4); // or other value
    std::printf( "%i\n", i);

    i = rotr(i, 4); // same value as above
    std::printf( "%i\n", i);
}

当输出如下所示时,这给了我预期的行为:

-5
-1
-1

因为int i已签名,但是如果我对代码执行此操作:

i = (int)rotl((unsigned int)i, 4);
. . .
i = (int)rotr((unsigned int)i, 4);

输出变为:

-5
-65
-5

这也像我想要的那样。我还可以使用numeric_limits检查T的签名,如下所示:

T rotr(T input, unsigned int shift)
{
    if(std::numeric_limits<T>::is_signed == false){
        return ()
    }else{
        return // problem here
    }
}

但我似乎无法弄清楚如何扭转T的签名,(unsigned T)对于类型名称无效。那我该怎么做呢?我宁愿不使用除标准库之外的任何东西(真正的个人品味),但如果没有合理的方法,我可能会考虑非标准库。

1 个答案:

答案 0 :(得分:2)

正如celticminstrel建议使用std::make_unsigned<T>::type

以下是:


template<typename T>
T rotl(T input, unsigned int shift)
{
    typename std::make_unsigned<T>::type ii = static_cast<typename std::make_unsigned<T>::type>(input); 
    return static_cast<T>((ii<<shift)|(ii>>(sizeof(T)*CHAR_BIT-shift)));
}