【问题标题】:Qualifier-losing conversion C++限定符丢失转换 C++
【发布时间】:2015-08-07 16:13:59
【问题描述】:

删除注释标记后,以下代码在 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;
}

这个问题与previously asked one 不同,因为没有整体const 限定符被抛弃。

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

对象指针可以显式转换为不同类型的对象指针。当对象指针类型的prvaluev转换为对象指针类型“pointer to cv T”时,结果为static_cast&lt;cv T*&gt;(static_cast&lt;cv void*&gt;(v))

在这种情况下,目标“指向cv T”的指针是const int * * *,这使得T = const int * * 没有cv 限定符。因此,结果应该是static_cast&lt;T*&gt;(static_cast&lt;void*&gt;(v))

T 的对齐存在一些限制,但与静态断言中所示的此处无关。由于reinterpret_cast&lt; const int * * * &gt;( a ) 的结果实际上可以使用中间步骤计算,因此如果未注释,注释代码应该可以编译。

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

【问题讨论】:

  • 根据 [expr.const.cast]p8,通过 [expr.reinterpret.cast]p2 禁止这样做。
  • @dyp:我读到 [expr.const.cast]p8 “有条件地支持将函数指针转换为对象指针类型或反之亦然。”,但我认为它不应该在这里应用,因为不涉及函数指针。
  • 您引用的是 [expr.reinterpret.cast]p8。我指的是 [expr.const.cast]p8 和 [expr.reinterpret.cast]p2。
  • 是的,我看错了你的评论 ;-)

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


【解决方案1】:

N3690 5.2.11/8:

以下规则定义了称为抛弃常量的过程。在这些规则中,TnXn 代表类型。对于两种指针类型:

X1T1 cv1,1* ... cv1, N* 其中T1 不是指针类型

X2T2 cv2,1* ... cv2, M* 其中T2 不是指针类型

K 为 min(N,M)

如果对于非指针类型 T 不存在来自以下的隐式转换(第 4 条),则从 X1 转换为 X2 会放弃常量:

T cv1,(N-K+1)* cv1,(N-K+2)* ... cv1,N*

T cv2,(M-K+1)* cv2,(M-K+2)* ... cv2,M*

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

的隐式转换

T cv1,1* cv1,2* = @ 987654357@

T cv2,2* cv2,3* = @ 987654361@?

没有;因此,你的演员抛弃了 constness。

当然我们有 5.2.10/2:

reinterpret_cast 运算符不应抛弃 constness (5.2.11)。

【讨论】:

  • 您使用的是哪个版本的标准/草案?
猜你喜欢
  • 2018-05-04
  • 1970-01-01
  • 2014-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多