C++ Logo


Advanced search

Re: [std-proposals] Base class reflection

From: Jason McKesson <jmckesson_at_[hidden]>
Date: Tue, 31 Jan 2023 19:53:59 -0500
On Tue, Jan 31, 2023 at 3:23 PM Billy Martin via Std-Proposals
<std-proposals_at_[hidden]> wrote:
> You can't do this because there isn't any code that knows both B and D at compile time.
> The case I'm thinking of involves some templated container that has an object of type D. (Maybe it's a type erasure system, a smart pointer, whatever). That container knows the type D because it was passed as a template argument when it was instantiated with a brand new D object. Somewhere else, some other code has a pointer B* and they want it to point to this object, but they don't know what type D is (it might not even be knowable until runtime). The container, on the other hand, doesn't know about the type B because it's just a container template and it turns out C++ has literally no way to query a type for its base classes for some reason. So there is no point where you can do the safe conversion static_cast<B*>(D*) because no code knows both types.

I could follow everything until this last sentence. Because it's at
this point where it's unclear *who* is trying to do this cast.

The container isn't trying to do this cast because, as you point out,
it doesn't know about `B`. The other code isn't trying to do this
cast, because it doesn't know about `D` and the only way for it to get
a `D*` is for someone to hand it a `D*`, and to get handed a `D*`
means you have to *know about `D`* (either as an explicit function
parameter or a deduced template parameter).

So either one of your premises is incorrect or there is some
third-party code that's trying to interoperate between these two
worlds. If it is the latter, then why doesn't this code know about
`D`, `B`, and the relationship between them?

I get the impression that what you're describing is an overcomplicated
form of the following. Some code has a `std::any` containing a `D`.
Some other code takes an `any` and expects to extract a `B` from it.
You want this to work for any `D` derived from `B`. That is, you want
`any_cast<B*>` to return a pointer to the base class rather than
`nullptr`, so long as the object the `any` holds is (publicly) derived
from `B`.

At present, `any` cannot do this (and I would argue *should not*, but
that's neither here nor there). To implement this conversion, you
would have to store some kind of map from a typeid (or something
similar) to a conversion function that converts a `D` to that
particular type. This would be built by introspecting all of the base
classes of `D` at the time of its creation and storing this map along
with `D` inside the type-erased `any`.

Is that an accurate description of what you're trying to achieve?

When you say, "there are issues with using Type Erasure on polymorphic
classes," I feel that that is as it should be. These are both forms of
runtime polymorphism. So it's not clear why it is that you're trying
to use both at the same time.

Received on 2023-02-01 00:54:37