I like to have some sort of static (compile-time) check, if a type is initialised with a constant.
Below is a test code. The type C is just a test to see if/when constant-evaluation is triggered.
The type D is more to be a real example of what I want to do:
Runtime: if D is initialized with the wrong value, the value might be clamped somewhat or a runtime-assertion should trigger
Compiletime: if D is initialized with the wrong value, the compilation should fail.
I can't find a solution for that.
The code:
#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!
}
The above code in CE: https://godbolt.org/z/16GTx797q
D d{42}; // runtime assert, but should be compiletime error!
In the way you want it, it is not possible. Your method is fine - if your arguments are to be constant evaluated, do constexpr D d{42}
. See explanation of is_constant_evaulated
- I found https://gist.github.com/Som1Lse/5309b114accc086d24b842fd803ba9d2.
You can use the gcc extension __builtin_constant_p
calling a function with an error attribute (and optimizations maybe are needed to be enabled). This method is typically used in C by library implementations - see _FORTIFY_LEVEL
in glibc
.
#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};
}