提问人:Jan Schultke 提问时间:9/16/2023 最后编辑:Jan Schultke 更新时间:10/5/2023 访问量:267
你能将常量 T*&& 绑定到 T* 类型的 xvalue 吗?
Can you bind a const T*&& to an xvalue of type T*?
问:
请考虑以下代码:(https://godbolt.org/z/8W699x6q6)
int* p;
const int*&& r = static_cast<int*&&>(p);
注意:const int*&&
是对指向 const int
的指针的右值引用。
Clang 编译它,并绑定到一个临时对象:r
p: .quad 0
r: .quad _ZGR1r_ // r is a reference to a temporary object, otherwise this would be p
GCC 拒绝以下代码:
<source>:2:18: error: binding reference of type 'const int*&&' to 'int*' discards qualifiers
2 | const int *&&r = static_cast<int*&&>(p);
| ^~~~~~~~~~~~~~~~~~~~~~
就我个人而言,我认为 GCC 正确地实现了 CWG 2352 对 [dcl.init.ref] p4 的更改,但我不相信我的解释是正确的。 这里哪个编译器是正确的?
注意:本问题中的示例灵感来自CWG 2018中提到的最后一行代码。
注意:如果允许将 const
int*&& 绑定到 int*&&
,这将提供一个 const 正确性脚枪。这与将 int
** 转换为 const int**
的问题相同。就我个人而言,我认为委员会不太可能希望允许这种引用绑定,但是,尽管有缺陷报告,但措辞可能仍然允许这样做。
答:
是的,GCC 在这里是正确的。[dcl.init.ref]#4 和 [dcl.init.ref]#5.3.1 中的措辞仅在 T1 和 T2 具有相似的限定分解时才适用,因为指向 T1 的 prvalue 指针可以转换为指向 T2 的指针。
在这里,它们各自尝试转换的顺序是 和 。如果 绑定到指针(又名 cv0,在比较 cv 签名时不考虑),则这些类型将是兼容的,因为它们将具有相似的序列。但相反,分解 Tj 与 T2 不匹配,并且由于 prvalue 转换的要求是 Tj 与 T2 相同,因此它们并不相似。这意味着转换序列格式不正确,因此绑定格式不正确。* pcv1, * U, [int]
* pcv1, * const U, [int]
const
它格式错误的原因是,使用左值引用,通过将 a 绑定到 a ,您将能够修改对象。T*
const T*&
const
根据 [dcl.init.ref]/4 中给出的定义,
- “指针”与“指针”的引用不兼容,因为不能转换为 。
const int
int
int**
const int**
- “指针”与“指针”的引用相关,因为这两种类型相似。
const int
int
引用兼容性控制何时可以进行直接绑定。这种直接绑定必须尊重常量正确性:如果一个对象可以通过引用 non-const 来引用,那么 a 的值可以通过 写入,从而将其值复制到 中。因此,这种直接绑定是不允许的。但是,如果引用类型本身是 const(即引用类型是 ),则它与 [conv.qual]/3 下的引用兼容。(Bullet 3.3 需要额外的 。int*
p
r
const int*
const int*
r
p
const int* const
int*
const
如果存在必要的引用兼容关系,则此引用绑定将由 [dcl.init.ref]/5.3 控制。在本例中,由于引用的类型与初始值设定项的类型不兼容,因此我们转到 [dcl.init.ref]/5.4.2,这需要创建一个类型的临时对象;引用绑定到该对象,而不是初始值设定项。const int*
我同意OP的观点,即这一结果似乎是无意的。CWG2018将以下间接引用绑定称为“奇怪”:
- 引用绑定到
const int* const
int*
- 引用绑定到
const int*
int*
前者由CWG2352直接引用绑定。后者不能是直接绑定,因为这种直接绑定会违反 const 正确性,因此它应该是格式错误的。
使此引用绑定格式不正确的另一个理由是:
const int x = 0;
int&& r = std::move(x);
这不会复制和绑定对临时的引用;它格式不正确。在这种情况下,不允许创建临时的原因是引用的类型与初始值设定项的类型“太接近”了:也就是说,这两种类型是引用相关的。引用相关性导致 p5.4.3 启动:x
CV1 应与 CV2 相同或更高 CV 资格;[...]
CWG2352将参考相关性扩展到 OP 给出的案例。看来,起草过程中的疏忽导致了目前的不一致。
新创建的CWG2801提出了纠正该问题的措辞,使 OP 的代码格式不正确。
评论
T const*
T*
T* const
T const*
T*