简体   繁体   English

在C ++ 14 Standard中,它表示非constexpr函数不能用于constexpr函数的定义吗?

[英]Where in C++14 Standard does it say that a non-constexpr function cannot be used in a definition of a constexpr function?

For example the code below doesn't compile unless incr() is declared constexpr : 例如,除非将incr()声明为constexpr否则下面的代码不会编译:

int incr(int& n) {
    return ++n;
}

constexpr int foo() {
    int n = 0;
    incr(n);
    return n;
}

Looking at §7.1.5/3 in C++14 we have: 看看C ++ 14中的§7.1.5/ 3,我们有:

The definition of a constexpr function shall satisfy the following constraints: constexpr函数的定义应满足以下约束:
(3.1) — it shall not be virtual (10.3); (3.1) - 它不应是虚拟的(10.3);
(3.2) — its return type shall be a literal type; (3.2) - 其返回类型应为字面类型;
(3.3) — each of its parameter types shall be a literal type; (3.3) - 每个参数类型应为文字类型;
(3.4) — its function-body shall be = delete, = default, or a compound-statement that does not contain (3.4) - 其函数体应为= delete,= default或不包含的复合语句

(3.4.1) — an asm-definition, (3.4.1) - asm-definition,
(3.4.2) — a goto statement, (3.4.2) - goto语句,
(3.4.3) — a try-block, or (3.4.3) - 试块,或
(3.4.4) — a definition of a variable of non-literal type or of static or thread storage duration or for which no initialization is performed. (3.4.4) - 非文字类型或静态或线程存储持续时间的变量的定义,或者不执行初始化的定义。

Two paragraphs later, in [dcl.constexpr]/5: 两段之后,在[dcl.constexpr] / 5中:

For a non-template, non-defaulted constexpr function or a non-template, non-defaulted, non-inheriting constexpr constructor, if no argument values exist such that an invocation of the function or constructor could be an evaluated subexpression of a core constant expression (5.20), or, for a constructor, a constant initializer for some object (3.6.2), the program is ill-formed; 对于非模板,非默认的constexpr函数或非模板,非默认的,非继承的constexpr构造函数,如果不存在参数值,则调用函数或构造函数可以是核心常量的计算子表达式表达式(5.20),或者,对于构造函数,某个对象(3.6.2)的常量初始值设定项,程序是不正确的; no diagnostic required. 无需诊断。

No argument exists such that foo() could be a core constant expression because of incr() , therefore the program is ill-formed (NDR). 由于incr() ,因为foo()可能是核心常量表达式,所以不存在任何参数,因此程序是错误的(NDR)。

What you're looking for is § 5.19: 你要找的是§5.19:

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将评估以下表达式之一:

This applies to the evaluation of an expression that is a constexpr function call. 这适用于对constexpr函数调用的表达式的求值。 That is, calling a constexpr function will be a 'core constant expression' if evaluating the function, ie executing the body of the function according to the rules of the C++ abstract machine, doesn't do any of the things forbidden in the list given in § 5.19. 也就是说,调用constexpr函数将是一个'核心常量表达式',如果评估函数,即根据C ++抽象机器的规则执行函数体,则不执行给定列表中禁止的任何事情在第5.19节中。

One of items in the list is: 列表中的一项是:

  • an invocation of a function other than [...] a constexpr function 调用constexpr函数以外的函数

So to apply this to your example: evaluating the expression foo() evaluates a call to a function incr() which is not a constexpr function, which means that the expression foo() is not a core constant expression. 因此,将此应用于您的示例:计算表达式foo()计算对函数incr()的调用,该函数不是constexpr函数,这意味着表达式foo()不是核心常量表达式。

Further, since the above is true for all possible invocations of your function foo , the rule in § 7.1.5/5 kicks in and means that your example program is ill-formed, no diagnostic required, even if you never actually call foo() . 此外,由于上述情况适用于函数foo所有可能调用,因此第7.1.5 / 5节中的规则启动并意味着您的示例程序格式错误,无需诊断,即使您实际上从未调用foo()


As Ben Voigt points out a constexpr function can contain calls to non-consexpr functions, so long as the particular evaluation of the function does not actually evaluate any such function call (or it appears in a context that does not require a constant expression). 正如Ben Voigt所指出的,constexpr函数可以包含对非consexpr函数的调用,只要该函数的特定评估实际上不评估任何此类函数调用(或者它出现在不需要常量表达式的上下文中)。

The restrictions in 5.19 only pertain to what expressions actually end up being evaluated as part of the evaluation of an expression. 5.19中的限制仅适用于实际上最终被评估为表达式评估的一部分的表达式。

For example: 例如:

#include <iostream>

int incr(int &n) { return ++n; }

enum E {be_constexpr, not_constexpr};

constexpr int foo(E e = be_constexpr) {
  int n = 0;
  if (e == not_constexpr) { incr(n); }
  return n;
}

int main() {
  constexpr int a = foo(); // foo() is a constant expression
  int b = foo(not_constexpr); // may or may not evaluate `foo(non_constexpr)` at runtime. In practice modern C++ compilers will do compile-time evaluation here even though they aren't required to.
  // constexpr int c = foo(not_constexpr); // Compile error because foo(not_constexpr) is not formally a constant expression, even though modern compilers can evaluate it at compile-time.

  std::cout << a << ' ' << b << '\n';
}

It doesn't. 它没有。

The following is allowed, even though it does exactly what you surmise is forbidden: 允许以下内容,即使它完全符合您的猜测是禁止的:

int incr(int& n) {
    return ++n;
}

constexpr int foo(bool x) {
    int n = 0;
    if (x) incr(n);
    return n;
}

The code in your question is disallowed by the rule with Barry quoted in his answer. 在他的回答中引用了巴里的规则,你的问题中的代码是不允许的。 But in my variation, there does exist a set of parameters (specifically, false ) with which invocation of foo results in a compile-time constant expression. 但在我的变体中,确实存在一组参数(特别是false ), foo调用会导致编译时常量表达式。

Note that a diagnostic isn't required -- a conforming compiler could allow your version to compile as well. 请注意,不需要诊断 - 符合标准的编译器也可以允许您的版本进行编译。

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

相关问题 在constexpr函数体c ++ 14中可以有非文字类型的定义变量吗? - can have definition variable of non-literal type in constexpr function body c++14? C++ 错误:调用非 constexpr 函数 - C++ error: Call to non-constexpr function 在非 constexpr function 中作为左值传递的变量上使用 `constexpr` function - Using a `constexpr` function on a variable passed as lvalue in a non-constexpr function 调用非constexpr函数“ std :: map…” - Call to non-constexpr function 'std::map…' C ++中的“constexpr”14 - “constexpr” in C++14 非constexpr函数在constexpr构造函数中的使用有效 - Non-constexpr function's use in constexpr constructor is valid 在内联函数的定义中使用 constexpr 变量时可能的 ODR 违规(在 C++14 中) - Possible ODR-violations when using a constexpr variable in the definition of an inline function (in C++14) 为什么gcc5.4不编译调用非constexpr函数的constexpr函数,而icpc编译呢? - Why gcc5.4 doesn't compile a constexpr function calling a non-constexpr function, but icpc does? 使C ++ 14 constexpr函数与C ++ 11兼容 - Make C++14 constexpr function C++11 compatible 如果在C ++ 14或更高版本上,非const的成员函数应该只是constexpr - member function that is not const should only be constexpr if on C++14 or later
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM