C++ Logo

std-proposals

Advanced search

Re: std::any / std::any_cast without typeid

From: connor horman <chorman64_at_[hidden]>
Date: Sat, 5 Dec 2020 15:48:58 -0500
On Sat, Dec 5, 2020 at 14:31 Nikolay Mihaylov via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> Consider following code:
>
> struct A{
> virtual ~A() = default;
> virtual int op(int a, int b) const = 0;
> };
>
> struct Sum : A{
> int op(int a, int b) const override{
> return a + b;
> }
> };
>
> #include <any>
>
> std::any x = Sum{};
>
> int main(){
> return std::any_cast<A &>(x).op(5, 5);
> }
>
> It crashes with `std::bad_any_cast` exception.
>
> this happens, because *std::any_cast* is specified in terms of *typeid*.
>
> I also know how to fix this.
>
> However I can not understand why this *should* happen. Reference is
> pointer under the hood, so cast should work, e.g. following works OK.
>
This isn't necessarily the case, but even when it is, pointers are quite
interesting and not simply addresses.

>
> Maybe we need some other kind of cast, for example
> *std::non_secure_any_cast* that just casts the value no matter what.
>
I wouldn't think this necessarily fixes this, due to strict-aliasing.
Notably, reinterpret_casting a pointer to Sum to a pointer to A wouldn't
necessarily yield a pointer to the A subobject of the Sum, because it's not
*pointer-interconvertible*. I am not saying its not a good idea, I think an
unchecked version of "any_cast" may be useful, but it won't solve the
problem you brought up.

>
>
> We can not really call it "dynami_any_cast", because it will work the same
> way for *int* -> *long* or *unsigned* -> *float*.
>
Those conversions would be impossible to do without violating
strict-aliasing. Focusing on the dynamic_any_cast case may work better,
especially since the proposed operation would not solve your original
problem, as I mentioned.

>
> Of course the price if we made the wrong cast the program will crash, but
> I can make the program crash with the current *std::any_cast* implementation
> as well.
>
> Current *std::any_cast* does not behave the way programmers expect:
>
> Consider this code:
>
> int main(){
> Sum s;
> A &a = s;
>
> return a.op(5, 5);
> }
>
> and this code too:
>
> int main(){
> Sum s;
> A *a = &s;
>
> return a->op(5, 5);
> }
>
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>

Received on 2020-12-05 14:49:12