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.
assert
? – Isomerousconsteval
. – Amyloidassert
in a constant expression context. – Narratethrow
from aconstexpr
. I'm not familiar enough withconsteval
to be certain, but I believe you should be able tothrow
from them as well. – Karimakarinconsteval
or if you have an external requirement that you not usethrow
? – Karimakarinthrow
in aconstexpr
function. You cannot execute anythrow
statements in constant evaluation; that causes a compile error.consteval
only forces any calls to the function to be constant expressions; it doesn't change how they operate. So the standard rules ofconstexpr
apply. – Narrateconsteval
to produce a hard error when that code path is executed? – Isomerousassert
. – Narrateassert
should work as intended, even in an executed code path, as of C++17. I actually thought it was since C++14, but I guess either works in a C++20 context. Standardwise, that blurb is in [assertions.assert]. – Isomerousconsteval
, it is not thrown at runtime. – Faunia