【发布时间】:2014-01-19 03:36:36
【问题描述】:
在计算常量表达式以初始化 constexpr 时,可能会引发异常。例如,这里是一个常量表达式的计算防止溢出的例子:
#include <iostream>
#include <stdexcept>
constexpr int g(int n, int n0, int n1) {
return n == 0? n1: g(n - 1, n1, n0 + n1);
}
constexpr int f(int n) {
return n < 42? g(n, 0, 1): throw std::out_of_range("too big");
}
int main()
{
try {
constexpr int f41 = f(41); // OK: constexpr
int f43 = f(43); // OK: throws an exception
constexpr int f42 = f(42); // not OK but what happens?
}
catch (std::exception const& ex) {
std::cout << "ERROR: " << ex.what() << "\n";
}
}
第一次调用f() 只是表明可以计算出constexpr。对f() 的第二次调用不用于初始化constexpr 并引发运行时异常。对f() 的第三次调用用于初始化constexpr,但由于引发了异常,因此永远不会到达该点。但是,在这种情况下应该怎么办?我希望catch-clause 中的处理程序被执行,但gcc 和clang 都会产生编译时错误。
【问题讨论】:
-
你最近没有问过类似的问题吗? throw-expression 的求值不是简单地使求值的 constexpr 函数成为 not-a-constant-expression 吗?
-
我认为[expr.const] / 2适用:条件表达式不是 i>如果它包含“带有参数的@ 987654333函数的调用,则核心常量表达式,当被函数调用替换时,不产生核心常量表达式;"
-
@DyP:我之前询问过throwing from the ternary operator,并考虑到
constexprs。但是,当他们被抛出并捕获时,我没有预计会导致编译时间错误:毕竟,永远不会达到constexpr的初始化... span> -
我只想说初始化器不是一个常量表达式,因此格式错误。至少我是这么理解的。请注意,[expr.const] 包含一个将 constexpr 函数解析为非常量表达式的示例。
-
也许我把问题简单化了,但我发现 clang++ 错误
test.cpp:17:23: error: constexpr variable 'f42' must be initialized by a constant expression相当清楚......?
标签: c++ exception c++11 language-lawyer constexpr