プログラミング言語C++における条件演算子(conditional operator) ?:
と、子クラスから親クラスへの型推論に関してメモ。
条件演算子の第2, 3項目に親クラスParent
から派生した子クラスChild1
, Child2
を指定した場合、C++では型推論に失敗してコンパイルエラーとなる。(両者の共通型Parent
への型推論は行われない)
class Parent {}; class Child1 : public Parent {}; class Child2 : public Parent {}; bool b = /*...*/; Child1 c1; Child2 c2; auto r = b ? c1 : c2; // ★NG: ill-formed // GCC: operands to ?: have different types 'Child1' and 'Child2' // Clang: incompatible operand types ('Child1' and 'Child2') // MSVC: ':': no conversion from 'Child2' to 'Child1'
下記コードのように、共通の親クラス参照型へと明示的にキャストstatic_cast<Parent&>(x)
すれば良い。注意:親クラス型Parent
へのキャストではオブジェクトのスライシングが生じ、C++プログラマの意図に反した振る舞いになるはず。
// OK: rはParent&型 auto r = b ? static_cast<Parent&>(c1) : static_cast<Parent&>(c2);
C++14, 5.16/p5より引用(下線部は強調)。
Otherwise, the result is a prvalue. If the second and third operands do not have the same type, and either has (possibly cv-qualified) class type, overload resolution is used to determine the conversions (if any) to be applied to the operands (13.3.1.2, 13.6). If the overload resolution fails, the program is ill-formed. Otherwise, the conversions thus determined are applied, and the converted operands are used in place of the original operands for the remainder of this section.