78

这是我之前的问题的后续问题,其中明显的共识是,prvalues 的 cv 限定处理的变化只是一个相当小的和无关紧要的变化,旨在解决一些不一致的问题(例如,返回 prvalues 并声明为 cv 限定返回的函数类型)。

但是,我在标准中看到另一个地方似乎依赖于具有 cv 限定类型的纯右值:const通过临时实现转换使用纯右值初始化引用。相关措辞可在9.3.3/5的多个位置找到

[...] 如果转换后的初始值设定项是纯右值,则其类型 T4 调整为类型“cv1 T4” ([conv.qual]) 并应用临时实现转换 ([conv.rval]) [...]

[...] 否则,初始化表达式被隐式转换为“cv1 T1”类型的纯右值。应用临时实现转换并将引用绑定到结果。

目的显然是为了确保当我们进行实际的临时物化转换时

7.3.4 临时物化转换
1 T 类型的纯右值可以转换为 T 类型的 xvalue。这种转换通过使用临时对象评估纯右值,从纯右值初始化 T 类型的临时对象([class.temporary])它的结果对象,并产生一个表示临时对象的 xvalue。[...]

它作为输入接收的类型T包括所需的 cv 限定。

但是,在非类非数组纯右值的情况下,该 cv-qualification 如何在7.2.2/2中存活下来?

7.2.2 类型
2如果prvalue 最初具有类型“cv T”,其中T 是无cv 限定的非类、非数组类型,则表达式的类型在任何进一步分析之前调整为T。

或者是吗?

例如,在这个例子中我们得到什么样的临时

const int &r = 42;

是临时的const还是不是?我们能做到吗

const_cast<int &>(r) = 101; // Undefined or not?

不触发未定义的行为?如果我没记错的话,最初的意图是const int在这种情况下获得一个临时的。还是真的吗?(对于类类型,答案很明确——我们得到一个const临时的。)

4

1 回答 1

1

你为什么怀疑7.2.2的语言?cv 限定符在非类、非数组纯右值上被丢弃似乎非常明确,因此临时实现中的类型 T 是非常量、非易失性类型。

如果不是这种情况,那么您将无法将纯右值绑定到非 const 右值引用。然而,该标准似乎极有可能旨在接受以下程序:

#include <type_traits>

template<typename T> void
f(T &&t)
{
  static_assert(std::is_same_v<decltype(t), int&&>);
  ++t;
}

int
main()
{
  f(5);
}
于 2021-06-13T05:13:04.350 回答