如何判断是否在编译时计算了"constexpr"(无需手动检查)
How to tell if `constexpr` is evaluated at compile time (without manual inspection)
有没有一种标准方法来找出编译器对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
的问题。
- valgrind-hellgrind与泄漏检查的结果不同
- C++模板来检查友元函数的存在
- 检查输入是否不是整数或数字
- 试图让变量检查数组中的某些内容
- 检查值是否在集合p1和p2中,但不在p3中
- C++概念:如何使用'concept'检查模板化结构的属性?
- 概念TS检查忽略私有访问修饰符
- 检查 std::shared_ptr<> 的当前底层类型是否为 T
- 在c++中检查长方体是否尽可能快地重叠(无迭代)
- 如何在C++中检查2D数组中负值的输入验证
- C++:正在检查LinkedList中的回文-递归方法-错误
- 使用for循环检查数组中的重复项
- 如何检查一个c++字符串中有多少相同的字符/数字
- 检查不带转换的扫描格式
- 如何检查线程是否锁定
- 清除前检查矢量
- 如何处理来自核心指南检查器的关于gsl::at的静态分析警告
- C++LDAP检查用户是否是特定组的成员
- 检查TCHAR数组输入是否为带符号整数C++
- 用概念检查属性的类型