Date: Mon, 08 Jul 2024 18:55:58 +0100
Arthur O'Dwyer wrote:
> To Phil's original question "how do I make a dynamic_cast that casts *only*
> down, not sideways?"
> After diagramming the situation in my head (using the notation from my
> talk), I'm like 90% sure that this approach necessarily works —
> https://godbolt.org/z/cazrbPEx3
> struct Cat { virtual ~Cat() = default; };
> struct LeftCat : Cat {};
> struct RightCat : Cat {};
> struct SiameseCat : LeftCat, RightCat {};
>
> LeftCat *downcast_to_leftcat(Cat *c) {
> if (LeftCat *lc = dynamic_cast<LeftCat*>(c)) {
> if (static_cast<Cat*>(lc) == c) {
> return lc; // this was definitely a pure downcast
> }
> }
> return nullptr;
> }
>
> int main() {
> SiameseCat sc;
> assert(downcast_to_leftcat((LeftCat*)&sc) != nullptr);
> assert(downcast_to_leftcat((RightCat*)&sc) == nullptr);
> }
Thanks Arthur.
Can you make it work if there is no common base class? I.e.
struct LeftCat { virtual ~LeftCat() = default; };
struct RightCat { virtual ~RightCat() = default; };
struct SiameseCat: LeftCat, RightCat {};
int main() {
SiameseCat sc;
auto lc = static_cast<LeftCat*>(&sc); assert(lc);
auto rc = down_cast<RightCat*>(&sc); assert(rc);
auto lrc = down_cast<RightCat*>(lc); assert(!lrc); // dynamic_cast will sidecast here.
}
Regards, Phil.
> To Phil's original question "how do I make a dynamic_cast that casts *only*
> down, not sideways?"
> After diagramming the situation in my head (using the notation from my
> talk), I'm like 90% sure that this approach necessarily works —
> https://godbolt.org/z/cazrbPEx3
> struct Cat { virtual ~Cat() = default; };
> struct LeftCat : Cat {};
> struct RightCat : Cat {};
> struct SiameseCat : LeftCat, RightCat {};
>
> LeftCat *downcast_to_leftcat(Cat *c) {
> if (LeftCat *lc = dynamic_cast<LeftCat*>(c)) {
> if (static_cast<Cat*>(lc) == c) {
> return lc; // this was definitely a pure downcast
> }
> }
> return nullptr;
> }
>
> int main() {
> SiameseCat sc;
> assert(downcast_to_leftcat((LeftCat*)&sc) != nullptr);
> assert(downcast_to_leftcat((RightCat*)&sc) == nullptr);
> }
Thanks Arthur.
Can you make it work if there is no common base class? I.e.
struct LeftCat { virtual ~LeftCat() = default; };
struct RightCat { virtual ~RightCat() = default; };
struct SiameseCat: LeftCat, RightCat {};
int main() {
SiameseCat sc;
auto lc = static_cast<LeftCat*>(&sc); assert(lc);
auto rc = down_cast<RightCat*>(&sc); assert(rc);
auto lrc = down_cast<RightCat*>(lc); assert(!lrc); // dynamic_cast will sidecast here.
}
Regards, Phil.
Received on 2024-07-08 17:56:01