I came across an older pondering Type erasure techniques, by Xeo, and I became to wonder, how should one to amend that code to make it work with std::unique_ptr'ers and std::shared_ptr'ers.
The code in the post can be found here. The code won’t compile if fed with something containing unique_ptrs and the data in shared_ptr'ers become garbage. What I tried was a class inherited from a templated base class, so maybe it was somewhat complicated too. Now, this is mainly out of curiosity, as I became to wonder if it would be difficult (in general case) as this could become handy when storing complex objects, say, in std::vector when Boost.Any isn’t available for use.
Edit: I noticed I just had a bug in my code whilst testing, the code works just fine with shared_ptr'ers (the contents aren’t garbage), though not with unique_ptr'ers. And then also, why not store a newed instance of this type erasured Any_Virtual (as in code provided by Xeo) to, say, std::unique_ptr'ers.
I guess then the questions would be:
- How to amend the
Any_Virtualso that it could work withstd::unique_ptr? - Which one would be better design, a
std::vector<Any_Virtual>objects, whereAny_Virtualholds a smart pointer, or astd::vector<std::unique_ptr<Any_Virtual>>objects? Or does it even matter?
When you use type-erasure there is always a set of requirements that a type must satisfy to be compatible with the type-erasing container: this set is called the model. In particular, the
holder<T>::clonemember that copies*thisrequires in turn thatheld_(of typeT, the type being erased) be copy constructible. Hence the model of your type-erasing class is copy constructible.However a type containing an
std::unique_ptrwill not be copy constructible out of the box.There is no obvious fix without knowing what you want to achieve. Perhaps you really want the model to be less strict, e.g. it could only require to be move constructible (which a type containing an
std::unique_ptrcan easily fulfill, right out of the box). Or perhaps you really want those types that do holdstd::unique_ptrs to be copy constructible.In my opinion the very worst you can do with type-erasure is to compromise, and make an operation on the model work conditionally, depending on whether the type being erased supports such an operation itself. Here that would mean that coyping an
Any_Virtualvalue would result in an exception if it happened to hold a value of non-copy constructible erased type.Perhaps more worryingly, the fact that you obtain garbage
std::shared_ptrs heavily suggest that there is a problem with either your implementation ofAny_Virtualor your use of it. You should definitively not assume that there is a problem with usingstd::shared_ptrin tandem withAny_Virtualalone, but that there might be a problem with using anything withAny_Virtual. Since I haven’t noticed a problem in the implementation (but I could easily have overlooked something), I’d like to see an example of a program exhibiting the problem.