Date: Mon, 23 Sep 2019 10:01:56 -0500
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 <http://coliru.stacked-crooked.com/a/49d1853146cbcdc1> 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.)
#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 <http://coliru.stacked-crooked.com/a/49d1853146cbcdc1> 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*
Received on 2019-09-23 10:04:17