如何初始化constexpr引用

vso*_*tco 21 c++ reference constexpr c++11

我试图初始化一个constexpr参考没有成功.我试过了

#include <iostream>

constexpr int& f(int& x) // can define functions returning constexpr references
{
    return x;
}

int main()
{
    constexpr int x{20};
    constexpr const int& z = x; // error here
}
Run Code Online (Sandbox Code Playgroud)

但我得到编译时错误

错误:constexpr变量'z'必须由常量表达式初始化

删除const结果

错误:将类型'int'的引用绑定到类型'const int'的值会删除限定符

即使我有一种constexpr自动暗示const变量声明的感觉.

所以我的问题是:

  1. constexpr参考以往有用吗?(即比const参考文献"更好" )
  2. 如果是,我该如何有效地定义它们?

PS:我看过几个与我有关的问题,例如哪些值可以分配给`constexpr`参考?,但我不认为他们解决了我的问题.

Jon*_*ely 24

  1. constexpr引用是否有用?(即,比const引用"更好")

保证在程序启动之前初始化它们,而在程序开始运行之后,可以在动态初始化期间初始化对const的引用.

  1. 如果是,我该如何有效地定义它们?

一个constexpr 参考具有绑定到一个全球性的,而不是一个局部变量(或者更正式,它必须绑定与静态存储时间的东西).

引用在概念上等同于获取变量的地址,并且局部变量的地址不是常量(即使main只能调用一次,因此其局部变量仅初始化一次).

  • 它们需要绑定到具有静态存储持续时间的东西,这可以是本地的"静态"或全局的. (9认同)
  • @antred [basic.start.main]/3:"函数`main`不能在程序中使用.`main`的链接是实现定义的.一个程序将`main`定义为已删除或声明为main是`inline`,`static`或`constexpr`是不正确的.名称`main`不是保留的." (5认同)
  • @antred我不是C专家,但快速浏览N1570显示没有类似的限制.5.1.2.2.3/1程序终止确实说"如果`main`函数的返回类型是与`int`兼容的类型,则从*initial*调用返回到`main`函数等同于调用`exit`函数,其中`main`函数返回的值为其参数..."[强调添加].这似乎暗示*对main的非初始*调用是合规的. (4认同)
  • @TC*"可以是本地`静态`或全局"*或临时,其生命周期延长到静态存储持续时间:`static constexpr int const&x = 42;`很好.这也是为什么`static constexpr auto x = {1,2};`被clang ++接受,但`constexpr auto x = {1,2};`不是(在块范围内).(这意味着即使在OP的代码中`static constexpr const int&z = + x;`也是合法的.) (3认同)
  • `constexpr`影响引用,而不是它绑定的类型,所以绑定到`const int`你还需要一个`const int&` (2认同)
  • @vsoftco从语言的角度来看,`constexpr`是*decl-specifier*.我不打算详细介绍,但你可以将其余部分放在一起. (2认同)

Sha*_*our 9

所以问题是constexpr引用需要绑定到具有静态存储持续时间的对象,这在C++ 11标准草案中有所涉及:N3337 section 5.19 [expr.const](强调我的):

引用常量表达式是左值核心常量表达式,用于指定具有静态存储持续时间或函数的对象

C++草案标准14:N3936改变措词:

常量表达式是glvalue核心常量表达式,其值是指具有静态存储持续时间的对象或函数,或者是prvalue核心常量表达式,其值是一个对象,对于该对象及其子对象:

  • 引用类型的每个非静态数据成员是指具有静态存储持续时间或对象的对象,以及
  • 如果对象或子对象是指针类型,则它包含具有静态存储持续时间的对象的地址,超过此类对象的结尾的地址(5.7),函数的地址或空指针值.

所以改变这样的声明x会起作用:

constexpr static int x{20};
Run Code Online (Sandbox Code Playgroud)


小智 5

TC一样,初始化程序需要是具有静态存储持续时间的对象.

N4140 /§5.19/ 4 常量表达式是glvalue核心常量表达式,其值指的是具有静态存储持续时间的对象[...]

N4140/§7.1.5/ 9 constexpr对象声明中使用的说明符将对象声明为const.这样的对象应具有文字类型并应初始化.[...]否则,或者如果constexpr 在引用声明中使用了说明符,则其初始值设定项中出现的每个完整表达式都应为常量表达式.

在N3337中,措辞不同.