【发布时间】:2018-12-17 06:20:33
【问题描述】:
最近我在我的 constexpr 函数中将一些 if constexpr 修改为 if ,发现它们仍然可以正常工作并且可以在编译时进行评估。这是一个最小的情况:
template<int N>
constexpr bool is_negative()
{
if constexpr (N >= 0) return false;
else return true;
}
int main()
{
constexpr bool v = is_negative<1>();
}
在上述情况下,N 必须在编译时知道,因为它是非类型模板参数,所以 if constexpr 在这里可以正常工作。但是,它是一个 constexpr 函数,因此,iirc,即使我将 if constexpr 替换为 if,也 可能 获得返回值:
template<int N>
constexpr bool is_negative()
{
if (N >= 0) return false;
else return true;
}
int main()
{
constexpr bool v = is_negative<1>();
}
来自cppref,A constexpr function must satisfy the following requirements: 中的所有要求均未提及if。因此,IIUC,即使所有相关变量在编译时已知(如上面的is_negative), constexpr 函数是否包含要在编译时评估的 if 也应该是实现定义的行为。
所以,我的结论是:
- 在c++17之前,我们没有
if constexpr,所以选择if,这意味着不能保证我们的constexpr函数在编译时就被求值,都依赖于编译器实现李> - 在 c++17 之后,如果我们希望在编译时评估 constexpr 函数,则首选
if constexpr。
以上都是我的个人想法,可能有一些重要的遗漏/误解,请随时纠正我。问题仍然没有改变:if 和 if constexpr,对于预期在编译时进行评估的 constexpr 函数应该首选。
参考: - What is Allowed in a constexpr Function? - Difference between "if constexpr()" Vs "if()"
【问题讨论】:
-
常量的评估一直是编译时评估。例如。使用模板
is_negative()和13会产生条件13 >= 0,编译器会将其解析为1(也没有constexpr)。现代编译器优化了整个条件,但我不知道这是否是强制性的,如果是的话,从哪个版本的标准开始。顺便提一句。if (N >= 0) return true; else return false;:为什么不return N >= 0;?还是因为minimal reproducible example 的简化? -
哎呀,我的错,这是糟糕的风格。我应该发布一个更好的示例...
-
好的,没问题。 (您也可以说这是由于 MCVE 造成的。这些事情可能看起来有点愚蠢,但只是为了“展示原理”。恕我直言,如果这样说是可以接受的。);-)
-
@Scheff 我发现我只是告诉一个操作员这是很棒的风格 2 个月前stackoverflow.com/a/52826880/6949852XD
-
我和@Nelfeal 在一起。具有常量的算术或关系操作再次产生常量(编译时评估)。我试图找到相应的。参与 Constant expressions 但失败了,直到我意识到 核心常量表达式 被表达为“反向”,即它们列出了任何内容以使表达式 not 成为核心常量表达式。我需要一点才能意识到这一点...... ;-)
标签: c++ constexpr compile-time if-constexpr