On Thu, Apr 11, 2024 at 5:43 PM Jason McKesson via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
No, the only differences are that `any` has value semantics and is
type safe. In every other way, `any` does what `void*` does, and `any`
doesn't do what `void*` cannot do.

That's like saying that the only difference between fish and birds is that birds can fly and fish can breathe underwater. Value semantics vs reference/pointer semantics is a very big difference, and so is type-safety. And really, void* cannot do anything by itself. The only thing that void* can do is to be relabeled as any other pointer. `Void*` is raw building material, `any` is a utility.
 
Furthermore, even if we are to think of `any` as a generic
discriminated union, discriminated unions can't do this either. If you
have a `variant<T, U>`, you can't get a pointer to `B` which is a base
class of `T` directly. You must get the `T*` out of it, then manually
cast it to `B*`. If you have a `union {T t; U u};`, and you know that
`t` is active, you can't just cast the union *itself* to a `B*`. You
have to access `t` and perform the conversion on that.

Yes, I agree that an open discriminated union is not an entirely correct characterization. A better description would be to say that `std::any` is a polymorphic type which can hold values of unrelated types. The important part is that the reasonable usage of `std::any` is to check whether the value is of a specific type that we know how to handle, and if it is, take the value out of it and handle it.

And when we are asking the container, is the value in it of a given type, it is intuitive to expect that if the object inside it is of a derived type the answer would be positive, just like everywhere else in the language.
 
> The intended use of `any` is just like with any discriminated union - the receiver tests the discriminator against one or more options that it knows how to handle and performs a cast if it turns out to be one of them. And so it actually makes sense for a test against a base class to succeed when the `any` contains an instance of a derived class. Of course, as you pointed out, the actual cast should pass through the derived type, before it gets to the base type.

That's the point: if the receiving code knows the proper derived type
it was given, then there's no need for a feature. As such, the only
time you would want what the OP is asking for is if the receiving code
doesn't know what the derived type is.

The whole point of using `any` instead of `variant` is to support the use case where the receiver of the container doesn't know all possible values that can be stored in it. For `any` to be actually useful, you need to either store in it unrelated types, or be able to get a base type when the `any` contains an instance of a derived type, even if the derived type is unknown to the receiver.
 
What the OP wants is for the receiving code to get any class derived
from a particular base class. `void*` can't do that regardless of
type-safety questions, so `any` shouldn't either. `any` isn't the
right tool for this job, especially considering how value-centric it
is.

If `any` isn't the right tool for the job, what is?


This electronic communication and the information and any files transmitted with it, or attached to it, are confidential and are intended solely for the use of the individual or entity to whom it is addressed and may contain information that is confidential, legally privileged, protected by privacy laws, or otherwise restricted from disclosure to anyone else. If you are not the intended recipient or the person responsible for delivering the e-mail to the intended recipient, you are hereby notified that any use, copying, distributing, dissemination, forwarding, printing, or copying of this e-mail is strictly prohibited. If you received this e-mail in error, please return the e-mail to the sender, delete it from your computer, and destroy any printed copy of it.