启用静态检查以进行持续评估
Enable static checks for constant evaluation
如果一个类型是用常量初始化的,我喜欢进行某种静态(编译时)检查。
下面是测试代码。
类型 C 只是一个测试,以查看 if/when 触发常量计算。
D型更像是我想做的真实例子:
运行时:如果 D 用错误的值初始化,该值可能会有所限制,或者应该触发运行时断言
编译时:如果 D 用错误的值初始化,编译应该会失败。
我找不到解决方案。
代码:
#include <cassert>
#include <type_traits>
inline void constant_assert() {}
struct C {
constexpr C() {
if (std::is_constant_evaluated()) {
constant_assert();
}
}
};
struct D {
constexpr D(const char v) {
if (std::is_constant_evaluated()) {
//static_assert(v < 10); // not callable
if (v >= 10) {
constant_assert();
}
}
else {
assert(v < 10);
}
}
};
int main() {
C t0; // does not trigger the check
// constexpr C t1; // triggers the check: ok
D d{42}; // runtime assert, but should be compiletime error!
}
以上CE中的代码:https://godbolt.org/z/16GTx797q
你可以简单地这样做:
struct D {
constexpr D(const char v) {
assert(v < 10);
}
};
- 如果
D
在运行时赋值错误,将在运行时触发assert
。
- 如果
D
在编译时被赋予了错误的值,那么它将发生 编译时错误 因为 assert
不满足。
D d{42}; // runtime assert, but should be compiletime error!
以你想要的方式,这是不可能的。你的方法很好——如果你的参数要被不断评估,做constexpr D d{42}
。请参阅 is_constant_evaulated
的解释 - 我找到了 https://gist.github.com/Som1Lse/5309b114accc086d24b842fd803ba9d2。
您可以使用 gcc 扩展 __builtin_constant_p
调用带有错误属性的函数(并且可能需要启用优化)。此方法通常由库实现在 C 中使用 - 请参阅 glibc
.
中的 _FORTIFY_LEVEL
#include <cassert>
#include <type_traits>
__attribute__((__error__("Och nooo")))
void undefined_function();
struct D {
constexpr D(const int v) {
if (__builtin_constant_p(v)) {
if (v >= 10)
undefined_function();
} else {
assert(v < 10);
}
}
};
int main(int argc, char *argv[]) {
D d1{42};
}
如果一个类型是用常量初始化的,我喜欢进行某种静态(编译时)检查。
下面是测试代码。 类型 C 只是一个测试,以查看 if/when 触发常量计算。
D型更像是我想做的真实例子:
运行时:如果 D 用错误的值初始化,该值可能会有所限制,或者应该触发运行时断言
编译时:如果 D 用错误的值初始化,编译应该会失败。
我找不到解决方案。
代码:
#include <cassert>
#include <type_traits>
inline void constant_assert() {}
struct C {
constexpr C() {
if (std::is_constant_evaluated()) {
constant_assert();
}
}
};
struct D {
constexpr D(const char v) {
if (std::is_constant_evaluated()) {
//static_assert(v < 10); // not callable
if (v >= 10) {
constant_assert();
}
}
else {
assert(v < 10);
}
}
};
int main() {
C t0; // does not trigger the check
// constexpr C t1; // triggers the check: ok
D d{42}; // runtime assert, but should be compiletime error!
}
以上CE中的代码:https://godbolt.org/z/16GTx797q
你可以简单地这样做:
struct D {
constexpr D(const char v) {
assert(v < 10);
}
};
- 如果
D
在运行时赋值错误,将在运行时触发assert
。 - 如果
D
在编译时被赋予了错误的值,那么它将发生 编译时错误 因为assert
不满足。
D d{42}; // runtime assert, but should be compiletime error!
以你想要的方式,这是不可能的。你的方法很好——如果你的参数要被不断评估,做constexpr D d{42}
。请参阅 is_constant_evaulated
的解释 - 我找到了 https://gist.github.com/Som1Lse/5309b114accc086d24b842fd803ba9d2。
您可以使用 gcc 扩展 __builtin_constant_p
调用带有错误属性的函数(并且可能需要启用优化)。此方法通常由库实现在 C 中使用 - 请参阅 glibc
.
_FORTIFY_LEVEL
#include <cassert>
#include <type_traits>
__attribute__((__error__("Och nooo")))
void undefined_function();
struct D {
constexpr D(const int v) {
if (__builtin_constant_p(v)) {
if (v >= 10)
undefined_function();
} else {
assert(v < 10);
}
}
};
int main(int argc, char *argv[]) {
D d1{42};
}