C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Get base class from std::any

From: Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
Date: Wed, 29 Mar 2023 15:54:11 -0400
On Wed, Mar 29, 2023 at 3:38 PM Phil Endecott via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> Thanks everyone for your continued feedback.
>
> > 1. Add something like any_base_cast to std::any, and hope that library
> > implementers will use private features of the ABI to provide a fast
> > implementation.
>
> Arthur O'Dwyer wrote:
> > This would be an ABI break: the vendor would have to add a new
> > virtual function to the vtable of the internal type used by `std::any`
>
> I'm not convinced that's true, can you elaborate? In fact, I think it's
> very nearly possible to implement any_base_cast as a free function;
> all that's missing is a method in std::any that returns the void* pointer
> to the contained value.
>

True, I had forgotten that `std::any` already exposes the typeinfo through
`std::any.type()`. So the vtable already holds enough information to make
this possible without an ABI break.


Thiago Macieira wrote:
> > That's dynamic_cast.
>
> No, I don't think so. dynamic_cast lets me cast from a base class to a
> derived class; what I want is to cast from a derived class to a base
> class. That's one of the things that static_cast does at compile time.
> Am I missing something?
>

dynamic_cast can also cast from derived to base, and also "sideways" — all
the different directions.
But the big thing you want, that `dynamic_cast` can't do, is that you want
to cast from `void*`: you have a pointer to an object where *you don't know
its static type at compile time*. `dynamic_cast` cannot deal with that kind
of thing. Specifically, see
https://quuxplusone.github.io/blog/2022/12/01/chimeric-ptr/#solution-2-open-coded-dynamic_cast-via-root-object-type

It is interesting to think about what sort of casting or conversion is
> useful in the case of std::any. I do recall once accidentally storing
> a double in an any and then trying to retrieve a float, and having
> much trouble debugging it.
>

Right. But I hope you agree that *that* kind of conversion would be
difficult or impossible to build into std::any.
The thing about classical inheritance relationships (base/derived) is that
they are all written down explicitly at compile time and then encoded into
the executable (in the form of typeinfo and exception-handling machinery).
You could imagine inventing a way for the user-programmer to tell the
compiler "Please encode an arbitrary relationship between *these* two types
also," e.g. between `double` and `float` or `int` and `BigNum`; but I'm not
sure what the syntax for that should look like, and it would be extremely
difficult to sell that to WG21 anyway.

–Arthur

Received on 2023-03-29 19:54:24