Closed nlewycky closed 3 years ago
Excellent, thanks a lot! The two main questions I have are:
- Is there really no convenient way to allow implicit casting from
own<Derived>
toown<Base>
anymore? What is common C++ practice to work around that?
Ordinarily you simply make the Base
destructor virtual
and everything just works. Deletion of a pointer at any type in the hierarchy goes through virtual method dispatch to find the most derived type's destructor.
The trouble with a non-virtual d'tor is that you can, with no complaint from the compiler, create a unique_ptr<Derived>
cast it to a unique_ptr<Base>
. In practical terms this means that any additional members Derived
adds which have user-defined d'tors won't see their d'tors called. In theory, the incorrect destruction is UB regardless.
I've been assuming we can't use virtual
, without really questioning why. This would all be a lot easier if we could use virtual dispatch and virtual inheritance.
Now, unique_ptr<T1, D1>
can cast to unique_ptr<T2, D2>
when T2
is a T1
and D2
is a D1
. We could have a class hierarchy of D's that mirrors the types and the unique_ptr would cast through them together. Better idea, we could use a single D type if it knew how to delete each of T1, T2, etc. So I suppose we can change destroyer<>
to:
class destroyer {
public:
template<typename T>
void operator()(T *ptr) {
ptr->destroy();
}
};
Yep, I'll commit that.
- Can we somehow maintain the former regularity and brevity of going from an interface type to its implementation?
Sorry for the confusion, I was always planning to put that back. That's part of the reason this was a draft PR.
ExternType
is a little more complicated but I think I can make impl(ptr)
work on those too, but the template code will be a little bit more than just defining a single type alias.
Thanks a lot!
Fixes #119.