函数的条件评估
好吧,这可能是一个愚蠢的问题,但我完全不明白章节12.1.6.2 - 在C++编程语言的constexpr函数下的条件评估。这是整个很短的文字。函数的条件评估
不评估不在constexpr 函数中采用的条件表达式的分支。这意味着没有采取的分支可以运行时评估 。例如:
constexpr int check(int i) { return (low<=i && i<high) ? i : throw out_of_range(); } constexpr int low = 0; constexpr int high = 99; // ... constexpr int val = check(f(x,y,z));
你可能想象低,高到被 在编译时已知的配置参数,而不是在设计时,和F(X,Y,Z) 计算一些依赖于实现值。
我试图运行上面的代码,试图更多的解释理解,但我得到一个错误。有人可以提供更清晰的解释吗?
编辑:我创建了一个程序来测试这一点:
#include<iostream>
#include<stdexcept>
using namespace std;
constexpr int low = 0;
constexpr int high = 99;
constexpr int check(int i) {
return (low<=i && i<high) ? i : throw out_of_range();
}
constexpr int f(int x, int y, int z) {
return x*y*z;
}
int main() {
constexpr int val = check(f(2,2,2));
cout << val << '\n';
}
它将无法运行:
no matching function for call to 'std::out_of_range::out_of_range()' //I'm really surprised at this
return (low<=i && i<high) ? i : throw out_of_range();
error: body of constexpr function 'constexpr int check(int)' not a return-statement
}
error: 'constexpr int check(int)' called in a constant expression
constexpr int val = check(f(2,2,2));
这意味着在constexpr功能的条件分支被允许使用非常量表达式(即那些需要运行时评估的表达式,例如抛出异常),只要在常量表达式上下文中调用该函数时从不采用该分支。
因此,只要函数的参数是常量表达式,并且条件(low<=i && i<high)
为true,就可以调用check
来初始化constexpr
变量val
。
如果参数不是常量,函数调用不是常量表达式,因此不能初始化变量constexpr
。
如果条件为false,则函数需要接受假分支,该分支需要抛出异常,这需要运行时评估,所以函数不是常量表达式,所以不能初始化变量constexpr
。
当参数是一个常量表达式时,编译器知道在编译时是否会采用分支,所以只要条件为true
它可以完全忽略false
分支,并且不会抱怨抛出异常在编译时是不可能的。
在运行时调用该函数时,它可以有任何参数,并且可以采用false
分支,并且将针对正常(非constexpr)函数对throw
进行评估。
谢谢我现在明白了。但我想测试它,它不会运行?请检查我的编辑。 – morbidCode 2014-09-30 16:46:18
'std :: out_of_range'没有默认构造函数,您需要传递一个字符串,例如'抛出std :: out_of_range(“我必须低于 2014-09-30 17:00:53
注意'f'也必须是'constexpr'函数。 – aschepler 2014-09-30 16:20:11
您可能想查看是否可以使用'static_assert()'。 http://en.cppreference.com/w/cpp/language/static_assert – dgnuff 2014-09-30 16:43:19
@dgnuff'static_assert' _requires_一个常量表达式,所以如果你将它添加到'check'中,你不能在运行时调用check恒定的论点。上面例子的要点是它是一个有效的运行时检查,它也可以用来初始化constexpr变量。 – 2014-09-30 17:02:34