是否有一种标准方法可以找出编译器对 constexpr
函数做了什么?
(旁注:对于调试,默认情况下每个 constexpr 函数都延迟到运行时。为什么这是明智的?有没有办法影响它?)
对于发布,它取决于上下文。显然,对于小型测试设置,您可以轻松检查生成的机器代码,但这不是实际项目的方法。
我当前的“解决方法”(VC++) 是在某处中断,转到我的 constexpr 函数并(尝试)检查反汇编。如果没有,我的结论是这一切都是在编译时完成的。 但这种方式并不是 100% 可靠的。 (优化等) 只有另一种方式是肯定的:如果我确实找到反汇编(甚至可以在那里中断),我知道它不是在编译时完成的。
最佳答案
这是不可能的。 constexpr
不保证值内联,你可以在这里看到这个操纵优化级别:https://godbolt.org/z/dAoiM-
只有从 -O2 开始,一切都被内联并且结构被分解。在该编译器之下,即使对于 constexpr
上下文中使用的代码,编译器也会愉快地使用运行时评估。
没有标准的语言工具可以查询编译器是否应用了特定的优化。这一切都归结为 as-if rule .如果代码的行为相同,编译器可以对它做任何事情。唯一的异常(exception)是强制性 RVO 和其他 RVO(允许它们改变观察到的行为。)
话虽这么说。 constexpr
是一个有用的提示。在链接示例中,如果删除 constexpr
说明符,甚至 O3
(在最近的 clang 和 gcc 上)也无法删除 map 。
编写 constexpr
函数和数据结构是值得优化的,确保编译器可以优化,尽管你不能强制它。
您可以强制在 constexpr
上下文中评估函数,您还可以保护非 constexpr 路径抛出,以防止保证运行时评估。
#include <iostream>
#include <vector>
using namespace std;
constexpr int f(int el) {
return el > 0 ? el : throw "error";
}
int main() {
// constexpr auto r = f(-1); // #1 compiler errors that throw is forbidden in
// constexpr, so it went into a non-constexpr path
// and failed
constexpr auto r = f(1); // #2 fine - has to be interpreted in constexpr context
cout << f(1) << '\n'; // #3 fine - can be interpreted in both contexts
try {
cout << f(-1) << '\n'; // # 4 // throws - i.e. runtime evaluation
}
catch (const char* e) {
cout << e << '\n';
}
return 0;
}
关于c++ - 如何判断 `constexpr`是否在编译时求值(无需人工检查),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52078752/