C++訳分からなすぎワロタ (4) 三項演算子とアップキャスト

前からこれが不満だった...

struct B { };
struct D1 : B { };
struct D2 : B { };

int main(int argc, char *argv[]) {
//  B *pb0 = (argc > 1) ? new D1 : new D2; // だめぽ
    B *pb1 = (argc > 1) ? static_cast<B*>(new D1) : new D2; // おk
    B *pb2 = (argc > 1) ? new D1 : static_cast<B*>(new D2); // おk
}

C++にはユニフィケーションするような本格的な型推論は無くてボトムアップに決めるだけだよ... というのは友人から指摘されたりしてたんだが,「三項演算子の型は typeof(then) と typeof(else) の共通の派生元のうち最も特定的なもの」と定義すればボトムアップにいけるんじゃね? と思っていた.
しかし多重継承があると上の定義では最も特定的なものが一意に決まらずボトムアップできないことに,ようやっと気付いた:

struct B1 { };
struct B2 { };
struct D1 : B1, B2 { };
struct D2 : B1, B2 { };

int main(int argc, char *argv[]) {
//  B1 *pb0 = (argc > 1) ? new D1 : new D2; // 死ねる
    B1 *pb1 = (argc > 1) ? static_cast<B1*>(new D1) : new D2; // おk
    B1 *pb2 = (argc > 1) ? new D1 : static_cast<B1*>(new D2); // おk
}

こうなるとしょうがないね...
なお調べてたら,クラスの継承の無いCの時代でも(ENUM_APPLE は列挙型 (enum) として) int x = cond ? 1.0 : ENUM_APPLE; とか書くと似た問題に突き当たるらしいと知った.

τ <: σ を「τ は σ に変換可能」という意味で書くと enum <: int かつ float <: int だけど enum <: float でも enum :> float でもない.これはまさに同型の構図である.こういうのを知ってる(気付く)人ってのがlanguage lawyerというやつだろうね... 私も 1 + (cond ? UINT_MAX : INT_MIN) とか色々怪しいコードを考えてたんだが,なかなかビシッと決まらず.(そんなことしてたら上の記事の内容に気付いた)