Ternary operator implicit cast to base class

前端 未结 4 1963
我在风中等你
我在风中等你 2020-12-28 12:15

Consider this piece of code:

struct Base
{
    int x;
};

struct Bar : Base
{
    int y;
};

struct Foo : Base
{
    int z;
};

Bar* bar = new Bar;
Foo* foo          


        
4条回答
  •  感动是毒
    2020-12-28 12:36

    Since an implicit cast to a Base* exists, what is preventing the compiler from doing so?

    According to [expr.cond]/7,

    Lvalue-to-rvalue, array-to-pointer, and function-to-pointer standard conversions are performed on the second and third operands. After those conversions, one of the following shall hold:

    • ...
    • One or both of the second and third operands have pointer type; pointer conversions, function pointer conversions, and qualification conversions are performed to bring them to their composite pointer type. The result is of the composite pointer type.

    where composite pointer type is defined in [expr.type]/4:

    The composite pointer type of two operands p1 and p2 having types T1 and T2, respectively, where at least one is a pointer or pointer-to-member type or std​::​nullptr_­t, is:

    • if both p1 and p2 are null pointer constants, std​::​nullptr_­t;

    • if either p1 or p2 is a null pointer constant, T2 or T1, respectively;

    • if T1 or T2 is “pointer to cv1 void” and the other type is “pointer to cv2 T”, where T is an object type or void, “pointer to cv12 void”, where cv12 is the union of cv1 and cv2;

    • if T1 or T2 is “pointer to noexcept function” and the other type is “pointer to function”, where the function types are otherwise the same, “pointer to function”;

    • if T1 is “pointer to cv1 C1” and T2 is “pointer to cv2 C2”, where C1 is reference-related to C2 or C2 is reference-related to C1, the cv-combined type of T1 and T2 or the cv-combined type of T2 and T1, respectively;

    • if T1 is “pointer to member of C1 of type cv1 U1” and T2 is “pointer to member of C2 of type cv2 U2” where C1 is reference-related to C2 or C2 is reference-related to C1, the cv-combined type of T2 and T1 or the cv-combined type of T1 and T2, respectively;

    • if T1 and T2 are similar types, the cv-combined type of T1 and T2;

    • otherwise, a program that necessitates the determination of a composite pointer type is ill-formed.

    Now you can see a pointer to "common base" is not the composite pointer type.


    In other words, why does Base* obj = foo; work without a cast but using the ?: operator doesn't? Is it because it's not clear that I want to use the Base part?

    The problem is that the rule should detect the type of the conditional expression independently, without observing the initialization.

    To be specific, a rule should detect the conditional expressions in the following two statements to be the same type.

    Base* obj = !bar ? foo : bar;
    bar ? foo : bar;
    

    Now, if you have no doubt that the conditional expression in the second statement is ill-formed1, what's the reasoning to make it well-formed in the first statement?


    1 Of course one can make a rule to make such expression well-formed. For example, let composite pointer types include the pointer to an unambiguous base type. However, this is something beyond this question, and should be discussed by ISO C++ committee.

提交回复
热议问题