如何在广义inttype上设置/检查msb?

时间:2019-02-05 16:57:01

标签: c++ templates bit-manipulation

我当前的代码库中有以下代码段:

// uint32_t id; defined somewhere
bool msb_set = id & 0x80000000

并希望将其更改为更灵活的内容:

using id_t = uint64_t;
id_t id;
bool msb_set = id & 0x80000000  // uh-oh, semantic change for any other differently sized inttype

如何根据所使用的具体整型轻松地生成适当的文字?我正在寻找某事

numeric_constants<id_t>::int_with_msb_set();

2 个答案:

答案 0 :(得分:1)

您可以利用std::bitset来检查是否设置了最高有效位。您可以将数字转换为std::bitset,然后返回最高有效位,例如

template<typename T> 
constexpr bool mb_set(T value)
{
    constexpr auto size = sizeof(T) * CHAR_BIT;
    return std::bitset<size>(value)[size - 1];
}

使用-O2-O3在clang上对其进行测试,从而优化了shr指令的功能。

答案 1 :(得分:1)

这是一个返回所需蒙版的函数:

template<typename T>
constexpr T getMsbMask()
{
    if constexpr (std::is_unsigned_v<T>)
        return T(-1) - T(-1) / 2;
    else
        return std::numeric_limits<T>::min();
    // Unsigned branch computes 0b11111... - 0b01111...
    // Signed branch assumes two's complement, which will soon be the standard:
    // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0907r0.html
}

Demo and tests on godbolt

编译器显然可以在编译时找出这些常量值,因此不会造成速度损失。

另一个明显的解决方案将是对每种类型进行专门化处理的结构(类似于std::numeric_limits)。