【问题标题】:Compiler error for conditional operator "?:" when used with typecasting operator与类型转换运算符一起使用时条件运算符“?:”的编译器错误
【发布时间】:2012-01-09 14:15:32
【问题描述】:

以下代码是最简单的形式:

struct X {
  operator char () const { return 'a'; }
};

int main ()
{
  X obj, *p = &obj;
  char a = *p;  // ok
  char c = (true)? *p : 'z';
}

This code 给出编译器错误,

错误:? 的操作数:具有不同的类型'X'和'char'

当类型转换运算符的class X 没有歧义时,为什么*p 不解析为char? 这样的虚假错误信息是正确的还是 g++ 错误?

[更新注意:有趣的是this scenario doesn't generate such error]

【问题讨论】:

  • 我使用 g++ 4.4.5 构建它,带有标志 -Wall 和 -Wextra,并且没有收到错误或警告。
  • 哪个编译器会产生这个错误?在 g++ 4.6.1 上运行良好

标签: c++ compiler-errors conditional-operator typecasting-operator


【解决方案1】:

在某些 G++ 版本中,条件运算符 ?: 的类之间存在隐式转换问题。此外,根据版本,您可能会看到错误,或者您可能/未/看到此类错误,但是您的所有三个示例都被 G++ 正确标记

这不是对原始问题的回答,而是对原始发布者和其他人的重新认证,担心 G++ 编译器和 ISOC++ 中指定的类类型的转换行为可能存在虚假错误问题:2003 5.16/3 [expr.cond]/3(@Nawaz 在上面也有概述)

here 显示了与原始海报样本相反的一个示例,其中可以在两个方向上发生隐式转换但未标记。

我在 G++ v3.4.6、v4.1.2、v4.2.1 和 v4.5.0(windows) 上编译了它,没有发现任何问题,因为 @Nawaz 再次表示这是 ISOC++:2003 规范中的正确行为。

但是,当我点击您的IDEONE 页面上的链接时,结构定义有所不同, 是您错误的根源。

struct X
{
  char ch;
  X(const char c) : ch(c) {}

  operator char () const { return ch; }
};

int main ()
{
  X obj('a'), *p = &obj;
  char a = *p; // ok
  char c = (true)? *p : 'b';
}

那么如上所述结构是不同的,我确实得到了你看到的错误。 这是一个正确的错误,因为 'z' 可以转换为 X 或 char,并且由于构造函数 'z' 也可以转换为 X - X/'z' 的双向性,所以编译器应该停止。 但是,只要稍作改动,它就可以通过,这与上面发布的 GNU G++ 错误完全相同。

如果您将上面的示例转换为指针示例,它将失败。字符指针,整数指针或其他。

虽然不相关,但我认为在 Windows/Linux 之间进行交叉移植时,强调一些经常让我感到困惑的东西可能是一个好点。如果 MSVC 认为转换是“安全的”,它通常会很高兴地通过此类转换,或者它通常可能会发出警告,表明正在执行转换时存在精度损失的风险——我不确定允许这种转换的触发器是什么。

【讨论】:

    【解决方案2】:

    这似乎是一个编译器错误。我在规范中检查了它,标准明确表示(§5.16/3 - C++03),

    否则,如果第二个和第三个操作数具有不同的类型,并且其中一个具有(可能是 cv 限定的)类类型,会尝试将这些操作数中的每一个转换为另一个的类型 .

    本节的其余部分解释了转换是如何完成的。没有什么可以阻止 *p 使用用户定义的转换运算符隐式转换为 char 类型。

    另外,我用(GCC) 4.5.0 编译它。它没有错误,-pedantic 选项也是如此。试过-std=c++98-std=c++0x。仍然没有错误。

    毫无疑问,这是一个编译器错误。

    【讨论】:

    • 编译器不应该根据结果类型评估*p'z'吗?或者还有什么我可能会遗漏的东西?
    • @Nawaz +1 啊,现在我明白为什么了。谢谢。
    • 哇...C++ 有时肯定会让你大吃一惊。
    【解决方案3】:

    错误是正确的。 ?: 的操作数有不同的类型:第一个是“X”,第二个是“char”。编译器无法知道您最终希望表达式成为 char - 这将在稍后对整个表达式 (true)? *p : 'z'; 进行评估之后发生 - 由于类型差异,首先无法进行评估。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-04-22
      • 2013-05-14
      • 1970-01-01
      • 2016-06-28
      • 1970-01-01
      • 2014-10-04
      • 1970-01-01
      相关资源
      最近更新 更多