【问题标题】:Cv-qualifications of prvalues in C++14C++14 中纯右值的 Cv 限定
【发布时间】:2017-03-23 23:52:18
【问题描述】:

似乎 C++11 和 C++14 对待纯右值的 cv 限定不同。

C++11 坚持自 C++98 以来一直存在的“经典”方法:根据 3.10/4 “非类纯右值始终具有 cv 非限定类型”

C++14 在 3.10/4 中包含类似的措辞,但它以注释的形式呈现:"[注意:类和数组纯右值可以有 cv 限定类型;其他纯右值总是有 cv 非限定类型. 见第 5 条。——尾注]"

在第 5 条中它说:

6 如果纯右值最初的类型为“cv T”,其中 T 是 cv 不合格的非类、非数组类型,则表达式的类型在任何进一步的分析。1

这个 5/6 条目是 C++14 中的新条目。它现在使用与引用类型结果相同的方法处理纯右值的 cv 限定(参见 5/5)。

这种变化的原因可能是什么? C++11 及之前的版本拒绝非类纯右值拥有任何 cv 资格的权利。 C++14 表示非类、非数组纯右值可以具有 cv 限定,但这些 cv 限定在在任何进一步分析之前被丢弃

我的猜测是,有一些新的(针对 C++14 的)语言特性可以在适当的情况下(在上述调整发生之前)以某种方式“看到”纯右值的 cv 限定。它们存在吗?如果有,这些功能是什么?2


问题源于以下上下文:想象一个编译器在内部将 X 类的隐藏参数 this 实现为 X *const 类型的变量。由于编译器需要将this 公开为纯右值,因此const 不应该在C++11(或之前)中导致任何问题,其中标量纯右值永远不是cv 限定的。但是 C++14 呢?如果同一个编译器将this 暴露为X *const 类型的纯右值,会不会导致问题?


1 C++14 中的 5/6 和 3.10/4 中的注解似乎有矛盾,但注解无论如何也不是规范的。我正在使用文本的草稿版本。

2 我最初的猜测是decltype。而且我什至以为我在尝试的时候找到了答案

std::cout << std::is_same<decltype((const int) 0), const int>::value << std::endl;

在 GCC 中,输出 1。但是,看到 Clang 和 VC++ 输出 0(并且 decltype 的规范似乎不支持这种行为)我倾向于认为这只是 GCC 中的一个错误(从 6.1 开始)

【问题讨论】:

  • @Neil Butterworth:这是一个关于概念行为的问题。我问这个问题的全部原因是我无法找到任何可以利用 C++11 和 C++14 之间的上述差异的代码示例。如果差异无法通过代码来演示,那么我想知道是什么促使标准文本发生了变化。如果差异可以通过代码来演示,那么很高兴看到该代码。
  • @Thomas 这绝对是语言律师领域。
  • @Neil Butterworth:太好了。那么,新措辞“更准确或更细致”在哪些方面?这基本上就是我的问题所在。
  • 这是核心问题 1261,在公共问题列表中的讨论为零,但我认为这只是措辞清理。例如,给定const int f();f() 是一个prvalue,根据[expr.call],它的类型是“静态选择函数的返回类型”,即const int,某种措辞是需要让 const 消失。
  • 嗯,是的,GCC 曾经遇到过S*&amp;&amp; p = this; 之类的代码问题。现在他们没有了。

标签: c++ c++11 c++14 language-lawyer


【解决方案1】:

根据commit on github,这样做是为了解决CWG1261: Explicit handling of cv-qualification with non-class prvalues

根据问题的 cmets,this(正式的 prvalue)的类型类别似乎存在令人惊讶的变化空间,而 gcc formerly 和 MSVC 目前改为使用 常量左值.

措辞收紧漏洞以明确表示,例如,即使 this 是某种编译器内部魔法,X* const 类型的纯右值,在任何进一步分析之前调整为X*

同样,您给出的示例确实看起来像 gcc 错误。可能decltype 在应用 c 样式转换之前没有查看值类型。

它现在是 [basic.lval]/4 中的注释的原因是它现在是 [expr]/6 中的新文本的结果,而不是在 [basic.lval]/4 中指定规则。

完全归功于 T.C. 在 cmets 中基本回答了这个问题,包括对 gcc 错误修复的引用,以及以前未充分指定的行为的各种其他示例 cv-qualified non-类非数组纯右值.

【讨论】:

  • Jason Merrill 写道“当 'this' 出现在表达式中时,它应该是右值而不是 const 左值;在 C++11 中,区别很重要。” C++11?在 C++ 历史的任何时候,右值都不像 const 左值。
  • @curiousguy;在 C++11 之前,您不能使用 decltype 和右值引用来区分它们(但也许 const_cast 可以做到这一点?)。
  • @DavisHerring 你的意思是C * const &amp;that = this; const_cast&lt;C*&amp;&gt;(that) = new C;
  • @curiousguy:只是const_cast&lt;C*&amp;&gt;(this)——分配给它可能是未定义的行为,但如果它是一个右值,那么强制转换不应该编译(如果我没记错我的 C++03)。跨度>
  • @DavisHerring 或者干脆&amp;this
猜你喜欢
  • 2011-01-11
  • 2015-01-06
  • 2015-10-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-23
  • 2011-02-14
相关资源
最近更新 更多