c++ - 如果忽略结果,则不会在编译时调用 Consexpr 函数
问题描述
我正在调查constexpr
函数的一些相当奇怪的代码覆盖结果(编译时调用无法被我使用的代码覆盖工具检测),并注意到某些constexpr
函数被调用为运行时函数,如果函数的结果通话未存储。
看来,对于constexpr
函数或方法,如果你存储调用的结果(在运行时变量 [emphasis!!!] 或constexpr
变量中),调用是编译时调用(只要参数是 compile -时间)。如果忽略结果,则调用是运行时调用。这与我的代码覆盖工具无关;在下面的简单示例中,该行为似乎是可重复的。
您可能会争辩说,由于constexpr
函数不会有副作用,因此如果您不返回/使用结果,编译器会做什么并不重要。我认为为了提高效率,编译器仍然会尽其所能constexpr
,但这既不是这里也不是那里......我想知道这是否甚至是定义的行为。
这是保证您的constexpr
函数将作为运行时调用的可移植方式吗???没有很多用途,但一个用途是:如果您想constexpr
在代码覆盖率中“为在函数上调用的测试而努力”,只需在单元测试结束时调用相同的函数,并且忽略结果,以便他们得到检测。
还有其他方法可以强制函数作为运行时调用,我知道,我主要对这里发生的事情感到好奇。当我第一次看到它时,这是非常出乎意料的。除非这是可移植的,否则我可能只会constexpr
通过运行时对象(即使对于静态方法也能做到这一点)或通过运行时函数指针调用我的方法。
请参见下面的示例。现场演示:https ://onlinegdb.com/rJao0RNGP
// Modified from https://stackoverflow.com/a/40410624/12854372
extern bool no_symbol;
struct ContextIsConstexpr {
size_t s;
constexpr ContextIsConstexpr() : s(1) {}
constexpr void operator()() {
auto ignore = s ? 1 : no_symbol;
}
};
constexpr bool tryIgnoringResult()
{
ContextIsConstexpr()();
return true;
}
constexpr void thereIsNoResult() {
ContextIsConstexpr()();
}
int main()
{
constexpr auto result1 = tryIgnoringResult(); // OK, compile-time
auto result2 = tryIgnoringResult(); // OK, compile-time
// tryIgnoringResult(); // Unexpected, runtime!
// thereIsNoResult(); // Unexpected, runtime!
}
解决方案
这可能会令人困惑,但 constexpr 函数应该在编译时仅在 constexpr 上下文中调用(分配给 constexpr 变量,用于数组大小或模板参数,...)。
在常规上下文中,函数在运行时被调用。优化器可能会在编译时解析该函数(对于遵循 as-if 规则的任何其他函数)。constexpr
确实是优化发生的一个很好的提示。
你可以争辩说,因为 constexpr 函数不能有副作用
它们可能有副作用,请参见以下有效示例:
constexpr int f(int i)
{
if (i == 0) return 0;
std::cout << i << std::endl;
return i;
}
int main()
{
[[maybe_unused]] constexpr int zero = f(0); // Compile time
f(42); // runtime
}
推荐阅读
- nginx - 来自 Kong 的自定义 Nginx 配置,必须禁用阻止 1GB 下载的代理临时文件
- spring-boot - 如何在使用 Spring Boot 访问地址时显示来自对象的信息
- c# - 如何将 AutoGenerate、IsolateApps 机器密钥系统移动到负载平衡服务器上?
- typescript - 在 tsconfig.json 和 tslint.json 中设置规则有什么区别?
- python - 向数据框添加新行 - 为什么使用 .loc[len(df)] 而不是 .iloc[len(df)]?
- sql - CosmosDb 计算不同元素
- javascript - 用户 requestAnimationFrame 'inside' requestAnimationFrame 的正确方法
- react-native - 需要使用本机代码的项目?
- wordpress - wordpress wp-blog-header.php 在第 16 行
- python - 从扁平字典创建嵌套字典