据我所知,constexpr函数可以在编译时和运行时执行,具体取决于整个评估是否可以在编译时完成。
但是,您不能重载此函数以使其具有运行时和编译时对应。
所以我的问题是,我如何设置运行时断言以确保运行时函数的执行与我的static_assert一起传递有效参数?
答案 0 :(得分:5)
Eric Niebler在Assert and Constexpr in C++11中很好地介绍了这个问题,他指出在C ++ 11中不允许在constexpr函数中使用assert但是在C ++ 14中允许使用assert( {{3 }} )并提供以下代码段:
constexpr bool in_range(int val, int min, int max)
{
assert(min <= max); // OOPS, not constexpr
return min <= val && val <= max;
}
如果我们必须支持C ++ 11,那么有一些替代方案。显而易见的是使用throw,但是当他指出这会将应该是一个不可恢复的错误变成可恢复的错误,因为你可以捕获异常。
他建议了一些替代方案:
将throw与As part of the Relaxing constraints on constexpr functions proposal:
一起使用constexpr bool in_range(int val, int min, int max) noexcept
{
return (min <= max)
? min <= val && val <= max
: throw std::logic_error("Assertion failed!");
}
如果异常离开函数std :: terminate将被调用。
从异常类型的构造函数中调用noexcept specifier:
struct assert_failure
{
explicit assert_failure(const char *sz)
{
std::fprintf(stderr, "Assertion failure: %s\n", sz);
std::quick_exit(EXIT_FAILURE);
}
};
constexpr bool in_range(int val, int min, int max)
{
return (min <= max)
? min <= val && val <= max
: throw assert_failure("min > max!");
}
将断言的lambda表达式传递给异常类型的构造函数:
constexpr bool in_range(int val, int min, int max)
{
return (min <= max)
? min <= val && val <= max
: throw assert_failure(
[]{assert(!"input not in range");}
);
}
答案 1 :(得分:1)
您可以抛出异常。如果在编译时从constexpr函数抛出异常,它基本上算作失败的静态断言。如果它在运行时发生,它将像往常一样例外。
此问题显示了发生这种情况的代码示例:Passing constexpr objects around
还相关:What happens when an exception is thrown while computing a constexpr?