有条件地 static_assert 如果函数被调用 constexpr
Conditionally static_assert if function is called 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不能这样用,但这只是为了说明问题。
不能以这种直接的方式,因为 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
}
在您的特定情况下,您可以只保留断言 - 它会在条件错误时阻止编译,因为断言处理程序是非 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
我知道有人提议使用 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不能这样用,但这只是为了说明问题。
不能以这种直接的方式,因为 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
}
在您的特定情况下,您可以只保留断言 - 它会在条件错误时阻止编译,因为断言处理程序是非 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