Deleting through a void*
results in undefined behavior, so you are guaranteed nothing.
5.3.5 Delete [expr.delete]
1 The delete-expression operator destroys a most derived object (1.8) or array created by a new-expression.
[...]
The operand shall have a pointer to object type, or a class type having a single non-explicit conversion function (12.3.2) to a pointer to object type. The result has type void.78
78) This implies that an object cannot be deleted using a pointer of type void* because void is not an object type.
Emphasis mine.
So even though you said not to say it, the answer is to create some form of smart pointer. It would need to use type-erasure to hide the type externally (allowing the heterogeneous list), but internally keep track of the type it was given and how to delete it. Something much like boost::any
.