当前位置:  开发笔记 > 编程语言 > 正文

据我所知,下面的函数不是constexpr,但是代码用clang和g ++编译.我错过了什么?

如何解决《据我所知,下面的函数不是constexpr,但是代码用clang和g++编译.我错过了什么?》经验,为你挑选了2个好方法。

我从N4140的§5.19/ 2得到了这个例子:

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

据我所知,这不是一个constexpr功能.但是代码片段用clang和g ++编译.查看实例.我在这里错过了什么?



1> Shafik Yaghm..:

在C++ 14中,constexpr函数的规则被放宽了,论文N3597:放宽了对constexpr函数的约束.本文介绍了理论基础和效果,其中包括以下内容(强调我的):

与在C++ 11中一样,constexpr关键字用于标记在翻译期间需要实现的函数,如果它们是从需要常量表达式的上下文中使用的话.constexpr函数允许使用任何有效的C++代码,包括局部变量的创建和修改,以及几乎所有语句,并且限制是必须可以在常量表达式中使用constexpr函数.常量表达式可能仍然具有评估及其结果的局部副作用.

和:

保留了对constexpr函数的一些语法限制:

asm-declarations是不允许的.

不允许使用try-blocks和function-try-blocks.

具有静态和线程存储持续时间的变量声明有一些限制(见下文).

我们可以在N4140部分7.1.5 [dcl.constexpr]中找到这个内容,其中说:

constexpr函数的定义应满足以下约束:

它不应是虚拟的(10.3);

其返回类型应为字面类型;

每个参数类型都应是文字类型;

它的函数体应为= delete,= default或不包含的复合语句

asm-definition,

一个goto声明,

尝试块,或

非文字类型或静态或线程存储持续时间的变量的定义,或者不执行初始化的定义.

最后一个示例显示了如何incr在constexpr中使用:

constexpr int h(int k) {
  int x = incr(k); // OK: incr(k) is not required to be a core
                   // constant expression
  return x;
}

constexpr int y = h(1); // OK: initializes y with the value 2
                        // h(1) is a core constant expression because
                        // the lifetime of k begins inside h(1)

而涵盖的规则the lifetime of k begins inside h(1)是:

修改对象(5.17,5.2.6,5.3.2),除非它被应用于文字类型的非易失性左值,该文字类型引用一个非易失性对象,其生命周期始于e的评估范围内;

7.1.5 [dcl.constexpr]中的措辞向我们展示了为什么incr有效的constexpr:

对于非模板,非默认的constexpr函数或非模板,非默认的,非继承的constexpr构造函数,如果不存在参数值,则调用函数或构造函数可以是核心常量的计算子表达式表达式(5.19),程序不正确; 无需诊断.

作为TC给出的修改示例:

constexpr int& as_lvalue(int&& i){ return i; }

constexpr int x = incr(as_lvalue(1)) ;

表明,我们确实可以使用incr核心常量表达式的子表达式,因此它不是错误的.


@ShafikYaghmour经过一番思考后,我终于明白了`constexpr int x = incr(as_lvalue(1));`证明`constexpr int incr(int&n){return ++ n; }`实际上是一个constexpr函数(+1).

2> melak47..:

据我所知,这不是一个constexpr功能.

你为什么这么说?§5.19/ 2中的示例如下:

constexpr int g(int k) {
    constexpr int x = incr(k); // error: incr(k) is not a core constant
                               // expression because lifetime of k
                               // began outside the expression incr(k)
    return x;
}

incr(k)不是核心常量表达并不意味着incr不能成为constexpr函数.

根据C++ 14的constexpr规则,可以incr在constexpr上下文中使用,例如:

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

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

除非函数体不可能constexpr(例如,无条件地调用非constexpr函数),否则编译器没有理由在定义时产生错误.

constexpr函数甚至可能包含正文中的路径/分支,这些路径/分支不是constexpr.只要它们从未进入constexpr上下文,您就不会收到错误.例如:

constexpr int maybe_constexpr(bool choice, const int& a, const int& b) {
    return choice ? a : b;
}

constexpr int a = 0;
int b = 1;
static_assert(maybe_constexpr(true, a, b) == 0, "!");

实例

推荐阅读
mobiledu2402851377
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有