C++ - 检查所有模板参数是否为2的幂

Tom*_*omW 3 templates variadic constexpr c++11

我试图找到一种简单的方法来检查作为模板参数传递的参数是否都是2的幂.我在网站上找到了一个bithack,我有这个:

constexpr bool isPowerOf2(size_t value){
return !(value == 0) && !(value & (value - 1));
}
Run Code Online (Sandbox Code Playgroud)

这适用于单个值,但将此应用于多个参数看起来很难看.

static_assert(isPowerOf2(Arg1), "Argument must be a power of 2");
static_assert(isPowerOf2(Arg2), "Argument must be a power of 2");
static_assert(isPowerOf2(Arg3), "Argument must be a power of 2");
Run Code Online (Sandbox Code Playgroud)

如果我能让它看起来像arePowersOf2(Arg1,Arg2,Arg3)会更好,但是我并不是真的在模板魔术方面先进.所以我的问题是:有一种简单的方法吗?我更喜欢constexpr C++ 11解决方案.

Tar*_*ama 7

您可以编写一个conjunction特征来检查bool参数包中是否包含所有s true.这个例子使用了@Columbobool_pack诀窍:

template <bool...> struct bool_pack{};
template <bool... bools> 
struct conjunction : std::is_same<bool_pack<true, bools...>,
                                  bool_pack<bools..., true>>
{};

template <size_t... Args>
constexpr bool arePowerOf2() {
    return conjunction<isPowerOf2(Args)...>::value;   
}
Run Code Online (Sandbox Code Playgroud)

然后你会这样称呼它:

arePowerOf2<Args...>();
arePowerOf2<Arg1, Arg2, Arg3>();
Run Code Online (Sandbox Code Playgroud)

Live Demo


在C++ 1z中,您可以使用折叠表达式:

template <size_t... Args>
constexpr bool arePowerOf2() {
    return (... && isPowerOf2(Args));
}
Run Code Online (Sandbox Code Playgroud)

C++ 1z也会得到std::conjunction,这与上面的版本略有不同.