如何解决如果忽略结果,则在编译时不会调用Constexpr函数
我正在研究constexpr
函数的一些相当奇怪的代码覆盖结果(我使用的代码覆盖工具无法检测编译时调用),并注意到一些constexpr
函数被调用为 运行时 函数, 如果未存储函数调用的结果 。
对于constexpr
函数或方法,如果您将调用结果存储在运行时变量[emphasis !!!]或constexpr
变量中,则该调用似乎是编译时调用(只要参数是编译时)。如果忽略结果,则该调用为运行时调用。这与我的代码覆盖工具无关。在下面的简单示例中,该行为似乎是可重复的。
您可能会争辩说,由于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函数。
在常规情况下,在运行时调用函数。 Optimizer可能会在编译时解析该函数(就像遵循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
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。