On Fri, Apr 12, 2024 at 6:16 PM Thiago Macieira via Std-Proposals <
std-proposals@lists.isocpp.org> 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