有没有一种标准的方法来找出编译器对constexpr
函数的作用?
(附带说明:对于调试,默认情况下,每个constexpr函数都推迟到运行时。为什么这样做很明智?有没有办法影响这一点?)
要发布,取决于上下文。显然,对于较小的测试设置,您可以轻松地检查生成的机器代码,但这并不是真正项目的方法。
我当前的“解决方法”(VC ++)是要打断某个地方,转到我的constexpr函数,然后(尝试)检查反汇编。如果没有,我得出的结论是所有这些都是在编译时完成的。 但是这种方式并不是100%可靠的。 (优化等) 只能通过另一种方式确定:如果我发现反汇编(甚至可以在那里分解),我知道它不是在编译时完成的。
答案 0 :(得分:1)
这是不可能的。 constexpr
不保证值内联,您可以在此处查看此操纵优化级别:https://godbolt.org/z/dAoiM-
仅由于-O2,所有内容都被内联并且结构被溶解。在此之下,即使对于constexpr
上下文中使用的代码,编译器也愉快地使用运行时评估。
没有标准的语言工具来询问编译器是否应用了特定的优化。归结为as-if rule。如果代码的行为相同,则编译器可以对其执行任何操作。唯一的例外是强制性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;
}
答案 1 :(得分:0)
现在我们有了当前的C ++ 20标准,因此可以使用consteval
。
从文档中
consteval-指定一个函数为立即函数,也就是说,每次对该函数的调用都必须产生一个编译时常量。 doc
这将解决constexpr
的问题。