C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Downcasting without Sidecasting

From: Phil Endecott <std_proposals_list_at_[hidden]>
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.

Received on 2024-07-08 17:56:01