Nested `constexpr` function calls before definition in a constant-expression context

From what I gather from this answer, a constexpr function's result is not a constant-expression if the function has not been declared yet. What surprises me is the following code snippet [ˈsnɪpɪt] 片段:

constexpr int f();

constexpr int g() {
    return f();
}

constexpr int f() {
    return 42;
}

int main() {
    constexpr int i = g();
    return i;
}

This compiles without trouble and works. Moving f's definition past main triggers error: 'constexpr int f()' used before its definition, as I would expect.

I presume that it works because f has been defined before the call to g, thus both calls are constant expressions.

Why are f() and g() apparently constant-expressions, even though f isn't defined when it is called by g? How is this described by the Standard?

I have tested this on Coliru's GCC 6.1.0 and Clang 3.8.0.

2个回答

最佳答案

  • It is not necessary to define a constexpr before it is used. However, the result of calling it before its definition is not constexpr. Consequently, the compiler rightfully complains because you're trying to initialize a constexpr variable with a non-constant expression.

    §5.20/p2 Constant expressions [expr.const] (Emphasis Mine) :

    A conditional-expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine (1.9), would evaluate one of the following expressions:

    ...

    (2.3) — an invocation of an undefined constexpr function or an undefined constexpr constructor;

参考答案2

  • As linked by T.C. in his comment, this is subject to a defect report.

    According to 5.20 [expr.const] bullet 2.3, an expression is a constant expression unless (among other reasons) it would evaluate

    • an invocation of an undefined constexpr function or an undefined constexpr constructor;

    This does not address the question of the point at which a constexpr function must be defined. The intent, in order to allow mutually-recursive constexpr functions, was that the function must be defined prior to the outermost evaluation that eventually results in the invocation, but this is not clearly stated.

    This makes it clear that the example is well-formed and should indeed work as expected as long as f is defined before the call to g.

发布了190 篇原创文章 · 获赞 107 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/digitalkee/article/details/105121145