将 constexpr 引用绑定到不同类型的变量时出错

问题描述 投票:0回答:1

在C++中众所周知,初始化引用时,类型必须匹配。所以下面的代码片段会导致错误(全局范围内,下同):

unsigned i; 
int & p = i;  // error

但是对 const 的引用有一个例外,因此以下在允许类型转换的情况下是正确的:

unsigned i; 
const int & p = i;  // ok

但是如果我将

p
定义为
constexpr
,就会出现编译错误:

unsigned i; 
constexpr const int & p = i;  // error: the value of 'i' is not usable in a constant expression

错误消息说

i
不是 const,我认为这是无关紧要的,因为如果我将类型从有符号更改为无符号,即没有类型转换,则不会出现编译错误:

unsigned i; 
constexpr const unsigned & p = i;

const
这里可以省略。

所以,看来是类型转换导致了

中的编译错误
unsigned i; 
constexpr const int & p = i;  // error

但我不确定。你能告诉我什么 C++ 标准规则导致了这个错误吗?我在 C++20 下在 GCC 和 MSVC 中测试了上述代码。

c++ reference type-conversion language-lawyer constexpr
1个回答
3
投票

这部分:

unsigned i; 
int& p = i;

..无法编译,因为它需要将左值引用绑定到将

unsigned
转换为
int
时具体化的临时值。详情可以参考dcl.init.ref#5.2

否则,如果引用是对非 const 限定或 volatile 限定的类型的左值引用,则程序格式错误。

同时,C++ 允许将

const
引用绑定到这样的临时对象,因此这可以正常工作:

unsigned i; 
const int& p = i;

这部分内容由 dcl.init.ref#5.4.2:

涵盖

否则,初始化表达式将隐式转换为

T1
类型的纯右值。应用临时物化转换,考虑纯右值的类型为
cv1 T1
,并且引用绑定到结果。

但是,当使用

constexpr
时,您应该提供一个常量表达式,在这种情况下不满足:

unsigned i; 
constexpr const int& p = i;

如果在常量表达式中使用引用,则应按照 expr.const#14:

直接绑定它们

T
类型的转换常量表达式是一个表达式,隐式转换为
T
类型,其中转换后的表达式是常量表达式,隐式转换序列仅包含

...

以及引用绑定(如果有)直接绑定的位置。

当发生隐式转换时,无法进行直接限制,如 dcl.init.ref#5:

在除最后一种情况之外的所有情况下(即,将初始化表达式隐式转换为引用类型),引用被称为直接绑定到初始化表达式。

但是将常量表达式引用绑定到非临时全局变量仍然可以,因为它不涉及任何临时变量,所以编译得很好:

unsigned i; 
constexpr const unsigned& p = i;
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.