【问题标题】:How do I check if a template parameter is a power of two?如何检查模板参数是否为 2 的幂?
【发布时间】:2012-05-14 14:35:39
【问题描述】:

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

编辑

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

【问题讨论】:

  • 8 是 2 的幂...
  • 它是指数作为参数的一个例子。 2^8 = 256
  • >my_stupid_array&lt;char, 8&gt; a2; // And not this... 为什么不这样呢?
  • @jrok:我意识到这一点,但重点仍然存在......
  • @triclosan 可能是这样,但它不直观,因为我不那么着急,我想我可以问并学习一些新的东西。 :)

标签: c++ templates c++11 constexpr static-assert


【解决方案1】:

如今,使用 constexprbit twiddling hacks 您可以

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

【讨论】:

  • 这才是真正的解决方案。
【解决方案2】:

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

Ideone output for C++11

Ideone output for C++03

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

UPDATE2:基于 @sehe 在聊天中的 cmets,您也可以为 constexpr 函数执行此操作

constexpr bool is_power_of_two(int x)
{
    return x && ((x & (x-1)) == 0);
}

【讨论】:

  • 打败我。不妨提一下 C++03 的 BOOST_STATIC_ASSERT。
  • 该死的。正要给this link。我必须学会更快地打字。
  • 我的嵌入式编译器还不支持 C++11。如果可行,我将尝试使用 boost 替代方案并将其添加到答案中。
  • BOOST_STATIC_ASSERT 只接受一个参数。另外,我遇​​到了一个编译错误,我正在尝试解决它。会更新问题。
  • 您始终可以使用BOOST_STATIC_ASSERT 来包含一条消息:BOOST_STATIC_ASSERT(val &amp;&amp; "This is SO wrong!")。 (对于那些想知道的人:布尔上下文中的字符串文字评估指向始终非零的文字的指针,即真)
【解决方案3】:

您可以使用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.");
};

【讨论】:

猜你喜欢
  • 2016-10-03
  • 1970-01-01
  • 1970-01-01
  • 2010-10-10
  • 2020-11-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多