为什么我不能在这里使用三元运算符?

时间:2014-10-03 23:56:46

标签: c++ variables expression variable-assignment

这条线不会编译:

Shape shape = (i % 2) ? Circle(5) : Rectangle(5, 5);

(我知道它没用,因为表达式返回的内容将简化为一个简单的Shape,这不是重点。

无法弄清楚它为什么不能编译。我正在创建一个名为Shape的{​​{1}}变量(我认为此时会创建一个新的shape),然后我将此变量指定为表达。为什么不编译?

错误:

Shape

真正奇怪的是,具有完全相同含义的较长代码 按预期编译和运行:

no match for ternary operator

3 个答案:

答案 0 :(得分:9)

条件运算符的详细转换规则相当复杂(如果您感兴趣,可以在this answer中找到标准的完整引用)。缺点是,当与类类型的对象一起使用时,它将尝试转换其第二个操作数以匹配第三个操作数的类型,并将其第三个操作数与第二个类型匹配,但它不会尝试将两者都转换为第三类类型。

由于Circle无法转换为RectangleRectangle无法转换为Circle,编译器会抱怨(好吧,除非这两种类型定义了一些奇数转换为指针,作用域枚举或算术类型,在这种情况下§5.16[expr.cond] / p5发挥作用。)

另请注意,您的作业将对对象进行切片,probably isn't a good idea

答案 1 :(得分:5)

条件运算符的第二个和第三个操作数必须具有公共类型,可以使用std::common_type特征确定。有趣的是,从公共基类派生的两个类 not 将该基类作为公共类型,因此指针或引用也不相关。进一步的思考很快就表明这样的概念确实没有意义:两个类可以有任意数量的基类,一般都没有办法选择一个独特的,首选的基础。

如果要在条件运算符中使用派生类,则必须自己明确地转换类型。

您的代码的更现实和明智的例子将是这样的:

Shape const & s = ask_user() ? static_cast<Shape const &>(show_me_a_circle())
                             : static_cast<Shape const &>(squares_all_the_way());

std::cout << "Your shape is " << s.get_colour() << ".\n";

答案 2 :(得分:2)

当条件运算符中两个分支的类型类型不同时,根据5.16 [expr.cond]第16段,需要将其转换为另一个:

  

否则,如果第二个和第三个操作数具有不同的类型并且具有(可能是cv限定的)类类型,或者两者都是相同值类别的glvalues和除cv-qualification之外的相同类型,则尝试将每个操作数转换为另一个操作数的类型。 ...

其他涉及的案例不适用:它们是void类型或一个throw表达式的分支。遗漏只是解释了如何尝试转换以及选择转换的情况(实际上,如果一个表达式的类型唯一地转换为另一个而不是相反的转换)。

假设您的CircleRectangle可转换为Shape,您可以将一个或两个表达式明确转换为Shape