C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Downcasting without Sidecasting

From: Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
Date: Mon, 8 Jul 2024 16:00:28 -0400
On Mon, Jul 8, 2024 at 1:55 PM Phil Endecott <
std_proposals_list_at_[hidden]> wrote:

>
> 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);
>

That's an upcast, not a downcast.


> auto rc = down_cast<RightCat*>(&sc); assert(rc);
>

That's an upcast, not a downcast.


> auto lrc = down_cast<RightCat*>(lc); assert(!lrc); // dynamic_cast will
> sidecast here.
>

That's a sidecast, not a downcast.
The only ways "down" the hierarchy I presented are (Cat => LeftCat), (Cat
=> RightCat), (LeftCat => SiameseCat), and (RightCat => SiameseCat).

You can exclude non-down-casts with a plain old static_assert:

template<class To, class From>
To *downcast_to_leftcat(From *c) {
  static_assert(std::is_base_of_v<From, To>, "Hey! I only do downcasts");
  if (To *lc = dynamic_cast<To*>(c)) {
    if (static_cast<From*>(lc) == c) {
      return lc; // this was definitely a pure downcast
    }
  }
  return nullptr;
}

–Arthur

Received on 2024-07-08 20:00:41