【问题标题】:In C++, can a C-style cast invoke a conversion function and then cast away constness?在 C++ 中,C 风格的强制转换可以调用转换函数然后抛弃 const 吗?
【发布时间】:2017-01-06 00:12:25
【问题描述】:

GCC 和 Clang 都拒绝以下代码中的 C 样式转换。

http://coliru.stacked-crooked.com/a/c6fb8797d9d96a27

struct S {
    typedef const int* P;
    operator P() { return nullptr; }
};
int main() {
    int* p1 = const_cast<int*>(static_cast<const int*>(S{}));
    int* p2 = (int*)(S{});
}
main.cpp:在函数'int main()'中: main.cpp:7:25:错误:从类型“S”到类型“int*”的无效转换 int* p2 = (int*)(S{}); main.cpp:7:15:错误:无法从类型“S”转换为指针类型“int *” int* p2 = (int*)(S{}); ^~~~~~~~~~~

但是,根据标准,C 样式转换可以执行由static_cast 后跟const_cast 执行的转换。这段代码格式正确吗?如果没有,为什么不呢?

【问题讨论】:

  • 我一直在关注规范,现在试图弄清楚这一点。该规范非常不清楚它如何确定在尝试执行static_castconst_cast 时使用的类型。如果它尝试按照您描述的方式执行它们,它绝对会起作用,但如果它尝试只执行const_cast&lt;int*&gt;(static_cast&lt;int*&gt;(S{}))),那么它肯定会失败。我不知道编译器如何知道尝试在此处添加const,但规范似乎没有说明任何关于该主题的内容...
  • @templatetypedef 显然“static_cast 后跟 const_cast”的情况将在这两种情况下使用不同的类型,因为一种是 const 限定的,一种不是
  • @M.M 就是这样——规范实际上并没有说编译器应该尝试在任何地方添加const。它只是说“先尝试static_cast,然后再尝试const_cast”,并没有说明如何选择static_cast 使用的类型。
  • @Yakk 也许布赖恩的情况是无效的,因为static_cast&lt;int const *&gt; 后跟 const_cast 是可能的,但 static_cast&lt;int const * const&gt; 后跟 const_cast 也是可能的,因此它是模棱两可的。但我认为这表明标准措辞有缺陷,正如 templatetypedef 所暗示的那样
  • 额外的 const 似乎毫无意义,但无论如何都可以将其转换为 const volatile,然后将 const_cast 两者都去掉。

标签: c++ language-lawyer


【解决方案1】:

这是core issue 909

根据 5.4 [expr.cast] 第 4 段,一种可能的解释 旧式演员表是static_cast,后跟const_cast。一 因此会期望在 以下示例将具有相同的有效性和含义:

struct S {
  operator const int* ();
};

void f(S& s)  {
  const_cast<int*>(static_cast<const int*>(s));  // #1
  (int*) s;  // #2
}

但是,许多实现在 #2 上发出错误。

(T*)x 的意图是否应该被解释为类似

const_cast<T*>(static_cast<const volatile T*>(x))

理由(2009 年 7 月):

根据对措辞的直接解释,该示例应该有效。这似乎只是一个编译器错误。

显然,Clang 和 GCC 都没有解决这个问题。是时候开票了。

【讨论】:

    猜你喜欢
    • 2023-03-16
    • 1970-01-01
    • 2010-09-27
    • 2010-10-14
    • 2015-07-19
    • 1970-01-01
    • 1970-01-01
    • 2021-12-02
    • 2013-07-29
    相关资源
    最近更新 更多