This is a follow-up of this question: conditional operator expression with base and const derived class doesn't compile, why?.
The core is cond ? [cv] T1() : [cv] T2()
where, for instance T2
publicly inherit from T1
.
Trying to follow the rules for determining the type of the expression, it seemed to require an implicit conversion sequence from the derived object to the base one. Yet implicit conversion rules do not cover derived object to base object conversion (only pointer/reference to derived implicit conversion to pointer/reference to base).
In linked question example, though, the types were really simple:
struct X {};
struct Y : X {};
And thus they have implicit default move and copy constructors which may allow the implicit conversion sequence to be formed.
In order to test this hypothesis, I tried to explicit these operators, to break the conversion sequence:
#include <iostream>
struct X {
X() = default;
explicit X(X const &) { std::cout << "copy to base\n"; }
explicit X(X &&) { std::cout << "move to base\n"; }
virtual ~X() = default;
};
struct Y : X {
Y() = default;
Y(Y const &y) : X(y) { std::cout << "copy to derived\n"; }
Y(Y &&) { std::cout << "move to derived\n"; }
virtual ~Y() = default;
};
int main() { true ? Y() : X(); }
LIVE
I tested different combinations with the explicit keywords and I got these output:
explicit | gcc | clang | msvc |
---|---|---|---|
none | move to base | move to base | move to base |
on move only | move to base (expected copy) | copy to base | move to base (expected copy) |
on copy only | move to base | move to base | move to base |
on both | move to base (expected error) | error | error |