
Hi, I just wanted to hear if anybody had already made a move_ptr I could use? br Thorsten

"Thorsten Ottosen" <nesotto@cs.auc.dk> wrote in message news:cglqbl$mig$1@sea.gmane.org...
Hi,
I just wanted to hear if anybody had already made a move_ptr I could use?
Daniel Wallin posted a complete implementation, some time ago. I believe there might have been one or two small problems that were easily fixed. I think this is it here: http://tinyurl.com/3f6sw. I wrote a version that incorporated deleters and special treatment for arrays, using Howard Hinnant's move_ptr<T[]> syntax. It think it was basically done, but I never got aound to writing documentation. I sort of forgot about it. I you like, I will post it. Jonathan

On Aug 26, 2004, at 8:10 PM, Jonathan Turkanis wrote:
I wrote a version that incorporated deleters and special treatment for arrays, using Howard Hinnant's move_ptr<T[]> syntax. It think it was basically done, but I never got aound to writing documentation. I sort of forgot about it. I you like, I will post it.
Far out! :-) Alternative names: owned_ptr unique_ptr sole_ptr solo_ptr exclusive_ptr lone_ptr only_ptr unshared_ptr selfish_ptr -Howard

"Howard Hinnant" <hinnant@twcny.rr.com> wrote in message news:8AB1FBFA-F7C3-11D8-8665-003065D18932@twcny.rr.com... | On Aug 26, 2004, at 8:10 PM, Jonathan Turkanis wrote: | Alternative names: | | owned_ptr this one would imply propogation of constness IMO. | unique_ptr seems ok, though I like move_ptr. br Thorsten

From: Howard Hinnant <hinnant@twcny.rr.com>
Alternative names:
Now that you raised a flag on the "move_ptr" name, I do agree that it isn't appropriate. "Move" is a verb, so "move_ptr" looks like a command.
owned_ptr
Many pointers are owned, they just have differing ownership semantics.
unique_ptr
There are many unique pointers, but they aren't necessarily movable or, rather, subject to being moved.
sole_ptr solo_ptr
ditto
exclusive_ptr
Many pointers have but one owner, but that doesn't mean that they are movable.
lone_ptr only_ptr
Similar to unique_ptr.
unshared_ptr
This has the right idea. It says that there is no sharing; that there can only ever be one owner of the resource at a time.
selfish_ptr
I don't think we need to condemn the pointer for its acting as designed, do you? I thought of "movable_ptr," but that's wrong because it suggests that the pointer *may* be moved, but doesn't have to be moved. How about "moving_ptr?" That suggests the transitive nature of ownership, doesn't it? "transitive_ptr?" How about something along the lines of "nonloyal_ptr?" That is, it has no allegiance to a single owner, but moves among them at will (well, not quite that freely, but I'm sure you get the idea). -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

"Jonathan Turkanis" <technews@kangaroologic.com> wrote in message news:cgltl6$ti1$1@sea.gmane.org... | | "Thorsten Ottosen" <nesotto@cs.auc.dk> wrote in message | news:cglqbl$mig$1@sea.gmane.org... | > Hi, | > | > I just wanted to hear if anybody had already made a move_ptr I could use? | | Daniel Wallin posted a complete implementation, some time ago. I believe there | might have been one or two small problems that were easily fixed. I think this | is it here: http://tinyurl.com/3f6sw. this one does not allow for deleters, in particlar just a reference to a deleter. | I wrote a version that incorporated deleters and special treatment for arrays, | using Howard Hinnant's move_ptr<T[]> syntax. It think it was basically done, but | I never got aound to writing documentation. I sort of forgot about it. I you | like, I will post it. please do. Thanks Thorsten

"Thorsten Ottosen" <nesotto@cs.auc.dk> wrote in message news:cgnbf7$r04$1@sea.gmane.org...
"Jonathan Turkanis" <technews@kangaroologic.com> wrote in message news:cgltl6$ti1$1@sea.gmane.org...
| I wrote a version that incorporated deleters and special treatment for arrays, | using Howard Hinnant's move_ptr<T[]> syntax. It think it was basically done, but | I never got aound to writing documentation. I sort of forgot about it. I you | like, I will post it.
please do.
I'll try to do so early next week.
Thorsten
Jonathan

On Aug 26, 2004, at 7:03 PM, Thorsten Ottosen wrote:
I just wanted to hear if anybody had already made a move_ptr I could use?
Fwiw, there's a copyright-free move_ptr at: http://home.twcny.rr.com/hinnant/Utilities/move_ptr But I don't recommend it. I really like Dave's move implementation better, though it is less portable with current compilers (including Metrowerks). I also think move_ptr should carry a destructor policy in it's type: template<class T, class D = typename detail::default_delete<T>::type> class move_ptr; And I think it should be specialized on T[] for arrays: template<class T, class D> class move_ptr<T[], D>; And finally, I really am not happy with the name move_ptr, ironically. I was just this morning trying to think of a better name. How about owned_ptr? I was trying to contrast it with shared_ptr: With shared_ptr, many instances share ownership of a pointer. With move/owned_ptr, unique ownership is always assured. Bringing up another possibility: unique_ptr. I'm trying to stress the characteristic of sole ownership vs shared ownership, rather than the fact the pointer is movable. In the future, many types will be movable (even shared_ptr). So move_ptr is a really lousy name. I spent way too much time with the thesaurus this morning. ;-) -Howard

Howard Hinnant <hinnant@twcny.rr.com> writes:
On Aug 26, 2004, at 7:03 PM, Thorsten Ottosen wrote:
I just wanted to hear if anybody had already made a move_ptr I could use?
Fwiw, there's a copyright-free move_ptr at:
http://home.twcny.rr.com/hinnant/Utilities/move_ptr
But I don't recommend it. I really like Dave's move implementation better, though it is less portable with current compilers (including Metrowerks). I also think move_ptr should carry a destructor policy in it's type:
My move implementation is more portable now. But for something that's movable but not copiable --- that's easier. Use Daniel's version, which is very portable.
And finally, I really am not happy with the name move_ptr, ironically.
Why not? Oh, below.
I was just this morning trying to think of a better name.
How about owned_ptr?
How is that different from auto_ptr?
I was trying to contrast it with shared_ptr: With shared_ptr, many instances share ownership of a pointer. With move/owned_ptr, unique ownership is always assured. Bringing up another possibility: unique_ptr. I'm trying to stress the characteristic of sole ownership vs shared ownership, rather than the fact the pointer is movable. In the future, many types will be movable (even shared_ptr). So move_ptr is a really lousy name.
single_ptr?
I spent way too much time with the thesaurus this morning. ;-)
I hope you two are good friends, now. -- Dave Abrahams Boost Consulting http://www.boost-consulting.com

Howard Hinnant wrote:
template<class T, class D = typename detail::default_delete<T>::type> class move_ptr;
why in type? This could be stored in trampoline function, stored together with pointer, something like this http://b.kozicki.pl/cpp/ext_auto_ptr_090.zip B.

Bronek Kozicki <brok@rubikon.pl> writes:
Howard Hinnant wrote:
template<class T, class D = typename detail::default_delete<T>::type> class move_ptr;
why in type? This could be stored in trampoline function, stored together with pointer, something like this http://b.kozicki.pl/cpp/ext_auto_ptr_090.zip
It's a space-vs-time tradeoff. -- Dave Abrahams Boost Consulting http://www.boost-consulting.com

David Abrahams wrote:
Bronek Kozicki <brok@rubikon.pl> writes:
Howard Hinnant wrote:
template<class T, class D = typename detail::default_delete<T>::type> class move_ptr;
why in type? This could be stored in trampoline function, stored together with pointer, something like this http://b.kozicki.pl/cpp/ext_auto_ptr_090.zip
It's a space-vs-time tradeoff.
right, but do you really believe that deleter should belong to type? Tradeoff is really small (3 pointers more, no extra allocations), and it gives *runtime* choice of deleter. Thus with it you can write "source" function (the one returning smart pointer), and caller of this function does not need to know anything about deleter. Heck, you can even safely pass pointers and other things between dynamic libraries, each using its own copy of statically linked CRT. B.

Bronek Kozicki <brok@rubikon.pl> writes:
David Abrahams wrote:
Bronek Kozicki <brok@rubikon.pl> writes:
Howard Hinnant wrote:
template<class T, class D = typename detail::default_delete<T>::type> class move_ptr;
why in type? This could be stored in trampoline function, stored together with pointer, something like this http://b.kozicki.pl/cpp/ext_auto_ptr_090.zip It's a space-vs-time tradeoff.
right, but do you really believe that deleter should belong to type?
Sometimes, probably.
Tradeoff is really small (3 pointers more, no extra allocations), and it gives *runtime* choice of deleter. Thus with it you can write "source" function (the one returning smart pointer), and caller of this function does not need to know anything about deleter. Heck, you can even safely pass pointers and other things between dynamic libraries, each using its own copy of statically linked CRT.
Believe me, I'm aware of the advantages of having a deleter member. -- Dave Abrahams Boost Consulting http://www.boost-consulting.com

On Aug 27, 2004, at 9:08 AM, Bronek Kozicki wrote:
David Abrahams wrote:
Bronek Kozicki <brok@rubikon.pl> writes:
Howard Hinnant wrote:
template<class T, class D = typename detail::default_delete<T>::type> class move_ptr;
why in type? This could be stored in trampoline function, stored together with pointer, something like this http://b.kozicki.pl/cpp/ext_auto_ptr_090.zip It's a space-vs-time tradeoff.
right, but do you really believe that deleter should belong to type? Tradeoff is really small (3 pointers more, no extra allocations), and it gives *runtime* choice of deleter. Thus with it you can write "source" function (the one returning smart pointer), and caller of this function does not need to know anything about deleter. Heck, you can even safely pass pointers and other things between dynamic libraries, each using its own copy of statically linked CRT.
I can see the utility of something like this. Perhaps we are talking about two different kinds of smart pointers, neither inherently better than the other. Sometimes you need hatchet, sometimes you need a carving knife. -Howard

Howard Hinnant wrote:
I can see the utility of something like this. Perhaps we are talking about two different kinds of smart pointers, neither inherently better than the other. Sometimes you need hatchet, sometimes you need a carving knife.
maybe we could use partial template specialization for this? And even for third one, where deleter object is copied into smart pointer, as it is in shared_ptr? B.

On Aug 27, 2004, at 11:15 AM, Bronek Kozicki wrote:
Howard Hinnant wrote:
I can see the utility of something like this. Perhaps we are talking about two different kinds of smart pointers, neither inherently better than the other. Sometimes you need hatchet, sometimes you need a carving knife.
maybe we could use partial template specialization for this? And even for third one, where deleter object is copied into smart pointer, as it is in shared_ptr?
I think you are essentially turning it into a policy-based smart pointer design - not that there's anything wrong with that. I'd like to see (or create for myself) a feature/cost comparison between: 1. pointer<T, D> - holds a compressed_pair<T*, D> 2. pointer<T>(t, d) - trampoline function design 3. pointer<T>(t, d) - internal copy design (a-la shared_ptr) That's probably a non-trivial task... -Howard

Bronek Kozicki wrote:
Howard Hinnant wrote:
template<class T, class D = typename detail::default_delete<T>::type> class move_ptr;
why in type? This could be stored in trampoline function, stored together with pointer, something like this http://b.kozicki.pl/cpp/ext_auto_ptr_090.zip
So that sizeof(move_ptr<T>) can be the same as sizeof(T*).

Peter Dimov wrote:
why in type? This could be stored in trampoline function, stored together with pointer, something like this http://b.kozicki.pl/cpp/ext_auto_ptr_090.zip
So that sizeof(move_ptr<T>) can be the same as sizeof(T*).
No quite. You can have sizeof(move_ptr<T, &your_deleter_goes_here>) the same size as sizeof(T*), but you need to "encode" deleter into smart pointer type. What about yet another smart opinter class that does *not* store deleter info inside its type? Or about providing specialization of move_ptr, that will have slightly higher overhead and provide runtime selection of deleter, something like: template <typename T> class move_ptr<T, dynamic> { // ... something similar to ext_auto_ptr_090 goes here }; sizeof(move_ptr<T, dynamic>) == sizeof(move_ptr<T, &deleter>) * 4 B.

On Aug 27, 2004, at 8:44 AM, Peter Dimov wrote:
Bronek Kozicki wrote:
Howard Hinnant wrote:
template<class T, class D = typename detail::default_delete<T>::type> class move_ptr; why in type? This could be stored in trampoline function, stored together with pointer, something like this http://b.kozicki.pl/cpp/ext_auto_ptr_090.zip
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> > class move_ptr; is to support the array specialization: template<class T, class D> class move_ptr<T[], D>; The default argument in the primary template must serve both the primary, and the array specialization. And you need different defaults for those two cases. Thus the extra level of (compile time) indirection. Oh, I forgot to mention other criteria that I consider very important concerning the deleter: 1. Clients should be able to get references to the embedded deleter (I prefer both const and non-const): deleter_reference get_deleter(); deleter_const_reference get_deleter() const; 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 // avoids copying the D, might do a better job // of maintaining the state of d_. // This can't fail, even if D's copy ctor might s_ = new ... p ... // acquire ownership of p - might throw an exception hold.release(); // move_ptr's job is done, transfer ownership to (s_,d_) -Howard

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? B.

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

"Bronek Kozicki" <brok@rubikon.pl> wrote in message news:412ED9D1.1@rubikon.pl... | Howard Hinnant wrote: | | > template<class T, class D = typename detail::default_delete<T>::type> | > class move_ptr; | | why in type? This could be stored in trampoline function, stored | together with pointer, something like this | http://b.kozicki.pl/cpp/ext_auto_ptr_090.zip correct me if I'm wrong, but embedding the deleter in the type is the only way to optimize the deleter completely away; eg, I need to be able to say typedef move_ptr< T, MyDeleter& > move_type; to support empty deletes without overhead. br Thorsten

"Howard Hinnant" <hinnant@twcny.rr.com> wrote in message news:632F334B-F7C0-11D8-8665-003065D18932@twcny.rr.com... | On Aug 26, 2004, at 7:03 PM, Thorsten Ottosen wrote: | | > I just wanted to hear if anybody had already made a move_ptr I could | > use? | | Fwiw, there's a copyright-free move_ptr at: | | http://home.twcny.rr.com/hinnant/Utilities/move_ptr Thanks. | But I don't recommend it. I really like Dave's move implementation | better, though it is less portable with current compilers (including | Metrowerks). I also think move_ptr should carry a destructor policy in | it's type: | | template<class T, class D = typename detail::default_delete<T>::type> | class move_ptr; definitely br Thorsten
participants (9)
-
Bronek Kozicki
-
David Abrahams
-
David B. Held
-
Eric Niebler
-
Howard Hinnant
-
Jonathan Turkanis
-
Peter Dimov
-
Rob Stewart
-
Thorsten Ottosen