当前位置: 首页 > 知识库问答 >
问题:

为什么不能使用static_cast将数组类型的prvalue转换为相同的类型?

董嘉祯
2023-03-14
#include <iostream>
int main(){
    using type = int[2];
    static_cast<type>(type{1,2});  //#1
}

Clang和GCC都抱怨#1格式不正确,并给出了奇怪的诊断。

Clang报告

static_cast from 'int *' to 'type' (aka 'int [2]') is not allowed  

GCC报告

invalid 'static_cast' from type 'type' {aka 'int [2]'} to type 'type' {aka 'int [2]'}   

但是,根据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,它将由prvalue初始化。

type t = type{1,2};  // #2

#2也被Clang和gcc拒绝。但是,这样的情况应该被dcl.init.general#15.9捕获

否则,正在初始化的对象的初始值是初始值设定项表达式的(可能已转换的)值。如果需要,将使用标准转换序列([conv])将初始值设定项表达式转换为目标类型的cv-unqualified版本;不考虑用户定义的转换。如果不能进行转换,则表示初始化格式不正确。当用一个位字段不能表示的值初始化该位字段时,该位字段的结果值是实现定义的。

根据basic.lval#1.2

prvalue是一个表达式,其求值初始化对象或计算运算符的操作数的值(由其出现的上下文指定),或者是一个具有cv void类型的表达式。

在这种情况下,不是type类型的prvalue不能初始化结果对象吗?

Clang假设数组到指针的转换应用于操作数。但是,只有当项目符号进入expr.static.cast#8时,才允许这样的转换。换句话说,这里的转换不应适用于项目符号4中的操作数。

GCC给出了一个更不合理的诊断。我想知道为什么Clang和gcc禁止显式转换?

共有1个答案

卢作人
2023-03-14

原始数组很难保持数组形式--在prvalue上下文中,数组衰减为指针。

但是它是否也应用static_cast上下文?规则概述在[expr.static.cast]中...

我们没有强制转换到引用,因此我们跳过前3个子句,得到[expr.static.cast]/4:

如果存在从ET的隐式转换序列([over.best.ics]),则表达式E可以显式转换为类型T

这是行不通的,因为它会涉及数组到指针的衰减。

否则,将从e直接初始化结果对象。

这将不起作用,因为无法从另一个数组直接初始化数组(int x[2](int[2]{1,2});格式不正确)。

我们跳过5点。6、7不适用。这将使我们看到[expr.static.cast]/8:

操作数应用lvalue到rvalue([conv.lval])、数组到指针([conv.array])和函数到指针([conv.func])转换。
。..

就这样,演员阵容无效。Clang和GCC似乎都是正确的。错误报告略有不同,因为Clang报告衰变的类型,而GCC报告原始类型。

作为一种解决办法,转换为引用类型:static_cast (类型{1,2});

 类似资料:
  • 此代码有效。它以“未检查或不安全操作”警告进行编译和运行。 当这两个给我运行时错误时 我遇到的错误如下:

  • 所以,实际上我对Java编程语言还是新手,并且还在学习如何转换数据类型,所以在这种情况下,我很难将字节转换为短字节。你们能帮帮我吗?? 所以在这种情况下,我可以正常地从(int)转换为(long)数据类型,因为(long)数据大小大于(int)。这与我尝试将其从(short)转换为(int)时的情况相同。但为什么我不能使用这个概念将数据类型从(byte)转换为(short)??即使(短)数据大小大

  • 我不明白,为什么我会有这个错误: 04-24 22:11:51.263:W/System.err(27504):org.JSON.jsonException:Value不能转换为JSONArray

  • 问题内容: 有人可以向我解释为什么以下代码示例中标记的行不起作用吗? 具体来说,当我们说类型为时,这并不表示它的每个元素都是的实例吗?如果是这样,那么它是什么铸造的问题,如果我们都可以投射单个实例来? 谢谢。 问题答案: 问题是这样的: 如果对数组执行相同的操作,则在运行时会在第4行获得ArrayStoreException。对于泛型集合,已决定在编译时避免这种情况。

  • 问题内容: 考虑以下代码: 我们感到恐惧,而且显然令人费解: 协议“集合”具有自定义或相关类型要求,因此只能用作通用约束。 但是,这很容易编译: 为什么?! 特别是,编译器 不 知道如何关联的类型(类型)的已经实现; 它只能得到它们已经存在的 承诺 (因为任何类型的对象 都 必须实现它们)。第一个示例中也有同样的保证!那么,为什么编译器抱怨一个而不是另一个呢? 我的问题是:在代码行中,编译器如何知