简体   繁体   English

嵌套的`constexpr`函数在常量表达式上下文中定义之前调用

[英]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. 根据我从这个答案收集的内容,如果函数尚未声明,则constexpr函数的结果不是常量表达式。 What surprises me is the following code snippet : 令我惊讶的是以下代码片段:

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. 移动f的定义超过主要触发器error: 'constexpr int f()' used before its definition ,正如我所料。

I presume that it works because f has been defined before the call to g , thus both calls are constant expressions. 我认为它的工作原理是因为在调用g之前定义了f ,因此两个调用都是常量表达式。

Why are f() and g() apparently constant-expressions, even though f isn't defined when it is called by g ? 为什么f()g()显然是常量表达式,即使f在被g调用时没有定义f How is this described by the Standard? 标准如何描述?

I have tested this on Coliru's GCC 6.1.0 and Clang 3.8.0. 我在Coliru的GCC 6.1.0和Clang 3.8.0上测试了这个。

It is not necessary to define a constexpr before it is used. 在使用constexpr之前没有必要定义它。 However, the result of calling it before its definition is not constexpr . 但是,在定义之前调用它的结果不是constexpr Consequently, the compiler rightfully complains because you're trying to initialize a constexpr variable with a non-constant expression. 因此,编译器正确地抱怨,因为您尝试使用非常量表达式初始化constexpr变量。

§5.20/p2 Constant expressions [expr.const] ( Emphasis Mine ) : §5.20/ p2常量表达式[expr.const]强调我的 ):

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: 条件表达式e是核心常量表达式,除非根据抽象机器(1.9)的规则评估e将评估以下表达式之一:

... ...

(2.3) — an invocation of an undefined constexpr function or an undefined constexpr constructor; (2.3) - 调用未定义的constexpr函数或未定义的constexpr构造函数;

As linked by TC in his comment , this is subject to a defect report . 由TC在其评论中链接,这是一个缺陷报告

According to 5.20 [expr.const] bullet 2.3, an expression is a constant expression unless (among other reasons) it would evaluate 根据5.20 [expr.const] bullet 2.3,表达式是一个常量表达式,除非(以及其他原因)它将进行评估

  • an invocation of an undefined constexpr function or an undefined constexpr constructor; 调用未定义的constexpr函数或未定义的constexpr构造函数;

This does not address the question of the point at which a constexpr function must be defined. 这没有解决必须定义constexpr函数的问题。 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. 为了允许相互递归的constexpr函数,意图是必须在最外部评估之前定义函数,最终导致调用,但这没有明确说明。

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 . 这清楚地表明,只要在调用g之前定义了f ,该示例就是格式良好的,并且确实应该按预期工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM