jac*_*k X 22 c++ language-lawyer c++20
#include <iostream>
int main(){
using type = int[2];
static_cast<type>(type{1,2}); //#1
}
Run Code Online (Sandbox Code Playgroud)
锵和GCC都抱怨这#1是形成不良的,并给予怪异的诊断。
Clang 报告
static_cast from 'int *' to 'type' (aka 'int [2]') is not allowed
Run Code Online (Sandbox Code Playgroud)
海湾合作委员会报告
invalid 'static_cast' from type 'type' {aka 'int [2]'} to type 'type' {aka 'int [2]'}
Run Code Online (Sandbox Code Playgroud)
但是,根据expr.static.cast#4
如果存在从 E 到 T的隐式转换序列([over.best.ics]),则表达式 E 可以显式转换为类型T
把一个类型转换成同一个类型不就叫恒等转换吗?
over.best.ics#general-8
如果不需要转换来将参数与参数类型匹配,则隐式转换序列是由身份转换 ([over.ics.scs]) 组成的标准转换序列。
我认为这里的一个关键规则是
转换序列是 [conv] 中定义的隐式转换,这意味着它受对象的初始化规则或单个表达式([dcl.init]、[dcl.init.ref])的引用的控制。
这意味着,假设一个结果对象将由t纯右值初始化。
static_cast from 'int *' to 'type' (aka 'int [2]') is not allowed
Run Code Online (Sandbox Code Playgroud)
#2也被 Clang 和 GCC 拒绝了。但是,这种情况应该被dcl.init.general#15.9捕获
否则,被初始化的对象的初始值是初始化表达式的(可能转换的)值。如有必要,将使用标准转换序列 ([conv]) 将初始值设定项表达式转换为目标类型的 cv 非限定版本;不考虑用户定义的转换。如果无法完成转换,则初始化格式错误。当用它不能表示的值初始化位域时,位域的结果值是实现定义的。
纯右值是一个表达式,其求值初始化一个对象或计算一个运算符的操作数的值,如它出现的上下文所指定,或者是一个类型为 cv void 的表达式。
在这种情况下,不是类型的纯右type值不能初始化结果对象吗?
Clang 假定数组到指针的转换适用于操作数。但是,只有当项目符号进入expr.static.cast#8时才允许这种转换。换句话说,此处的转换不适用于第 4 项中的操作数。
GCC 给出了更不合理的诊断。我想知道为什么 Clang 和 GCC 禁止显式转换?
原始数组很难以数组形式保存 - 在纯右值上下文中,数组会衰减为指针。
\n但它static_cast也适用于上下文吗?规则在[expr.static.cast]中概述...
我们不会转换为引用,因此我们跳过前 3 个子句并到达[expr.static.cast]/4:
\n\n\n如果存在从到...的隐式转换序列 ( [over.best.ics] ),
\nE则可以将表达式显式转换为类型。TET
这是行不通的,因为([conv.general]/3):
\n\n\n对于某些发明的临时变量,当且仅当声明\n格式良好时,表达式
\nE可以隐式转换为类型TT t=E;t
并且int t[2] = int[2]{1, 2};格式不正确。初始化数组的唯一合法方法在[dcl.init.general]/15.5中指定:
\n\n...如果目标类型是数组,则对象按如下方式初始化。令x 1 , \xe2\x80\xa6, x k为表达式列表的元素。...第 i个数组元素使用x i进行复制初始化,每个 1 \xe2\x89\xa4 i \xe2\x89\xa4 k。
\n
这里没有“展开”int[2]{1, 2}到表达式列表中的规定。
\n\n否则,结果对象将直接从 初始化
\nE。
同样,由于格式不正确,这也不起作用int x[2](int[2]{1, 2});。
请注意,聚合中有一个关于数组的特殊规定,它允许轻松复制(例如std::array)。原始数组中没有这样的处理。
我们跳过5。6、7 不适用。这将我们带到[expr.static.cast]/8:
\n\n\n左值到右值 ([conv.lval])、数组到指针([conv.array]) 和函数到指针 ([conv.func]) 转换应用于操作数。
\n
\n。。。
就是这样,强制转换无效。Clang 和 GCC 似乎都是正确的。错误报告略有不同,因为 Clang 报告衰减类型,而 GCC 报告原始类型。
\n作为解决方法,转换为引用类型:static_cast<type&&>(type{1,2});。
| 归档时间: |
|
| 查看次数: |
426 次 |
| 最近记录: |