以下代码是最简单的形式:
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]
答案 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';
的评估之后发生 - 由于类型差异而无法在第一时间完成的评估。