此行无法编译:
Shape shape = (i % 2) ? Circle(5) : Rectangle(5, 5);
(我知道这是无用的,因为无论表达式返回什么,都将被简化为简单的Shape
,这不是重点)。
不知道为什么它不能编译,我创建了一个名为shape
的Shape
变量(我认为这会创建一个新的Shape
),然后我给这个变量赋值一个表达式的结果,为什么这个不能编译?
错误:
no match for ternary operator
真正奇怪的是,具有完全相同含义的较长代码 * 确实 * 按预期编译和运行:
Shape shape;
if (i % 2)
shape = Rectangle(5, 5);
else shape = Circle(5);
3条答案
按热度按时间b5buobof1#
条件运算符的详细转换规则相当复杂(如果你有兴趣,你可以在这个答案中找到标准的完整引用)。简短的说,当与类类型的对象一起使用时,它将试图转换它的第二个操作数以匹配第三个的类型,并转换它的第三个操作数以匹配第二个的类型,但它不会尝试将两者都转换为第三类类型。
由于
Circle
不能转换成Rectangle
,Rectangle
也不能转换成Circle
,编译器会抱怨(除非这两种类型定义了一些奇怪的转换,转换成指针、作用域枚举或算术类型,在这种情况下§5.16 [expr.cond]/p5会起作用)。还请注意,您的赋值将对对象进行切片,即probably isn't a good idea。
i34xakig2#
条件运算符的第二个和第三个操作数必须具有 common type,这可以通过
std::common_type
trait来确定。有趣的是,从一个公共基类派生的两个类 * 不 * 将该基类作为公共类型,指针或引用也不具有这样的相关性。进一步的思考很快表明,这样的概念确实没有意义:两个类可以具有任意数量的共同基类,并且通常没有办法选择唯一的优选基类。如果要在条件运算符中使用派生类,则必须自己显式地强制转换类型。
一个更实际、更合理的代码示例如下所示:
pcww981p3#
当条件运算符中两个分支的类型不同时,需要根据5.16 [expr.cond]第16段将一个分支转换为另一个分支:
否则,如果第二个和第三个操作数具有不同的类型,并且其中一个具有(可能是cv限定的)类类型,或者如果两者都是相同值类别的glvalue,并且除了cv限定之外具有相同的类型,则尝试将这些操作数中的每一个转换为另一个的类型。
所提到的其他情况不适用:它们是关于类型是
void
或一个分支是throw
表达式的。省略只是解释了如何尝试转换以及在哪些情况下选择转换(本质上,如果一个表达式的类型唯一地转换为另一个,而不是相反)。假设您的
Circle
或Rectangle
可转换为Shape
,您可以显式地将一个或两个表达式转换为Shape
。