有条件地static_assert函数是否称为constexpr



我知道有一个关于constexpr((运算符的建议,但这还没有在gcc/clang中实现。我也知道使用一些技巧,如机器代码编辑:

http://saadahmad.ca/detecting-evaluation-context-inside-constexpr-functions/

我想知道是否有一个有点有限的解决方案:

struct F {
    constexpr F(int v) {
         if constexpr(constexpr()) {
             static_assert(v > 0);
         }
         else {
             assert(v > 0);
         }
    }
};
// ...
constexpr F f{0}; // should trigger a compile-time error

我知道static_assert不能以这种方式使用,但这只是为了澄清问题。

在你的特定情况下,你可以只保留断言 - 当条件错误时,它将阻止编译,因为断言处理程序是非 constexpr:

#include <cassert>
struct F {
    constexpr F(int v) {
         assert(v >0);
    }
};
// ...
constexpr F f1{0}; // doesn't compile in debug
constexpr F f2{1}; // compiles

但是,这不会在发布中触发编译时错误。这可以通过做出自己的断言并添加对一些非 constepxr 函数的调用来解决:

#include <cassert>
// some non-constexpr function
void AssertConditionFailed()
{
}
#define ASSERT_WIH_COMPILE_TIME_CHECK(...) 
    assert(__VA_ARGS__); 
    if (!(__VA_ARGS__)) 
    { 
        AssertConditionFailed(); 
    }
struct F {
    constexpr F(int v) {
         ASSERT_WIH_COMPILE_TIME_CHECK(v >0);
    }
};
// ...
constexpr F f1{0}; // doesn't compile
constexpr F f2{1}; // compiles

不是以如此直接的方式,因为根本不允许static_assert,同样尝试使用 v 作为模板参数也会失败,因此不使用enable_if类型解决方案。

出于错误的目的,如果 constexpr 导致异常,您将收到编译错误。

您可以使用宏,例如 assert(自 C++14 起允许(,允许在发布版本中对其进行优化并保留原始调试运行时行为。

constexpr int foo(int v)
{
    if (v < 0) throw std::invalid_argument("invalid v");
    return v * 2;
}
int main() {
    int a = -1;
    int a2 = foo(a); // Not evaluated at compile time
    constexpr int b = foo(2);
    constexpr int c = foo(-1); // ERROR
}

最新更新