失去限定符的c++转换

Qualifier-losing conversion C++

本文关键字:c++ 转换 失去      更新时间:2023-10-16

当注释标记被删除时,下面的代码在MSVC2015和clang中都无法编译,但它会按原样编译。

int main()
{
    static_assert( alignof( int * ) == alignof( int * * ), "nope" );
    const int * * a = nullptr;
    //const int * * * b = reinterpret_cast< const int * * * >( a );
    auto c = static_cast< const int * * * >( static_cast< void * >( a ) );
    return 0;
}

这个问题与之前的问题不同,因为没有抛弃整体的const限定符。

根据标准[expr. reinterpretation .cast]/7

对象指针可以显式地转换为不同类型的对象指针。将对象指针类型的右值v转换为对象指针类型"指向cv T的指针",结果为static_cast<cv T*>(static_cast<cv void*>(v))

在这种情况下,目标"指向cv T的指针"是const int * * *,这使得T = const int * *而没有cv限定符。因此,结果应该是static_cast<T*>(static_cast<void*>(v))

有关于T对齐的约束,但这些约束在这里不相关,如静态断言所示。由于reinterpret_cast< const int * * * >( a )的结果实际上可以使用中间步骤计算,因此注释的代码在没有注释的情况下应该可以编译。

我的推理错误在哪里(如果有的话)?

N3690 5.2.11/8:

下面的规则定义了称为的丢弃constness的过程。在这些规则中,TnXn表示类型。对于两个指针类型:

X1 T1 cv <子> 1,1 *……cv1,N *,其中T1不是指针类型

X2 T2 cv <子> 2,1 *……cv2,M *其中T2不是指针类型

K为min(NM)

如果对于非指针类型T不存在从

到 的隐式转换(第4条),则从X1X2的强制转换将放弃constness:

T cv <子> 1,(N - K + 1) * cv <子> 1,(N - K + 2) *……cv1,N *

T cv <子> 2 (M - K + 1) * cv <子> 2 (M - K + 2) *……cv2、M *

在您的示例中,X1const int**,因此N为2,T1intcv1,1constcv1,2为空。X2const int***,因此M为3,T2intcv2,1constcv2,2cv2,3为空。K为2。是否存在从

的隐式转换?

T cv <子> 1,1 * cv <子> 1,2 * = T const**

T cv <子> 2,2 * cv <子> 2,3 * = T** ?

没有;因此你的cast抛弃了constness。

当然我们有5.2.10/2:

reinterpret_cast操作符不能丢弃constness(5.2.11)。