繁体   English   中英

如果表达式是constexpr,则为static_assert

[英]static_assert if expressions is constexpr

我想创建一个类模板

template <class T>
class X {
  // here I'll use T::value (among other things)
};

T::value通常是constexpr静态变量,但并非总是如此。 T::value必须是正值,所以我希望在编译期间让人们知道它,如果可能的话。

如果T::value总是constexpr,我会添加static_assert类的

static_assert(T::value > 0, "need positive number");

是否可以仅在T::value constexpr的情况下添加此static_assert?

我们可以编写一个带有两个重载的is_valid模板函数(提出一个更好的名称):

template <typename T, int N = T::value>
constexpr bool is_valid(int) {
    return N > 0;
}

template <typename T>
constexpr bool is_valid(...) {
    return true;
}

第一个重载只有在T::value是常量表达式时才有效,否则它将是SFINAEd out。 无论如何,第二个重载都是有效的,因此我们使用dummy int参数消除了重载的歧义。

现在我们测试它是这样的:

static_assert(is_valid<T>(0), "need positive number");

现场演示

这对clang ++有用:

#include <type_traits>

// The default case, returns true if the value is not constant.
template <typename T, typename = void>
struct IsNonConstantOrPositive {
    static const bool value = true;
};

// The `constexpr` case. We check if we can evaluate `T::value == 0` which can only
// be evaluated at compile-time if `T::value` is constant. The whole `enable_if` thing
// is to provide a substitution to ensure SFINAE.
template <typename T>
struct IsNonConstantOrPositive<T, typename std::enable_if<T::value==0||true>::type> {
    static const bool value = T::value > 0;
};

template <typename T>
struct X {
    static_assert(IsNonConstantOrPositive<T>::value, "T::value should be positive");
};

例:

struct A {  // const > 0, should succeed
    static const int value = 123;
};

struct B {  // const <= 0, should fail
    static const int value = -1234;
};

struct C {   // non-const, should succeed
    static int value;
};

int main() {
    X<A> a;     // ok
    //X<B> b;   // error
    X<C> c;     // ok
}

我认为对变量的const(expr)进行测试会很好,如下所示:

struct T {
    ...
    static_assert(!IS_CONSTANT_VAR(value) || value > 0, "trouble is afoot");
};

下面的实现使用类似于kennytm解决方案的策略来对非常量引用进行失败。 它适用于Clang和GCC。

#include <type_traits> // enable_if

template<typename T, T& var, typename = void> struct is_constant_var_impl {
    static constexpr bool value = false;
};
template<typename T, T& var>
struct is_constant_var_impl <T, var, typename std::enable_if<(double)var == (double)var>::type> {
    // (double) cast above to thwart GCC's agressive constant folding;
    // perhaps could be removed with a bit more finesse
    static constexpr bool value = true;
};
#define IS_CONSTANT_VAR(...) (is_constant_var_impl<decltype(__VA_ARGS__), (__VA_ARGS__)>::value)

优点

  • 模板可以跨不同的类或静态成员名称重用
  • static_assert自解释代码

缺点

  • 在MSVC中不起作用
  • (也许?)使用C ++ 14

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM