c++ - 模板结构的静态常量成员的不同值

标签 c++ c++11 metaprogramming

我正在尝试制作一个小型元编程结构,它生成 width 的位掩码位移位 shift左侧位置(主要用于学习目的)。以下代码在 VC++15 上针对 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) .

关于c++ - 模板结构的静态常量成员的不同值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33301499/

相关文章:

C++11 static_assert(以及其中使用的函数)

c# - 可以在编译时评估 C# 自定义属性吗?

c++ - Variadic 模板候选者不匹配

ruby-on-rails - 使用 define_method 动态定义 setter 方法?

c++ - 函数指针类型定义错误

c++ - 在 Widget 之间传输 std::unique_ptr

c++ - 如果在 C++ 中禁用指针,最严重的问题是什么?

c++ - 如何为我的 Apache 模块定义自定义配置指令?

c++ - 具有不完整类型的图/树实现

c++ - 尝试在类成员初始化中使用 vector 的填充构造函数失败。怎么了?