如何判断是否在编译时计算了"constexpr"(无需手动检查)



有没有一种标准方法来找出编译器对constexpr函数的作用?

(旁注:对于调试,默认情况下,每个 constexpr 函数都延迟到运行时。为什么这是明智的?有没有办法影响这一点?

对于发布,这取决于上下文。显然,对于小型测试设置,您可以轻松检查生成的机器代码,但这不是实际项目的方法。

我目前的"解决方法"(VC++(是在某个地方中断,转到我的constexpr函数并(尝试(检查反汇编。如果没有,我的结论是这一切都是在编译时完成的。 但这种方式并不是 100% 可靠的。(优化等( 只有相反的方式是肯定的:如果我确实发现反汇编(甚至可以在那里中断(,我知道它不是在编译时完成的。

是不可能的。constexpr不保证值内联,您可以在此处查看此操作优化级别:https://godbolt.org/z/dAoiM-

只有因为 -O2 一切都是内联的,结构才会溶解。在该编译器下面,即使对于constexpr上下文中使用的代码,编译器也可以愉快地使用运行时评估。

没有标准语言工具来查询编译器是否应用特定的优化。这一切都归结为仿佛规则。如果代码的行为相同,编译器可以对其执行任何操作。唯一的例外是强制性 RVO 和其他 RVO(允许它们更改观察到的行为(。

话虽如此。constexpr是一个有用的提示。在链接的示例中,如果删除constexpr说明符,即使O3(在最近的 clang 和 gcc 上(也无法删除地图。

在优化方面编写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++20 标准,因此我们可以使用consteval.

从文档中:

consteval - 指定函数是即时函数,也就是说,对该函数的每次调用都必须生成一个编译时常量。 .doc

这将解决constexpr的问题。

最新更新