C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Extend std::type_info with more information

From: Jason McKesson <jmckesson_at_[hidden]>
Date: Thu, 11 Apr 2024 10:43:05 -0400
On Thu, Apr 11, 2024 at 5:34 AM Mihail Mihaylov via Std-Proposals
<std-proposals_at_[hidden]> wrote:
>
> On Wed, Apr 10, 2024 at 7:34 PM Jason McKesson via Std-Proposals <std-proposals_at_[hidden]> wrote:
>>
>> `std::any` is a type-safe, object-based `void*`. It is intended to
>> replace the usage of `void*` in code that needs to hide types between
>> interfaces. The main point of the type is to check for mistakes, to
>> turn undetectable runtime UB into detectable runtime errors. As such,
>> it should be able to do whatever you could do with a `void*` (minus
>> the fact that it's object-based). But also, it shouldn't be able to do
>> anything you *couldn't* do with a `void*` (again, minus being
>> object-based).
>
>
> I strongly disagree with this statement. `Std::any` has value semantics. It is very different from `void*`. `Any` is an "open" discriminated union, whereas `void *` is a type-erased pointer. Therefore, their use cases are quite different.

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.

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.

So this functionality is wrong regardless of how you conceptualize the
purpose of `any`. Discriminated unions expect you to get the right
type first, *then* convert it to a base class pointer/reference on
your own.

>> The standard is very clear on this point: if you cast a `T*` to a
>> `void*`, the *only* viable cast is to *exactly* `T*` (outside of
>> `char*` shenanigans). Casting to a `B*` which is a base class of `T*`
>> is UB, unless you cast to a `T*` between the `void*` and the `B*`. So
>> the thing you want is impossible with `void*`.
>>
>> And owing to `any`'s design, it should be impossible to do this with
>> `any` too. This is not a matter of implementability; this is a
>> question of "what is the intended purpose of this object?".
>
>
> 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.

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 you want to change this, then you're asking to change what `any` is
>> for. And that requires more than just that you want to do it. You need
>> to argue that this is broadly usable in various use cases that many
>> programmers encounter and have no viable alternatives. And you also
>> need to argue that a different type would not be more appropriate,
>> that `std::any` is the appropriate type for this use case.
>
>
> As I argued above, yes, the ability for `any_cast` to return a base class instance if the contained value is of a derived class is in line with the expected use of `any`.
>
> Practical implementability is another story.
>
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
>
> 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.--
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

Received on 2024-04-11 14:43:21