一个constexpr函数不需要返回一个常量表达式吗?

16
《C++ Primer》(第五版)第240页有一条注释:
constexpr函数不要求返回一个常量表达式。”
有人对此提出了一个问题:constexpr函数的返回类型可以是非const吗?。那个问题的提问者误解了这个注释。
但是,对它的正确理解是什么(引用帖子的答案澄清了那个帖子作者的困惑,但没有回答我的问题)?

4
谢谢Simon将问题格式处理得这么好,我从中学到了新的东西。 - AlwaysLearning
2
Scott Meyers在他的新书《Effective Modern C++》中很好地解释了这个主题。 - Alejandro
@Alejandro,是哪个项目编号? - AlwaysLearning
对我来说,"进入现代C++"中的15。 - Alejandro
下面有两个很好的答案,它们回答了你的问题吗? - Shafik Yaghmour
2个回答

15

constexpr函数在所有参数都是常量表达式的情况下,必须返回一个常量表达式。这其实很有道理。例如:

constexpr int square(int i){
    return i*i;
}

std::array<int, square(2)> ia; //works as intended, constant expression
int i;
std::cin >> i;
int j = square(i); //works even though i is not a constant expression
std::array<int, square(i)> ia; //fails, because square does not (and cannot)
                               //return a constant expression

*由chris更正。


1
我不同意。只要函数能够返回常量表达式,那么就可以了。允许使用常量表达式参数并返回非常量表达式,只要它再次返回常量表达式即可(例如:http://coliru.stacked-crooked.com/a/a0d9dcadc756749c)。这个论点来自OP链接的问题。 - chris
1
在constexpr函数内,参数不被视为常量表达式。因此,即使constexpr int foo(int i) { return i; }也不会返回一个常量表达式。在我的看法中,《C++ Primer》的措辞有点傻。标准要求的是必须能够在常量表达式内调用constexpr函数(存在这样的参数,使得函数可以在常量表达式内被调用)。 - dyp

12

一个(非模板)constexpr函数必须至少有一条执行路径返回常量表达式;形式上,必须存在参数值使得 "该函数的调用[...] 可以成为核心常量表达式的计算子表达式" ([dcl.constexpr]/5)。例如(同上文):

constexpr int f(bool b) { return b ? throw 0 : 0; }     // OK
constexpr int f() { return f(true); }     // ill-formed, no diagnostic required

这里的int f(bool)被允许是constexpr,因为它的参数值为false时返回一个常量表达式。

如果一个函数模板的一个特化能够返回常量表达式,则可能存在一个constexpr函数无法返回常量表达式。再次引用以上示例:

template<bool B> constexpr int g() { return f(B); }    // OK
constexpr int h() { return g<true>(); }    // ill-formed, no diagnostic required

g<true>() 声明为 constexpr 有什么用处?你能写出 constexpr int a = g<true>(); 吗?我猜不能,因为编译器在编译时无法计算初始化值。 - AlwaysLearning
@MeirGoldenberg 正确,但你可以写成 constexpr int a = g<false>();,所以标准允许 g()constexpr - ecatmur
啊,对了,在特化时如果我省略了constexpr就无法编译通过!谢谢! - AlwaysLearning
你是想进行g<true>()的显式实例化还是显式特化?为什么h()是不合法的NDR? - T.C.
那么你不想要 <> ...? template <> 将是一个显式的特化。 - T.C.
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接