
On Aug 27, 2004, at 11:49 AM, Bronek Kozicki wrote:
Howard Hinnant wrote:
So that sizeof(move_ptr<T>) can be the same as sizeof(T*). Yes, yes! Absolutely zero-overhead over a raw pointer is (imho) a critical design criteria of this type of smart pointer. And the reason for the ::type dance instead of something more direct like: template<class T, class D = detail::default_delete<T> >
OK, I guess that detail::default_delete<T> is going to be stored as static field of move_ptr class. However ...
2. And the deleter itself should be able to be a reference type. I can't stress this second point enough. It is a real feature when you want to allow for the possibility of a deleter that is both state-full and heavy. In templated code that already owns a deleter (that you don't know anything about, except its name), and you're using the move_ptr just to enforce ownership temporarily (say for exception safety purposes), then passing a reference-typed deleter to the move_ptr is an extremely elegant solution: Code templated on P (p : pointer type) and D (d_ : deleter type): move_ptr<P, D&> hold(p, d_); // grab hold of p, using a D&, as opposed to a D
... how are you going to store reference to deleter object here, without any memory overhead in your pointer object?
Oh, sorry for not being clear about this. move_ptr<T, D> holds a single data member of type compressed_pair<T*, D>. compressed pair takes care of optimizing away the space for D if D is an empty class. If D turns out to be a non-empty class, or a function pointer, then space is not optimized away (compressed_pair is magic ;-) ). If D turns out to be a reference, the space is not optimized away, and compressed_pair deals with the reference to reference problem. -Howard