如何初始化constexpr引用

时间:2022-02-04 16:54:24

I am trying to initialize a constexpr reference with no success. I tried

我试图初始化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
}

but I'm getting a compile time error

但我得到编译时错误

error: constexpr variable 'z' must be initialized by a constant expression

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

Dropping the const results in

删除const会导致

error: binding of reference to type 'int' to a value of type 'const int' drops qualifiers

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

even though I had the feeling that constexpr automatically implies const for variable declarations.

即使我觉得constexpr自动暗示变量声明的const。

So my questions are:

所以我的问题是:

  1. Are constexpr references ever useful? (i.e., "better" than const references)
  2. constexpr引用是否有用? (即比const引用“更好”)

  3. If yes, how can I effectively define them?
  4. 如果是,我该如何有效地定义它们?

PS: I've seen a couple of questions related to mine, such as Which values can be assigned to a `constexpr` reference? , but I don't think they address my questions.

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

3 个解决方案

#1


20  

  1. Are constexpr references ever useful? (i.e., "better" than const references)
  2. constexpr引用是否有用? (即比const引用“更好”)

They are guaranteed to be initiailized before the program starts, whereas a reference to const can be initialized during dynamic initialization, after the program starts running.

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

  1. If yes, how can I effectively define them?
  2. 如果是,我该如何有效地定义它们?

A constexpr reference has to bind to a global, not a local variable (or more formally, it has to bind to something with static storage duration).

constexpr引用必须绑定到全局变量,而不是局部变量(或者更正式地说,它必须绑定到具有静态存储持续时间的东西)。

A reference is conceptually equivalent to taking the address of the variable, and the address of a local variable is not a constant (even in main which can only be called once and so its local variables are only initialized once).

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

#2


9  

So the problem is that a constexpr reference needs to bind to an object with static storage duration, which is covered in the draft C++11 standard: N3337 section 5.19 [expr.const] (emphasis mine):

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

A reference constant expression is an lvalue core constant expression that designates an object with static storage duration or a function

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

The draft C++14 standard: N3936 changes the wording:

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

A constant expression is either a glvalue core constant expression whose value refers to an object with static storage duration or to a function, or a prvalue core constant expression whose value is an object where, for that object and its subobjects:

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

  • each non-static data member of reference type refers to an object with static storage duration or to a function, and
  • 引用类型的每个非静态数据成员是指具有静态存储持续时间或对象的对象,和

  • if the object or subobject is of pointer type, it contains the address of an object with static storage duration, the address past the end of such an object (5.7), the address of a function, or a null pointer value.
  • 如果对象或子对象是指针类型,则它包含具有静态存储持续时间的对象的地址,超过此类对象的结尾的地址(5.7),函数的地址或空指针值。

So changing the declaration of x like so would work:

所以改变x的声明就好了:

constexpr static int x{20};

#3


5  

Like T.C. says, the initializer needs to be an object with static storage duration.

像T.C.说,初始化程序需要是一个具有静态存储持续时间的对象。

N4140/§5.19/4 A constant expression is either a glvalue core constant expression whose value refers to an object with static storage duration [...]

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

N4140/§7.1.5/9 A constexpr specifier used in an object declaration declares the object as const. Such an object shall have literal type and shall be initialized. [...] Otherwise, or if a constexpr specifier is used in a reference declaration, every full-expression that appears in its initializer shall be a constant expression.

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

In N3337, the wording is different.

在N3337中,措辞不同。

#1


20  

  1. Are constexpr references ever useful? (i.e., "better" than const references)
  2. constexpr引用是否有用? (即比const引用“更好”)

They are guaranteed to be initiailized before the program starts, whereas a reference to const can be initialized during dynamic initialization, after the program starts running.

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

  1. If yes, how can I effectively define them?
  2. 如果是,我该如何有效地定义它们?

A constexpr reference has to bind to a global, not a local variable (or more formally, it has to bind to something with static storage duration).

constexpr引用必须绑定到全局变量,而不是局部变量(或者更正式地说,它必须绑定到具有静态存储持续时间的东西)。

A reference is conceptually equivalent to taking the address of the variable, and the address of a local variable is not a constant (even in main which can only be called once and so its local variables are only initialized once).

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

#2


9  

So the problem is that a constexpr reference needs to bind to an object with static storage duration, which is covered in the draft C++11 standard: N3337 section 5.19 [expr.const] (emphasis mine):

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

A reference constant expression is an lvalue core constant expression that designates an object with static storage duration or a function

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

The draft C++14 standard: N3936 changes the wording:

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

A constant expression is either a glvalue core constant expression whose value refers to an object with static storage duration or to a function, or a prvalue core constant expression whose value is an object where, for that object and its subobjects:

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

  • each non-static data member of reference type refers to an object with static storage duration or to a function, and
  • 引用类型的每个非静态数据成员是指具有静态存储持续时间或对象的对象,和

  • if the object or subobject is of pointer type, it contains the address of an object with static storage duration, the address past the end of such an object (5.7), the address of a function, or a null pointer value.
  • 如果对象或子对象是指针类型,则它包含具有静态存储持续时间的对象的地址,超过此类对象的结尾的地址(5.7),函数的地址或空指针值。

So changing the declaration of x like so would work:

所以改变x的声明就好了:

constexpr static int x{20};

#3


5  

Like T.C. says, the initializer needs to be an object with static storage duration.

像T.C.说,初始化程序需要是一个具有静态存储持续时间的对象。

N4140/§5.19/4 A constant expression is either a glvalue core constant expression whose value refers to an object with static storage duration [...]

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

N4140/§7.1.5/9 A constexpr specifier used in an object declaration declares the object as const. Such an object shall have literal type and shall be initialized. [...] Otherwise, or if a constexpr specifier is used in a reference declaration, every full-expression that appears in its initializer shall be a constant expression.

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

In N3337, the wording is different.

在N3337中,措辞不同。