C++ 如何检查模板参数是否为2的幂?

C++ 如何检查模板参数是否为2的幂?,c++,templates,c++11,constexpr,static-assert,C++,Templates,C++11,Constexpr,Static Assert,我想创建一个静态分配2^N字节数组的结构,但我不希望此结构的用户将此大小指定为指数。例如: my_stupid_array<char, 32> a1; // I want this! my_stupid_array<char, 5> a2; // And not this... 我的愚蠢数组a1;//我想要这个! 我的愚蠢数组a2;//而不是这个。。。 如何检查此模板参数是否为二次幂和向用户发出有关此问题的警告 我已经能够通过一个简单的模板来检查这一点: templa

我想创建一个静态分配2^N字节数组的结构,但我不希望此结构的用户将此大小指定为指数。例如:

my_stupid_array<char, 32> a1; // I want this!
my_stupid_array<char, 5> a2; // And not this...
我的愚蠢数组a1;//我想要这个!
我的愚蠢数组a2;//而不是这个。。。
如何检查此模板参数是否为二次幂
和向用户发出有关此问题的警告

我已经能够通过一个简单的模板来检查这一点:

template<int N>
struct is_power_of_two {
    enum {val = (N >= 1) & !(N & (N - 1))};
};
模板
结构是二的幂{
枚举{val=(N>=1)&!(N&(N-1))};
};
但是,我无法用一条正常的消息来警告用户。有什么想法吗

编辑

修正了模棱两可的例子

编辑

1确实是2的幂。修正了!:)

编辑

使用BOOST_STATIC_ASSERT,我得到了GCC代码的编译错误:

template<int N>
struct is_power_of_two {
    enum {val = (N >= 1) & !(N & (N - 1))};
    BOOST_STATIC_ASSERT(val);
};
模板
结构是二的幂{
枚举{val=(N>=1)&!(N&(N-1))};
BOOST_STATIC_ASSERT(val);
};
错误

。\main.cpp:29:1:错误:“sizeof”对不完整类型“boost::STATIC\u断言\u失败”的应用无效

编辑


哦,我明白了。这就是当断言失败时我应该得到的消息。但这并没有给用户一些合理的信息:(

static\u assert to the rescue(仅限C++11,取消C++03的BOOST\u static\u assert注释):


您可以使用
static\u assert
提供错误消息:

template<int N>
struct is_power_of_two {
    static_assert((N > 1) & !(N & (N - 1)), "Template parameter must be a power of two.");
};
模板
结构是二的幂{
静态断言((N>1)&!(N&(N-1)),“模板参数必须是二的幂。”);
};

现在,使用
constexpr

constexpr bool is_powerof2(int v) {
    return v && ((v & (v - 1)) == 0);
}

8是2的幂…它是指指数作为参数的一个例子。2^8=256>
我的愚蠢数组a2;//而不是这个…
为什么不是这个?@jrok:我意识到,但重点仍然是…@triclosan可能是这样的,但它不是直观的,因为我不急,我想我可以问一些新的问题并学到一些新的东西。:)快来吧。不妨提及C++03.Damnit的BOOST\u STATIC\u断言。就要给了。我必须学会更快地打字。我的嵌入式编译器还不能完成C++11。我将尝试boost替代方案,并将其添加到答案中(如果可行)。boost\u STATIC\u ASSERT只接受一个参数。另外,我得到了一个编译错误,我正试图找出它。要更新问题。使用
BOOST\u STATIC\u ASSERT
始终可以包含以下消息:
BOOST\u STATIC\u ASSERT(val&&“这太错误了!”)
。(对于那些想知道:布尔上下文中的字符串文本计算指向该文本的指针,该文本始终为非零,即true)+1位旋转技巧:。根据
constexpr
:N>1应该是N>0,因为1是2^0。这是真正的解决方案。
template<int N>
make_power_of_two
{
    enum { val = 1 << N };
};

my_stupid_array<char, make_power_of_two<5>::val > a1; // size 2^5 = 32
constexpr bool is_power_of_two(int x)
{
    return x && ((x & (x-1)) == 0);
}
template<int N>
struct is_power_of_two {
    static_assert((N > 1) & !(N & (N - 1)), "Template parameter must be a power of two.");
};
constexpr bool is_powerof2(int v) {
    return v && ((v & (v - 1)) == 0);
}