On Wed, Mar 29, 2023 at 3:38 PM Phil Endecott via Std-Proposals <std-proposals@lists.isocpp.org> 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