CppCoreGuidelines F.4 如果函数可以在编译期计算出结果,可以声明为 constexpr
07 April 2022
F.4: If a function might have to be evaluated at compile time, declare
it constexpr
理由
通过 constexpr
让编译器在编译期进行计算。
例子
著名(臭名昭著?)的阶乘计算:
constexpr int fac(int n) { // constexpr enables max_exp to be used in Expects constexpr int max_exp = 17; // prevent silliness and overflow Expects(0 <= n && n < max_exp); int x = 1; for (int i = 2; i <= n; ++i) x *= i; return x; } int main() { cout << fac(10); return 0; }
3628800
C++14 可以这么玩。C++11 可以用递归方式计算。
注意
constexpr
不保证编译时能计算出来。它只是保证,在程序员要求的时候,或在编译器进行优化的时候,常量表达式参数可以在编译时计算。
constexpr int min(int x, int y) { return x < y ? x : y; } void test(int v) { int m1 = min(-1, 2); // probably compile-time evaluation constexpr int m2 = min(-1, 2); // compile-time evaluation int m3 = min(-1, v); // run-time evaluation constexpr int m4 = min(-1, v); // error: cannot evaluate at compile time } int main() { test(10); return 0; }
编译出错:
'v' is not a constant expression 17 | constexpr int m4 = min(-1, v); | ^
注意
不要把所有函数的声明为 constexpr
。很多计算适合在运行时进行。
注意
如果是需要在更高一层级运行时进行配置计算或业务逻辑运算的 API,不能是
constexpr
的。因为编译器无法优化。任何依靠这些 API 的 constexpr
函数最终都要重构,或去掉 constexpr
。
强化
编译器调用到声明为 constexpr
的函数时,如果函数中使用了可变变量,就会报错。