
Mathias Gaunard wrote:
I am proposing the addition of the following very simple utility in Boost, and thus request a very informal and early review of the ideas and design.
Idea ----
The idea is to provide an utility that allows the manipulation of dynamically typed objects, that may be of any derived type of a given base type, as if it were a simple base object. This is quite similar to a smart pointer that does deep-copying, but without any pointer or memory allocation exposed.
[ 8< -- snip -- ]
The motivation for this is that often usage of dynamic typing with inheritance and inclusion polymorphism often means explicit memory allocation and deallocation, and thus are often a source of unsafety. shared_ptr is one way to solve the problem, yet the shared object doesn't behave as a normal C++ object: it has entity semantics (= reference) instead of value semantics (= copying).
shared_ptr is highly regarded as being one of the most useful utilities
[ 8< -- snip -- ]
As a matter of fact, it appears that sharing is rarely needed, and makes the program more difficult to understand. (sharing between threads also cause a few issues). Indeed, the object is freed when it is no longer used, but it's not always trivial to trace whether it's still used or not. Sharing also means you can expect side-effects coming from anywhere.
I'm confused. Surely the whole point of shared_ptr is to relieve the programmer of the burden of worrying when its still used. And what side effects do you speak of?
Pure value objects make the program more easy to understand by making it more deterministic and thus to maintain.
How are programs made more deterministic?
Design ------
To implement that utility, there is a need for a way to call the appropriate copy constructor and move constructor for the right types, even with type erasure. There is no standard way, however, to simply make constructors virtual, so there is a need to do such a thing.
A few implementations of clone_ptr, a similar idea, that I have seen tried to make this non-intrusive. This of course adds some overhead, mainly in size of the object, but it has another downside: it requires to assume that the types of the objects being inserted in it are their real types.
Thus, writing that kind of code: poly_obj<Base> b = poly_obj<Base>(Derived()).get(); Would produce type splitting.
Actually, if you have the static type at the point of construction, you're set. Here's one I just threw together: http://rafb.net/p/bIQgtl24.html Edd