关于constexpr函数中使用的条件表达式的注释,我有一个问题:
不评估未在constexpr函数中使用的条件表达式的分支。 来源: 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
分支并返回0.当然它可以使用enable_if
或其他任何东西重写,但我只想知道以下事项:
当涉及子表达式类型评估时,此语句是否无效?
为什么即使上述声明声称子表达式未被评估,这也会失败?我想无论如何都必须评估类型(例如,检查是否满足条件的两个分支具有相同类型的要求),因此它以无限模板实例化结束。正确的假设?
c ++标准中是否有描述此行为的地方?
答案 0 :(得分:2)
你误解了评估某事的意义。评估是在执行时发生的事情(即使在编译器运行时发生执行)。
模板实例化是代码的静态属性。如果您编写times<N-1>
,则要求实例化该模板。如果你打电话给那个功能并不重要;你编写了实例化,所以它被实例化了。
这就是递归元编程通常通过模板特化处理终端案例的原因。
这就是将if constexpr
添加到C ++ 17的原因。因为它有权,不仅有条件地评估语句,而且有条件地 discard 语句,使得其他分支实际上不存在。这不是以前曾经存在过的东西。这允许另一个分支包含本来是静态形成的代码。
所以这会奏效:
if constexpr(N < 0) return 0 else return y+times<N-1>(y);
第二个子句将被丢弃,因此不会被实例化。
所以陈述是正确的;子表达式是有条件的评估。你只是误解了它如何适用于你的情况。