C++20. is_constant_evaluated() vs if constexpr



这是cpp首选项的示例:

constexpr double power(double b, int x)
{
if (std::is_constant_evaluated() && !(b == 0.0 && x < 0)) {
// A constant-evaluation context: Use a constexpr-friendly algorithm.
if (x == 0)
return 1.0;
double r = 1.0, p = x > 0 ? b : 1.0 / b;
auto u = unsigned(x > 0 ? x : -x);
while (u != 0) {
if (u & 1) r *= p;
u /= 2;
p *= p;
}
return r;
} else {
// Let the code generator figure it out.
return std::pow(b, double(x));
}
}

如您所见std::is_constant_evaluated().我的问题是为什么我们不能在这里使用if constexpr来检查函数调用是否发生在常量计算的上下文中?

is_constant_evaluated()问的问题在它的名字中得到了确切的拼写:"这个表达式是否在常量表达式计算中被计算?声明constexpr函数可能会也可能不会作为常量表达式计算的一部分执行。因此,在这样的上下文中调用该函数可能会返回不同的值,具体取决于实现如何调用它。

但是,if constexpr的条件必须是常量表达式,无论它碰巧处于什么功能中。因此,在if constexpr的条件下执行is_constant_evaluated()将始终产生true

不能将is_constant_evaluatedif constexpr的条件或任何其他显式constexpr上下文一起使用。好吧,你可以,但它可能不会返回你真正感兴趣的结果。

这段代码最终要做的是创建函数的两个版本:一个版本针对运行时执行进行了优化,另一个版本针对编译时执行进行了优化。这需要一个条件来测试需要调用哪个版本。

std::is_constant_evaluated的全部目的是能够在 if 语句中的运行时和编译时之间调度。

如果要使用if constexpr,那么您已经处于常量表达式中,并且条件将始终为真。

相反,你使用常规if,如果你在一个常量表达式中,你将在编译时得到if部分,如果不是,你将在运行时得到else部分。

cpppreferences已经回答了你的问题:

当直接用作static_assert声明或constexpr if语句的条件时,std::is_constant_evaluated()总是返回true

最新更新