C++ Logo

std-proposals

Advanced search

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

From: Mihail Mihaylov <mihail.mihailov_at_[hidden]>
Date: Mon, 15 Apr 2024 10:45:17 +0300
On Fri, Apr 12, 2024 at 6:16 PM Thiago Macieira via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> Still, we are talking about storing a polymorphic type inside of std::any
> and
> the general rule of thumb is that an object is EITHER polymorphic or
> copyable,
> not both. Storing an uncopyable object inside of std::any sounds just
> wrong. I
> don't think it supports storing immovable types at all, does it? So this
> alone
> removes the majority of the benefit of this operation, because the types
> in
> question cannot be stored inside std::any in the first place.
>

The base class can be polymorphic, while the derived class can be final and
copyable. Consider a base abstract interface class which has multiple final
copyable implementation classes. The "sender" can store into the `any` an
instance of the copyable derived type and the receiver could extract a base
pointer or base reference to the contained value.

This is very common when we are using non-erased types, so I believe it's
perfectly reasonable to want it with erased types too. And the only reason
Jason had me convinced for a moment that this is not reasonable for
`std::any` specifically, is because he made me believe that `any_cast`
always copies the value, which is not true.

Here's a motivating example to clarify what I mean. I already gave a
similar example earlier in this thread:

class Base
{
public:
    virtual void doSomething() = 0;
};

class Derived final : public Base
{
    void doSomething() final override { cout << "Doing something." << endl;
};
};

void foo(Base* b)
{
    b->doSomething();
}

void foo(any* a)
{
    Base* b = any_cast<Base>(a);

    if (b != nullptr)
        foo(b);
}

int main()
{
    any a = make_any<Derived>();

    foo(any_cast<Derived>(&a)); // Invokes do_something();
    foo(&a); // Does nothing. Would be more consistent to be equivalent to
the previous invocation.
}


In the Qt world, the class that best resembles std::any is QVariant and it
> does not support storing uncopyable types.
>
> It does support storing pointers and, if the pointer is to a class derived
> from QObject, then it can perform casting back to QObject and to any other
> class that derives from it after verifying that this cast would be valid.
>
>
Please, note that in the example above, we are not storing a pointer, we
are storing a `Derived` value, and `std::any` allows us to extract a
`Derived *` to it. What we want is to be able to extract a `Base *` pointer
to it. Also note that `foo(Base*)` doesn't need to know about `Derived` for
it to be used with a `Derived` instance, and similarly, we would like for
`foo(any *)` to be able to handle an `any` that contains a `Derived`
instance while knowing only about `Base`.

In other words, my argument is that `any_cast<Base>(any *)` should be on
par with `static_cast<Base*>(Derived *)`.

For the record, I don't believe that this justifies changes to `type_info`
and I wouldn't argue in support of such changes.

Regards,
Mihail

-- 
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.

Received on 2024-04-15 07:45:31