模板结构体的静态const成员的不同值

Different values of a static const member of a template struct

本文关键字:成员 静态 结构体 const      更新时间:2023-10-16

我正在尝试制作一个小的元编程结构,它生成width位的位掩码,将shift位向左移动(主要用于学习目的)。下面的代码触发警告C4293(移位计数负或太大,未定义的行为)在vc++ 15对mask<64>::value;,因为它仍然触发第二个分支的三元操作符-即使它不应该影响值本身。有什么更好、更干净的方法来实现这个目标呢?

// Bitmask of 'width' bits shifted 'shift' bits to the left
// For instance, mask<16,8> := 0x00FFFF00 
template <uint8_t width, uint8_t shift=0>
struct mask {
    static const uintmax_t value = (width >= (sizeof(uintmax_t)<<3)) ?
            (~0 << shift) : (((uintmax_t(1)<<width)-1) << shift) ;
    mask()=delete;
};
// A bitmask for a type, for instance, 0xFF for uint8_t
template <class T>
struct typeMask {
    static const uintmax_t value = mask<sizeof(T)<<3>::value;
    typeMask()=delete;
};

您希望避免编译条件的冗余分支width >= (sizeof(uintmax_t)<<3)。我家里只有gcc 5.1和clang 3.6但是我希望vc++ 2015也能让你这样做:

#include <cstdint>
#include <type_traits>
template <uint8_t width, uint8_t shift=0, typename Enable = void>
struct mask;
template <uint8_t width, uint8_t shift> struct 
mask<width,shift,typename std::enable_if<(width >= (sizeof(uintmax_t)<<3))>::type> 
{
    static const uintmax_t value = (~0 << shift);
    mask()=delete;
};
template <uint8_t width, uint8_t shift> struct 
mask<width,shift,typename std::enable_if<(width < (sizeof(uintmax_t)<<3))>::type> 
{
    static const uintmax_t value = (((uintmax_t(1)<<width)-1) << shift);
    mask()=delete;
};
template <class T>
struct typeMask {
    static const uintmax_t value = mask<sizeof(T)<<3>::value;
    typeMask()=delete;
};

顺便说一下,编译mask<64>::value, clang抱怨:

warning: in-class initializer for static data member is not a constant expression; folding it to a constant is a GNU extension [-Wgnu-folding-constant]
static const uintmax_t value = (~0 << shift);
                               ~~~~^~~~~~~~~

您可以通过将~0替换为~uintmax_t(0)来纠正它的抱怨。