与类型转换操作符一起使用时,条件运算符“?:”的编译器错误

时间:2011-11-30 10:19:45

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

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

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'

如果*p对于类型转换操作符没有歧义,为什么char未解析为class X? 这样的虚假错误消息是正确的还是g ++错误?

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

3 个答案:

答案 0 :(得分:8)

这似乎是一个编译器错误。我在规范中检查过,标准清楚地说(§5.16/ 3 - C ++ 03),

  

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

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

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

绝对是,它是一个编译器错误。

答案 1 :(得分:2)

条件运算符的类之间存在隐式转换的问题?:在某些版本的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 - 'z'的双向性,因此编译器应该停止。 但是稍微改变就可以通过,这与上面发布的GNU G ++错误完全相同。

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

虽然不相关,但我认为在Windows / Linux之间交叉移植时突出显示经常让我感到困惑的东西可能是一个好点。如果MSVC认为转换是“安全的”,或者通常可能会发出转换正在进行转换的风险,那么MSVC会很乐意通过这种转换 - 我不确定允许转换的触发器是什么。

答案 2 :(得分:0)

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