-
Notifications
You must be signed in to change notification settings - Fork 12
Description
Under two circumstances can two distinct instantiations of impl_ptr have a copier function convertible to the other impl_ptr? This copy assignment operator is templated, but I can't see a situation where two distinct impl_ptr instantiations could be used in an assignment.
I have discovered this problem as a result of my testing. I get why a single deleter function can be used for different types (the types could have inheritance relations and virtual destructors), but having compatible copier functions is weird. Even if such case would exist, what is
return impl_ptr(
base_type::ptr_ ? copier_(base_type::ptr_.get()) : nullptr,
base_type::ptr_.get_deleter(),
copier_);supposed to do in that case?
Let's consider the following example impl_ptr<BaseType, BaseDeleter, BaseCopier>{} = impl_ptr<DerivedType, BaseDeleter, BaseCopier>{}; DerivedType * is convertible to BaseType *. They have virtual destructors, so a shared BaseDeleter can be used.
Type requirements are satisfied for operator=, so it proceeds into the clone(). The clone calls a impl_ptr<DerivedType>(BaseType *, BaseDeleter function, BaseCopier function). Derived type cannot be trivially constructed from a pointer to BaseType (and even if it had a converting constructor, clone() would still fail, because BaseType * cannot be converted to DerivedType * without a cast (which would likely lead to UB)). Also, there is no constructor of impl_ptr accepting a templated pointer, copier function and a deleter function.