我想创建一个静态分配 2^N 字节数组的结构,但我不希望该结构的用户指定此大小作为指数。示例:
my_stupid_array<char, 32> a1; // I want this!
my_stupid_array<char, 5> a2; // And not this...
如何检查此模板参数是否为 2 的幂并通过一条不错的消息警告用户?
我已经能够使用一个简单的模板来检查这一点:
template<int N>
struct is_power_of_two {
enum {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);
};
错误
..\main.cpp:29:1: error: invalid application of 'sizeof' to incomplete type 'boost::STATIC_ASSERTION_FAILURE<false>'
编辑
哦,我明白了。这是断言失败时我应该收到的消息。但这未能给用户一些理智的信息。 :(
这些天,有了
constexpr
和 一些小小的技巧,你就可以
constexpr bool is_powerof2(int v) {
return v && ((v & (v - 1)) == 0);
}
static_assert 来救援(仅限 C++11,对于 C++03 取消注释 BOOST_STATIC_ASSERT):
#include<iostream>
// #include <boost/static_assert.hpp>
template<int N>
struct is_power_of_two {
enum {val = N && !(N & (N - 1))};
static_assert(val, "should use a power of 2 as template parameter");
// BOOST_STATIC_ASSERT(val); // without C++11 support, won't take a string message
};
int main()
{
std::cout << is_power_of_two<2>::val << "\n";
std::cout << is_power_of_two<3>::val << "\n";
}
更新1:其他想法(我知道你不想要这个,但对于大指数来说要容易得多):
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
更新2:根据@sehe在聊天中的评论,您也可以对
constexpr
功能执行此操作
constexpr bool is_power_of_two(int x)
{
return x && ((x & (x-1)) == 0);
}
您可以使用
static_assert
提供错误消息:
template<int N>
struct is_power_of_two {
static_assert((N > 1) & !(N & (N - 1)), "Template parameter must be a power of two.");
};
我知道这是一个老问题,但我想根据上面的答案(谢谢你顺便说一句!)提出我刚刚使用的另一个选项以及 c++20 概念:
template<auto V>
constexpr bool is_power_of_two = V && ((V & (V - 1)) == 0);
template<class T, auto SIZE> requires is_power_of_two<SIZE>
using my_stupid_array = std::array<T, SIZE>;
my_stupid_array<char, 32> a1; // FINE
my_stupid_array<char, 5> a1; // COMPILER ERROR