【问题标题】:clang & gcc interpret series of cast differentlyclang 和 gcc 对 cast 系列的解释不同
【发布时间】:2019-07-12 19:03:27
【问题描述】:

以下内容:

#include <iostream>

int& addone(int& r) {
    return ++r;
}

int main() {
    std::cout << addone((int&)(int&&)7) << std::endl;
}

使用 clang 编译、运行和打印 8,即使使用 -Wall -Wextra -Werror -pedantic 也是如此。
然而,使用 gcc,它根本无法编译,甚至使用 -fpermissive 也无法编译。

这里哪个是正确的? (最好带引号)

clang 结果here,gcc 结果here

【问题讨论】:

  • 请注意,两个编译器都可能是“正确的”。在很多 UB 情况下,编译器不需要打印诊断信息。
  • 它所做的“显而易见的事情”是什么?我看不到在尝试增加文字时应该发生任何明显的事情
  • 黄金法则是:如果有疑问,gcc 是正确的。这些年来,我发现 clang 是非常宽容的。我从来不会在没有先在 gcc 上测试的情况下发布使用 clang 编译的软件。
  • @sp2danny 你应该edit 你的问题包括预期的行为、观察到的行为和错误消息。
  • @RichardHodges 我见过很多相反的例子。即使 MSVC 是唯一正确的。所以规则是:如果其中一个编译器对 Godbolt 有不同意见,那么肯定有错误。使用您的代码(更有可能)或使用某些编译器。

标签: c++ language-lawyer


【解决方案1】:

看来第一次转换没问题。您将整数文字 - 纯右值 - 转换为右值引用。这会导致临时实现转换:

[conv.rval] T 类型的纯右值可以转换为 T 类型的 xvalue。 此转换通过以临时对象作为其结果对象评估纯右值,从纯右值初始化 T 类型的临时对象 ([class.temporary]),并产生一个表示临时对象的 xvalue。 p>

让我们考虑转换为左值引用:

[dcl.init.ref] 对“cv1 T1”类型的引用由“cv2 T2”类型的表达式初始化,如下所示:

如果引用是左值引用和初始化表达式

  • 是左值(不适用,表达式不是左值)

  • 有类类型(不适用,类型为int&&)

否则,如果引用是左值引用,则指向非 const-qualified 或 volatile-qualified,则程序格式错误。 (适用)

看来程序格式不正确。缺少来自 clang 的诊断表明存在编译器错误。

【讨论】:

  • 类类型段指的是 conversions,其中 T1 和 T2 与引用无关。
  • 相关段是:否则,引用应该是对非易失性const类型的左值引用(即cv1应该是const),或者引用应该是右值引用
  • 然而,这一切都适用于演员阵容吗?
  • @sp2danny 我不确定了。可能缺少某些规则,或者我刚刚查找了错误的部分。
  • 我发现关于强制转换:(8.5.1.9) 任何标准转换序列的逆序列(第 7 条)不包含左值到右值 (7.1) , ..., 可以使用 static_cast 显式执行
猜你喜欢
  • 2021-09-25
  • 1970-01-01
  • 1970-01-01
  • 2016-02-18
  • 1970-01-01
  • 2018-11-03
  • 2016-01-08
  • 1970-01-01
  • 2020-10-27
相关资源
最近更新 更多