Given a constexpr function, is there a way to create a compile-time error if the function is called at compile-time and return a sentinel value if the function is called at runtime?
I unfortunately can't use exceptions since they are disabled in the build.
This would be used mostly for converting to and from enums and to and from strings. If the developers enter incorrect values, it would be nice to fail the build rather than hope they see the error at runtime, but since we can get values from unknown sources, there is a chance that the value wouldn't be valid and we don't want to crash at runtime.
Demo use-case:
#include <fmt/core.h>
#include <iostream>
// from: https://stackoverflow.com/a/63529662/4461980
// if C++20, we will need a <type_traits> include for std::is_constant_evaluated
#if __cplusplus >= 202002L
#include <type_traits>
#endif
constexpr bool is_constant_evaluated() {
#if __cplusplus >= 202002L
return std::is_constant_evaluated();
#elif defined(__GNUC__) // defined for both GCC and clang
return __builtin_is_constant_evaluated();
#else
// If the builtin is not available, return a pessimistic result.
// This way callers will implement everything in a constexpr way.
return true;
#endif
}
enum class MyEnum { A, B, C, END_OF_ENUM };
constexpr const char* ToString(MyEnum value) {
switch (value) {
case MyEnum::A: {
return "A";
}
case MyEnum::B: {
return "B";
}
case MyEnum::C: {
return "C";
}
case MyEnum::END_OF_ENUM:
default: {
if (is_constant_evaluated()) {
// compile time error?
return "test";
} else {
return "UNKNOWN";
}
}
}
// unreachable?
return "";
}
int main(int argc, char** argv) {
// strcitly-speaking not UB since 5 is 0b101 in binary which does not use more bits than the
// highest item which would have value 4 which would be 0b100
// for demo purposes only, don't scream at me
constexpr auto stringified = ToString(static_cast<MyEnum>(5));
fmt::print("{}\n", stringified); // prints "test"
fmt::print("{}\n", ToString(static_cast<MyEnum>(5))); // prints "UNKNOWN"
}
godbolt: https://godbolt.org/z/nYora1b6M