Patch for smart pointers assignation of plain pointers

It seems to me that smart pointers could have the same semantics that plain pointers have (it's also the orientation taken by other smart pointers, like those in Glibmm). Here is my proposed patch against CVS HEAD: Index: boost/scoped_ptr.hpp =================================================================== --- boost/scoped_ptr.hpp.orig +++ boost/scoped_ptr.hpp @@ -101,6 +101,12 @@ return *this; } + scoped_ptr & operator=(T * rhs) + { + this_type(rhs).swap(*this); + return *this; + } + T * get() const // never throws { return ptr; Index: boost/shared_ptr.hpp =================================================================== --- boost/shared_ptr.hpp.orig +++ boost/shared_ptr.hpp @@ -246,6 +246,12 @@ #endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + shared_ptr & operator=(T * r) + { + this_type(r).swap(*this); + return *this; + } + #endif // BOOST_NO_AUTO_PTR #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) Regards, Nowhere man -- nowhere.man@levallois.eu.org OpenPGP 0xD9D50D8A

On 31/01/06, Pierre THIERRY <nowhere.man@levallois.eu.org> wrote:
+ shared_ptr & operator=(T * r) + { + this_type(r).swap(*this); + return *this; + } +
That results in implicitly creating a shared_ptr from a raw pointer, which as I understand it is explicitly disallowed because it means that simple code such as the following will fail: int *p = new int; shared_ptr<int> sp; sp = p; sp = p; Since it would be the same as: int *p = new int; shared_ptr<int> sp; sp.reset(p); sp.reset(); // which has the same effect as delete p, in this case sp.reset(p); // sp is now holding a pointer to unallocated memory My understanding is that the operator=(T*) is purposefully not there to make this more explicit. It should help in migrating to shared_ptr as well, since if sp was previously an int* that was manually deleted at the end of the scope, the code would have been fine. - Scott McMurray

Le Tue, 31 Jan 2006 11:06:51 -0500, me22 a écrit :
On 31/01/06, Pierre THIERRY <nowhere.man@levallois.eu.org> wrote:
+ shared_ptr & operator=(T * r) + { + this_type(r).swap(*this); + return *this; + } +
That results in implicitly creating a shared_ptr from a raw pointer, which as I understand it is explicitly disallowed because it means that simple code such as the following will fail: int *p = new int; shared_ptr<int> sp; sp = p; sp = p;
I understand, but the following code would fail the same way without compilation warnings: int p* = new int; shared_ptr<int> sp; sp.reset(p); sp.reset(p);
My understanding is that the operator=(T*) is purposefully not there to make this more explicit.
But this also renders some uses impossible, like this one: stack<foo*> fooS; while(shared_ptr<foo> = fooS.pop()) { ... } Sorry for answering so late to this (now) old thread. If I should start it again for clarity, just tell me. Lately, Nowhere man -- nowhere.man@levallois.eu.org OpenPGP 0xD9D50D8A

On 6/12/06, Pierre THIERRY <nowhere.man@levallois.eu.org> wrote:
I understand, but the following code would fail the same way without compilation warnings:
int p* = new int; shared_ptr<int> sp; sp.reset(p); sp.reset(p);
But in that case you're typing reset, which means you're aware that you're using smart pointers. You also would never have "sp.reset(p);" if sp used to be a plain pointer, so it's not a problem when refitting existing code to use smart pointers.
But this also renders some uses impossible, like this one:
stack<foo*> fooS; while(shared_ptr<foo> = fooS.pop()) { ... }
I'm not sure what that code's trying to do. Each of these works fine: stack<foo*> fooS; shared_ptr<foo> fptr; while ( fptr.reset(fooS.pop()) ) { ... } stack<foo*> fooS; shared_ptr<foo> fptr; while ( fptr = shared_ptr<foo>(fooS.pop()) ) { ... } stack<foo*> fooS; shared_ptr<foo> fptr; template <typename T> shared_ptr<T> make_shared_ptr(T *ptr) { return shared_ptr<foo>(ptr); } while ( fptr = make_shared_ptr(fooS.pop()) ) { ... } stack<foo*> fooS; if ( shared_ptr<foo> fptr( fooS.pop() ) ) { ... }
Sorry for answering so late to this (now) old thread. If I should start it again for clarity, just tell me.
Luckily gmail still managed to thread it for me =) HTH, ~ Scott McMurray

Le Mon, 12 Jun 2006 21:24:03 -0400, me22 a écrit :
You also would never have "sp.reset(p);" if sp used to be a plain pointer, so it's not a problem when refitting existing code to use smart pointers.
But then it makes refitting code to smart pointers a pain. And if anything is wrong with the smart pointers, it's a pain again to remove them. Maybe in most cases, with smart pointer assignation operator, it would only be a matter of commenting all calls to free() or the delete operator and having a typedef for the pointer type and you could easily use smart pointers or not.
But this also renders some uses impossible, like this one:
stack<foo*> fooS; while(shared_ptr<foo> = fooS.pop()) { ... }
I'm not sure what that code's trying to do.
Each of these works fine:
stack<foo*> fooS; shared_ptr<foo> fptr; while ( fptr.reset(fooS.pop()) ) { ... }
stack<foo*> fooS; shared_ptr<foo> fptr; while ( fptr = shared_ptr<foo>(fooS.pop()) ) { ... }
stack<foo*> fooS; shared_ptr<foo> fptr; template <typename T> shared_ptr<T> make_shared_ptr(T *ptr) { return shared_ptr<foo>(ptr); } while ( fptr = make_shared_ptr(fooS.pop()) ) { ... }
stack<foo*> fooS; if ( shared_ptr<foo> fptr( fooS.pop() ) ) { ... }
But it's not possible anymore that the pointer be in the scope of the while() loop. Maybe that's not an issue, though. Would it be OK if an assignable version of the smart pointers was implemented as different classes? That is, if a patch added assignable_shared_ptr and assignable_scoped_ptr? Quickly, Nowhere man -- nowhere.man@levallois.eu.org OpenPGP 0xD9D50D8A

On 6/14/06, Pierre THIERRY <nowhere.man@levallois.eu.org> wrote:
But then it makes refitting code to smart pointers a pain. And if anything is wrong with the smart pointers, it's a pain again to remove them.
Maybe in most cases, with smart pointer assignation operator, it would only be a matter of commenting all calls to free() or the delete operator and having a typedef for the pointer type and you could easily use smart pointers or not.
Refitting to smart pointers has to be done very carefully to prevent multiple deletes. Making the implicit creation of shared_ptrs illegal is a feature. And it's easy to implement a dumb pointer wrapper with a .reset() if it's really needed, but going back from smart pointers would also be quite difficult, as all the releasing would have to be put back again manually, and odds are that the orderings and such are different from before after fixing assignment orderings to avoid multiple frees.
But it's not possible anymore that the pointer be in the scope of the while() loop. Maybe that's not an issue, though.
In that case I'd use a for loop, personally. As mentioned, I wasn't exactly sure what you were trying to do.
Would it be OK if an assignable version of the smart pointers was implemented as different classes? That is, if a patch added assignable_shared_ptr and assignable_scoped_ptr?
You could easily implement them yourself as fairly trivial wrappers around shared_ptr or scoped_ptr. In fact, you could probably even template it to make assignable< shared_ptr<T> > and assignable< scoped_ptr<T> > work. If you have a well-written implementation and a solid use case, then it's quite possible that it would be added. Slowly, Scott McMurray
participants (2)
-
me22
-
Pierre THIERRY