Consider the following:

#include <type_traits>
struct S {};
bool b;
int main() {
    const S s {};
    static_assert(std::is_same<decltype(b ? S{} : s), const S>::value);
}


Here GCC and Clang confirm that the type is correct. But I can't figure out why. My reading of the standard is that the result should be a prvalue of type S, not const S.

[expr.cond]/4 applies because the two operand types are not the same (one is S, the other is const S) but at least one is a class type. We must therefore try to form an implicit conversion sequence in each direction. An implicit conversion sequence cannot be formed from the prvalue operand to const S& because (4.1) contains a restriction that the reference must bind directly to a glvalue. In the other direction, we have the identity conversion sequence from the const lvalue operand to S. Thus, /4 seems to tell us that the const lvalue operand must be converted to S, and the result should have type S.

Yet I would not expect both GCC and Clang to be wrong here, so I think that I have misunderstood the standard in this case. Surely there must be a reason why the result has type const S, but I can't figure it out.

(Even if we assume that the compiler is obligated to perform an lvalue-to-rvalue conversion on the const lvalue operand, resulting in a const prvalue, that still doesn't seem to explain the result. If this were the case, /4 would end with a const prvalue and a non-const prvalue, /5 would not apply, and we would get to /6 and the types would still not be the same. The "overload resolution" procedure prescribed there would fail since S can't be converted to any scalar types, making the program ill-formed. This interpretation thus cannot be correct either.)

--
Brian Bi