different types to ?: operator

namespace {
struct Base {};
struct Derived: Base {};
int main() {
Base a;
Derived b;
Derived *p = &b;
const Derived *c = &b;
bool s = false;
Base x = s ? *p : a;
Base y = s ? *c : a;

In the above code, p and c are both pointer to Derived, but c is const. Why g++ is OK with statement assign to x, but complains about statement assign to y?

OS is fedora 32 with kernel 5.6.13-300 and gcc is version 10.1.1.
error: operands to ?: have different types ‘const {anonymous}::Derived’ and ‘{anonymous}::Base’
   12 |     Base y = s ? *c : a;
      |              ~~^~~~~~~~

The compiler doesn't bother about that your structs have no members which could get changed, so it claims for trying to assign a const object to a non-const.
I suspect it's because the compiler would have to two type conversions to make the statement work. If I recall right, code must require at most one conversion. Otherwise figuring out which conversion to use gets too crazy.

In this case, it's key to realize that the value of the ?: operator has one type. That means the 2nd and 3rd operands must have the same type, or you must be able to convert 1 to the other.

So let's look at both statements:
Base x = s ? *p : a;
Okay. Converts *p to Base & and creates x with copy constructor

Base y = s ? *c : a;
Not okay. You need an explicit cast to remove the const-ness of *c, so whatever type ?: has, it must be const. The conversion fails because the compiler would have to convert both *c and b to const Base &
But here, x, y, and a are all the same type, which is Base, *p is Derived, and *c is const Derived. Are you saying const Derived can not be directly converted to Base, while Derived can?
Are you saying const Derived can not be directly converted to Base
Yes. Because the compiler won't silently throw away const-ness. After all, that would defeat the purpose of declaring something const.
Topic archived. No new replies allowed.