Is there a way to trigger a compilation failure in such a scenario?
If the goal is to trigger a compilation failure, then the easiest thing to do is to throw an exception. Doesn't matter what the exception is, since it won't actually be thrown, it's the act of throwing an exception that will trigger a compile error because throwing is not allowed at constant evaluation time:
template <size_t TSize>
consteval size_t indexOf(SomeEnum someEnum,
const std::array<SomeEnum, TSize> &arr) {
for (size_t i = 0; i < TSize; ++i) {
if (arr[i] == someEnum) {
return i;
}
}
throw "failed to find someEnum";
}
If you want to be more explicit, you can just have a non-constexpr
function without a definition:
void trigger_consteval_failure(char const*);
template <size_t TSize>
consteval size_t indexOf(SomeEnum someEnum,
const std::array<SomeEnum, TSize> &arr) {
for (size_t i = 0; i < TSize; ++i) {
if (arr[i] == someEnum) {
return i;
}
}
trigger_consteval_failure("failed to find someEnum");
}
In both cases, if you're looking for a value that is in the array, invoking this function is a valid constant expression. But if the index is not found, then we end up doing something that's now allowed in constant expressions and that's a hard compile error regardless, as desired.
It'd be nice if we could produce a better stack trace in this case, but I don't think there's actually a way to do that.