17

我想创建一个静态分配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>' 

http://ideone.com/cMfEf

编辑

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

4

3 回答 3

23

这些天来,你可以constexpr使用一些小技巧

constexpr bool is_powerof2(int v) {
    return v && ((v & (v - 1)) == 0);
}
于 2013-10-16T09:16:37.310 回答
22

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";
}

C++11 的 Ideone 输出

C++03 的 Ideone 输出

UPDATE1:其他想法(我知道你不想要这个,但对于大指数来说要容易得多):

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);
}
于 2012-05-14T14:40:52.623 回答
11

您可以使用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.");
};
于 2012-05-14T14:41:24.917 回答