将非 class 非数组纯右值转换为 cv 限定类型是否合法?

Is it legal to cast a non-class non-array prvalue to a cv-qualified type?

我正在阅读 value categories,并发现了以下内容(为简洁起见省略了很多):

The following expressions are prvalue expressions:

  • a literal (except for string literal), such as 42, true or nullptr;

Properties:

  • A non-class non-array prvalue cannot be cv-qualified.

但是...下面的程序编译和运行良好 on ideone.com 并且使用 g++ 5.4.0:

#include <iostream>

int main() {
    std::cout << ((const int) 42) << std::endl;
}

我知道编译器会提供扩展,并且可以在遇到未定义行为时执行各种操作。我只是想弄清楚标准的要求。

N4296中找到相关段落如下:

[expr]

[ ... content omitted ... ]

  1. If a prvalue initially has the type “ cv T ,” where T is a cv-unqualified non-class, non-array type, the type of the expression is adjusted to T prior to any further analysis.

"initially" 这个词让我很吃惊。目前尚不清楚这是否被允许作为另一个表达式的结果,例如用户将非 class 非数组纯右值显式转换为 cv 限定类型(产生另一个纯右值),或者这是否适用只有 "root" 表达式(在本例中为 42)。

我的问题是,标准是否允许这样的表达式(只是去掉了 cv 限定符),还是不允许这样的表达式(如果相关,这是在哪里强制执行的)?

您应该知道 cppreference 不是规范的。 "Cannot"可能有两种读法:

  • 禁止,阿拉"shall not"

  • 这根本不可能发生,ala invariants

您在文中列出的引述:

If a prvalue initially has the type “ cv T ,” where T is a cv-unqualified non-class, non-array type, the type of the expression is adjusted to T prior to any further analysis.

向我建议,cv 限定的纯右值会删除限定条件,就像数组可以衰减为指针一样(澄清一下,这条规则不会发生在转换格式错误的地方)。缺陷 #1261 确实使语言非常明确地说明了在何处发生的事情。

感谢 SanderDeDycker 指出要在其中搜索的标准的相关部分。

我的问题在 N4296 的以下部分得到了回答(强调我的):

[expr.cast]

  1. The result of the expression (T) cast-expression is of type T . The result is an lvalue if T is an lvalue reference type or an rvalue reference to function type and an xvalue if T is an rvalue reference to object type; otherwise the result is a prvalue. [ Note: if T is a non-class type that is cv-qualified, the cv-qualifiers are discarded when determining the type of the resulting prvalue; see Clause 5. — end note ]

因此我们可以得出结论,(const int) 42 等表达式是完全合法的 C++。