C++ constexpr 表达式求值

C++ constexpr expression evaluation

我对以下关于 constexpr 函数中使用的条件表达式的评论有疑问:

A branch of a conditional expression that is not taken in a constexpr function is not evaluated. Source: conditional evaluation of functions

正如源代码中已经写的那样,您可以使用像

这样的 constexpr 函数
constexpr int check(int i) {
    return (0<=i && i<10) ? i : throw out_of_range();
}

并且只评估采用的分支。到目前为止,一切都很好。但是为什么这与模板结合无效。那么让我们以这个基本示例为例:

template <int N>
constexpr int times(int y) {
    return (N<0) ? 0 : y+times<N-1>(y);
}

times<5>(10);

编译失败,因为模板实例化深度超过了最大值,即使 false 条件分支只执行了 4 次。然后它应该采用 true 分支和 return 0。当然可以使用 enable_if 或其他任何方式重写它,但我只想知道以下内容:

您误解了评估某事的含义。评估是在执行时发生的事情(即使该执行是在编译器 运行 时发生的)。

模板实例化是您代码的 static 属性。如果你写 times<N-1> 你要求实例化该模板。是否调用该函数并不重要;你写实例化,所以它被实例化。

这就是递归元编程通常通过模板特化来处理终端情况的原因。

这就是 if constexpr 被添加到 C++17 的原因。因为它有能力,不仅有条件地评估语句,而且有条件地 discard 语句,使另一个分支实际上不存在。这是以前不存在的东西。这允许另一个分支包含本来静态错误的代码。

所以这行得通:

if constexpr(N < 0) return 0 else return y+times<N-1>(y);

第二个子句将被丢弃,因此不会被实例化。

所以这个说法是正确的;子表达式有条件地求值。你只是误解了它如何适用于你的情况。