与类型转换运算符一起使用时条件运算符"?:"的编译器错误

Compiler error for conditional operator "?:" when used with typecasting operator

本文关键字:错误 编译器 条件运算符 运算符 类型转换 一起      更新时间:2023-10-16

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

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

这段代码给出了编译错误,

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

为什么在class X没有歧义的情况下,*p不能解析为char ?虚假错误信息是正确的还是c++错误?

[Update注意:有趣的是这个场景不会产生这样的错误]

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

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

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

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

在某些版本的g++中,条件操作符?:在类之间存在隐式转换问题。同样,根据版本的不同,你可能会看到一个错误,或者你可能/不/看到这样的错误,然而,所有三个示例都被g++ 正确标记。

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

这里有一个与原始海报相反的例子,两个方向的隐式转换都可以发生,但没有标记。

我在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++错误完全相同。

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

虽然不相关,但我认为这可能是一个很好的观点,强调在Windows/Linux之间进行交叉移植时经常遇到的一些问题。如果MSVC认为转换是"安全的",它会很高兴地传递这样的转换,或者通常它可能会提供一个警告,即转换正在冒着失去精度的风险进行——我不确定允许这种情况的触发因素是什么。

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