模板结构的静态常量成员的不同值
Different values of a static const member of a template struct
我正在尝试制作一个小型元编程结构,该结构生成 width
位的位掩码,向左移动 shift
个位置(主要用于学习目的)。以下代码在 VC++15 for mask<64>::value;
上触发警告 C4293(移位计数负数或太大,未定义的行为),因为它仍然触发三元运算符的第二个分支 - 即使它不应该影响价值本身。实现此目标的更好、更简洁的方法是什么?
// 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)
来纠正它的抱怨。
我正在尝试制作一个小型元编程结构,该结构生成 width
位的位掩码,向左移动 shift
个位置(主要用于学习目的)。以下代码在 VC++15 for mask<64>::value;
上触发警告 C4293(移位计数负数或太大,未定义的行为),因为它仍然触发三元运算符的第二个分支 - 即使它不应该影响价值本身。实现此目标的更好、更简洁的方法是什么?
// 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)
来纠正它的抱怨。