如何使 consteval 函数失败?
How to fail a consteval function?
我有以下功能:
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;
}
}
// How to fail here?
return SOME_DEFAULT_WRONG_VALUE;
}
函数应该失败而不是返回默认值,但我无法抛出异常或调用 assert
。我可以在每次调用该函数时添加一个 static_assert
(使用宏它会不那么可怕),但我更喜欢在函数中工作的解决方案。有没有办法在这种情况下触发编译失败?
您应该避免使用索引,而是使用 std::find
,现在是 constexpr
。如果你想要一个索引,你可以只使用数组的 begin
ing 中的指针算术减法来计算索引。
但是,如果你做不到,那就return TSize
;它应该像结束迭代器一样工作。
您可以简单地省略 return
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;
}
}
}
Demo(clang 警告该方法)。
编译器会拒绝到达该路径的代码。
throw
异常似乎更干净:
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 42; // or more meaningful exception
}
Is there a way to trigger a compilation failure in such a scenario?
如果目标是触发编译失败,那么最简单的事情就是抛出异常。不管异常是什么,因为它实际上不会被抛出,它是抛出异常的行为会触发编译错误,因为在常量评估时间不允许抛出:
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";
}
如果你想更明确一点,你可以只使用一个没有定义的非constexpr
函数:
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");
}
在这两种情况下,如果您要在数组中查找 是 的值,则调用此函数是一个有效的常量表达式。但是,如果索引 not found,那么我们最终会做一些现在在常量表达式中允许的事情,无论如何,这都是一个硬编译错误,正如所希望的那样。
如果我们能在这种情况下生成更好的堆栈跟踪,那就太好了,但我认为实际上没有办法做到这一点。
我有以下功能:
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;
}
}
// How to fail here?
return SOME_DEFAULT_WRONG_VALUE;
}
函数应该失败而不是返回默认值,但我无法抛出异常或调用 assert
。我可以在每次调用该函数时添加一个 static_assert
(使用宏它会不那么可怕),但我更喜欢在函数中工作的解决方案。有没有办法在这种情况下触发编译失败?
您应该避免使用索引,而是使用 std::find
,现在是 constexpr
。如果你想要一个索引,你可以只使用数组的 begin
ing 中的指针算术减法来计算索引。
但是,如果你做不到,那就return TSize
;它应该像结束迭代器一样工作。
您可以简单地省略 return
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;
}
}
}
Demo(clang 警告该方法)。
编译器会拒绝到达该路径的代码。
throw
异常似乎更干净:
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 42; // or more meaningful exception
}
Is there a way to trigger a compilation failure in such a scenario?
如果目标是触发编译失败,那么最简单的事情就是抛出异常。不管异常是什么,因为它实际上不会被抛出,它是抛出异常的行为会触发编译错误,因为在常量评估时间不允许抛出:
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";
}
如果你想更明确一点,你可以只使用一个没有定义的非constexpr
函数:
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");
}
在这两种情况下,如果您要在数组中查找 是 的值,则调用此函数是一个有效的常量表达式。但是,如果索引 not found,那么我们最终会做一些现在在常量表达式中允许的事情,无论如何,这都是一个硬编译错误,正如所希望的那样。
如果我们能在这种情况下生成更好的堆栈跟踪,那就太好了,但我认为实际上没有办法做到这一点。