yohhoyの日記

技術的メモをしていきたい日記

条件演算子と親クラスへの型推論(C++編)

プログラミング言語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.