[smart_ptr] Some questions

Hi, I was asked to present smart_ptr to our department, but while trying to understand the details of the implementation, I found some things that I don't understand: 1) in shared_ptr.hpp, the ctor which takes a weak_ptr doesn't copy px from r.px in the initializer list like all other ctors, instead the copy is done the the ctor body. There is even a comment which suggests that there is a problem with doing it before pn, it would not be "safe". What exactly does this mean? px is just a plain pointer, so AFAICS it won't hurt to simply say: template<class Y> explicit shared_ptr(weak_ptr<Y> const & r) : px(r.px), pn(r.pn) // may throw { } or is the current code some kind of optimization? 2) in detail/shared_count.hpp, operator= for shared_count has an optimization for tmp==pi_. At least I think that it's just an optimization and it would work without the check. OTOH, operator= for weak_count does not check for tmp==pi_. Why? Is there any deeper reason that these two code fragements differ? 3) I asked about this point before, but got no real answer: There is no throw specification in shared_from_this()'s documentation. AFAICS, shared_from_this() (if used correctly) can not throw. But will this be guaranteed? Also, it seems that enable_shared_from_this is getting some new features. Previously, enable_shared_from_this added a single weak_ptr to the derived class. Now it adds a vtable, a shared_ptr, a weak_ptr and a bool variable. Am I the only one who is concerned about this? Before the change, I even wondered if the weak_ptr could be replaced by a detail::weak_count, which would reduce the overhead from two plain pointers to only one plain pointer, since shared_from_this always has *this. Regards, Daniel

Daniel Frey wrote:
Hi,
I was asked to present smart_ptr to our department, but while trying to understand the details of the implementation, I found some things that I don't understand:
1) in shared_ptr.hpp, the ctor which takes a weak_ptr doesn't copy px from r.px in the initializer list like all other ctors, instead the copy is done the the ctor body. There is even a comment which suggests that there is a problem with doing it before pn, it would not be "safe". What exactly does this mean? px is just a plain pointer, so AFAICS it won't hurt to simply say:
template<class Y> explicit shared_ptr(weak_ptr<Y> const & r) : px(r.px), pn(r.pn) // may throw { }
No, copying a deleted pointer is undefined behavior.
2) in detail/shared_count.hpp, operator= for shared_count has an optimization for tmp==pi_. At least I think that it's just an optimization and it would work without the check. OTOH, operator= for weak_count does not check for tmp==pi_. Why? Is there any deeper reason that these two code fragements differ?
It's a performance optimization. There's no deep reason for the difference.
3) I asked about this point before, but got no real answer: There is no throw specification in shared_from_this()'s documentation. AFAICS, shared_from_this() (if used correctly) can not throw. But will this be guaranteed?
I'm not sure. It's not guaranteed by TR1 or the draft standard, and I haven't considered the issue in detail to be confident that this is a defect.

On Wed, 2008-04-09 at 17:07 +0300, Peter Dimov wrote:
Daniel Frey wrote:
is done the the ctor body. There is even a comment which suggests that there is a problem with doing it before pn, it would not be "safe". What exactly does this mean? px is just a plain pointer, so AFAICS it
No, copying a deleted pointer is undefined behavior.
Ah, thanks. I just learned something new. :)
2) in detail/shared_count.hpp, operator= for shared_count has an optimization for tmp==pi_. At least I think that it's just an optimization and it would work without the check. OTOH, operator= for weak_count does not check for tmp==pi_. Why? Is there any deeper reason that these two code fragements differ?
It's a performance optimization. There's no deep reason for the difference.
Maybe it's worth to do the same optimization in weak_ptr::operator= then?
3) I asked about this point before, but got no real answer: There is no throw specification in shared_from_this()'s documentation. AFAICS, shared_from_this() (if used correctly) can not throw. But will this be guaranteed?
I'm not sure. It's not guaranteed by TR1 or the draft standard, and I haven't considered the issue in detail to be confident that this is a defect.
I have use cases which would be a lot easier to implement if shared_from_this() never throws. And - at least with the "old" implementation - I don't see any reason why this guarantee should not hold. Of course it's not a defect, but to me it seems desirable. Since you are also currently working on enable_shared_from_this (which increases the overhead): Would it make sense if I develop a patch based on the old version which tries to use detail::weak_count instead of weak_ptr to create an even lighter, classic enable_shared_from_this? At least to me the overhead of deriving from enable_shared_from_this is important... Regards, Daniel

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Wednesday 09 April 2008 11:13 am, Daniel Frey wrote:
I have use cases which would be a lot easier to implement if shared_from_this() never throws. And - at least with the "old" implementation - I don't see any reason why this guarantee should not hold. Of course it's not a defect, but to me it seems desirable.
It is technically possible to make it throw without violating the functions documented requirements, if there are multiple owners. For example, if pass the raw pointer to multiple shared_ptrs with null deleters. - -- Frank -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) iD8DBQFH/QEx5vihyNWuA4URAucBAJwNnXN2182FzKZXbn8GS9L6Wm7c5ACgjM5q L2Y5wjzIaZrOvrwNQ8oQvls= =j6mg -----END PGP SIGNATURE-----

On Wed, 2008-04-09 at 13:47 -0400, Frank Mori Hess wrote:
On Wednesday 09 April 2008 11:13 am, Daniel Frey wrote:
I have use cases which would be a lot easier to implement if shared_from_this() never throws. And - at least with the "old" implementation - I don't see any reason why this guarantee should not hold. Of course it's not a defect, but to me it seems desirable.
It is technically possible to make it throw without violating the functions documented requirements, if there are multiple owners. For example, if pass the raw pointer to multiple shared_ptrs with null deleters.
Could you provide a small but complete code example, please? I fail to see how that case should be legal. Regards, Daniel

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Wednesday 09 April 2008 14:07 pm, Daniel Frey wrote:
On Wed, 2008-04-09 at 13:47 -0400, Frank Mori Hess wrote:
On Wednesday 09 April 2008 11:13 am, Daniel Frey wrote:
I have use cases which would be a lot easier to implement if shared_from_this() never throws. And - at least with the "old" implementation - I don't see any reason why this guarantee should not hold. Of course it's not a defect, but to me it seems desirable.
It is technically possible to make it throw without violating the functions documented requirements, if there are multiple owners. For example, if pass the raw pointer to multiple shared_ptrs with null deleters.
Could you provide a small but complete code example, please? I fail to see how that case should be legal.
Here you go, this throws against the old library. It doesn't against the trunk, due to a slight change in behavior, but could easily be modified to do so. - -- Frank -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) iD8DBQFH/Qfu5vihyNWuA4URAgMaAKCpxwhzr7c4wIpxWjOTizCeWLGZaQCeI8jV Ta0uHXG6PRTWMI224Z67WF4= =DOZL -----END PGP SIGNATURE-----

On Wed, 2008-04-09 at 14:16 -0400, Frank Mori Hess wrote:
Here you go, this throws against the old library. It doesn't against the trunk, due to a slight change in behavior, but could easily be modified to do so.
Wow. Impressive. I haven't found the part of the documentation which makes your example illegal, but my gut feeling is that it should be illegal :) Is there really no rule in the documentation which states that one object should not - at any point in time - be owned by two shared_ptr's that don't share ownership? Regards, Daniel

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Wednesday 09 April 2008 08:07 am, Daniel Frey wrote:
Before the change, I even wondered if the weak_ptr could be replaced by a detail::weak_count, which would reduce the overhead from two plain pointers to only one plain pointer, since shared_from_this always has *this.
But *this inside enable_shared_from_this<T> is not a T*, it is a enable_shared_from_this<T>*. To downcast it to a T* requires a dynamic_cast for the general case, which requires a vtable. Not that I consider a vtable to be significant overhead (I know, it's a horrifiying opinion for a C++ programmer but there it is). - -- Frank -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) iD8DBQFH/P925vihyNWuA4URAgQHAKDGiQq+OzEyLcGyCNwUk39rM6hFKwCfXGAx bohqAEpSPt9NJKUPBSWWn6U= =j1Bh -----END PGP SIGNATURE-----

On Wed, 2008-04-09 at 13:40 -0400, Frank Mori Hess wrote:
But *this inside enable_shared_from_this<T> is not a T*, it is a enable_shared_from_this<T>*. To downcast it to a T* requires a dynamic_cast for the general case, which requires a vtable. Not that I consider a vtable to be significant overhead (I know, it's a horrifiying opinion for a C++ programmer but there it is).
static_cast<T*>(this) should be legal AFAIK (and doesn't need a vtable) Regards, Daniel

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Wednesday 09 April 2008 14:13 pm, Daniel Frey wrote:
On Wed, 2008-04-09 at 13:40 -0400, Frank Mori Hess wrote:
But *this inside enable_shared_from_this<T> is not a T*, it is a enable_shared_from_this<T>*. To downcast it to a T* requires a dynamic_cast for the general case, which requires a vtable. Not that I consider a vtable to be significant overhead (I know, it's a horrifiying opinion for a C++ programmer but there it is).
static_cast<T*>(this) should be legal AFAIK (and doesn't need a vtable)
It works in some cases, but it will fail the smart_ptr/test/shared_from_this_test.cpp test for example. - -- Frank -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) iD8DBQFH/Qh15vihyNWuA4URAoanAKDl0x7Gg7kLDonOZtds/xeIG/eBngCgtP7Z +fVQ6X5wP/WT7JRyAnSJtf8= =m0wT -----END PGP SIGNATURE-----

On Wed, 2008-04-09 at 14:18 -0400, Frank Mori Hess wrote:
On Wednesday 09 April 2008 14:13 pm, Daniel Frey wrote:
static_cast<T*>(this) should be legal AFAIK (and doesn't need a vtable)
It works in some cases, but it will fail the smart_ptr/test/shared_from_this_test.cpp test for example.
You are right. Which makes the optimization possible only for cases where enable_shared_from_this<T> is not a virtual base class of T. What do you (and others) think about branching enable_shared_from_this<T> into two classes: low_overhead_enable_shared_from_this<T> and feature_rich_enable_shared_from_this<T> Yes, the names are crap, we need better ones :) Apart from that, I think it might be worth it. The first one would be the classic one plus the limitation you pointed out for virtual base classes, with an overhead of just 4 bytes, while the second one is the trunk version which offers a lot more features but currently has an overhead of 4 pointers, a vtable and a bool. Note that I don't think that one of the classes is "better" than the other, I just think that each class has valid use cases which can not be satisfied by the other class. Regards, Daniel

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Wednesday 09 April 2008 15:47 pm, Daniel Frey wrote:
What do you (and others) think about branching enable_shared_from_this<T> into two classes:
low_overhead_enable_shared_from_this<T>
and
feature_rich_enable_shared_from_this<T>
What I would like better is something like a simple base class that shared_ptr recognizes, which only has a single virtual member function like virtual void accept_owner(shared_ptr<T> &owner); which shared_ptr would call when it takes ownership of an object derived from the aforementioned base class. Then you could use it to implement your stripped down version of enable_shared_from_this, or whatever else you might think of. Of course, you would still be inflicted with a vtable, but that doesn't add any per-object space overhead, which seems to be what you're most concerned about. - -- Frank -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) iD8DBQFH/S+/5vihyNWuA4URAl7OAKCRK7OTsHU2H4a0GKuLeMKyyvcDxgCffB7+ OqJHVtck2ucIbrqotEU7yd0= =+6v3 -----END PGP SIGNATURE-----

On Wed, 2008-04-09 at 17:06 -0400, Frank Mori Hess wrote:
think of. Of course, you would still be inflicted with a vtable, but that doesn't add any per-object space overhead, which seems to be what you're most concerned about.
A vtable means that the per-object size *does* grow, since each object needs a pointer to the vtable. Regards, Daniel

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Wednesday 09 April 2008 17:26 pm, Daniel Frey wrote:
On Wed, 2008-04-09 at 17:06 -0400, Frank Mori Hess wrote:
think of. Of course, you would still be inflicted with a vtable, but that doesn't add any per-object space overhead, which seems to be what you're most concerned about.
A vtable means that the per-object size *does* grow, since each object needs a pointer to the vtable.
Oh, yeah. Well, it could be done generically too without even a vtable, if shared_ptr recognized a template class which the user could define specializations of. - -- Frank -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) iD8DBQFH/Vus5vihyNWuA4URAo4dAJ9gD9mtfHp2Azvr5ejGWAzPMiFxDACfUo2H 8nDJsrABHOCnou+rFEuYhuw= =UtPP -----END PGP SIGNATURE-----

On Wed, 2008-04-09 at 20:13 -0400, Frank Mori Hess wrote:
On Wednesday 09 April 2008 17:26 pm, Daniel Frey wrote:
On Wed, 2008-04-09 at 17:06 -0400, Frank Mori Hess wrote:
think of. Of course, you would still be inflicted with a vtable, but that doesn't add any per-object space overhead, which seems to be what you're most concerned about.
A vtable means that the per-object size *does* grow, since each object needs a pointer to the vtable.
Oh, yeah. Well, it could be done generically too without even a vtable, if shared_ptr recognized a template class which the user could define specializations of.
I attached a minimalistic patch against the trunk which enhances the current code into that direction. The name (enable_shared_from_this_base) is probably not a good name. I think that from shared_ptr's point of view, it doesn't need to know what the callback is used for. It might be better to call it notify_on_ownership or something in that direction. And the callback function should probably also be renamed. Suggestions? The next logical step would be to add another ctor for the low_overhead_enable_shared_from_this, i.e. a ctor for shared_ptr which takes a plain pointer and a weak_count or a shared_count?). Or it might be possible to generalize that case with the current special ctor that takes the ignore_enable_shared_from_this_tag, but that's a second patch on top of the first one, which I will try to write when my time permits. Regards, Daniel

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Thursday 10 April 2008 06:40 am, Daniel Frey wrote:
On Wed, 2008-04-09 at 20:13 -0400, Frank Mori Hess wrote: I attached a minimalistic patch against the trunk which enhances the current code into that direction.
The static_cast in your patch is going to have problems with virtual base classes. I think you could just use the Y* available in sp_enable_shared_from_this and call _internal_accept_owner from that. Also, on further thought, I don't think enable_shared_from_this_base needs to be a template class at all.
The name (enable_shared_from_this_base) is probably not a good name. I think that from shared_ptr's point of view, it doesn't need to know what the callback is used for. It might be better to call it notify_on_ownership or something in that direction. And the callback function should probably also be renamed. Suggestions?
I agree. notify_on_ownership seems ok. Some other possibilities are ownership_observer or shared_ptr_observer. The callback might be accept_shared_ptr_owner() or update_shared_ptr_owner() Also, I don't think enable_shared_from_this should actually use this base class in the end, whatever it is called (although it is a good test). If it does, the user will have to take special care to avoid problems when deriving from both enable_shared_from_this and this base class. This might happen if the user is deriving from the base class for purposes other than re-implementing enable_shared_from_this. - -- Frank -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) iD8DBQFH/hXl5vihyNWuA4URApOvAKCbEPJ81hykihJXVQDsJMaIjzYVeACfZoFZ tzESBNqzyeWB6E6YgNnvF5E= =n3li -----END PGP SIGNATURE-----

On Thu, 2008-04-10 at 09:27 -0400, Frank Mori Hess wrote:
On Thursday 10 April 2008 06:40 am, Daniel Frey wrote:
On Wed, 2008-04-09 at 20:13 -0400, Frank Mori Hess wrote: I attached a minimalistic patch against the trunk which enhances the current code into that direction.
The static_cast in your patch is going to have problems with virtual base classes. I think you could just use the Y* available in sp_enable_shared_from_this and call _internal_accept_owner from that.
Note that 5.2.9/8 only refers to B and D's relationship. Since we are creating a new base class, we can define that non-virtual derivation is a precondition. In the patch I've shown the static_cast should be perfectly legal and it should work in all cases, AFAICT.
Also, on further thought, I don't think enable_shared_from_this_base needs to be a template class at all.
If you have an easier implementation without further overhead, I'd be happy to see it.
The name (enable_shared_from_this_base) is probably not a good name. I think that from shared_ptr's point of view, it doesn't need to know what the callback is used for. It might be better to call it notify_on_ownership or something in that direction. And the callback function should probably also be renamed. Suggestions?
I agree. notify_on_ownership seems ok. Some other possibilities are ownership_observer or shared_ptr_observer. The callback might be accept_shared_ptr_owner() or update_shared_ptr_owner()
Those are excellent suggestions. I think shared_ptr_observer and update_shared_ptr_owner are the names I like most.
Also, I don't think enable_shared_from_this should actually use this base class in the end, whatever it is called (although it is a good test). If it does, the user will have to take special care to avoid problems when deriving from both enable_shared_from_this and this base class. This might happen if the user is deriving from the base class for purposes other than re-implementing enable_shared_from_this.
Good point. I'll need some time to think about this case. Regards, Daniel

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Thursday 10 April 2008 09:57 am, Daniel Frey wrote:
On Thu, 2008-04-10 at 09:27 -0400, Frank Mori Hess wrote:
Also, on further thought, I don't think enable_shared_from_this_base needs to be a template class at all.
If you have an easier implementation without further overhead, I'd be happy to see it.
This patch against trunk illustrates what I have in mind: shared_ptr_observer doesn't need to be a template class. I derived enable_shared_from_this from shared_ptr_observer so I could verify it still passes all the smart_ptr tests. - -- Frank -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) iD8DBQFH/is95vihyNWuA4URApWKAJ9j/aAg3bR2bi9xttLngQtlsJCydACgq3EY 7RQkDMmoMEDoGlsx4P0PY/c= =93cK -----END PGP SIGNATURE-----

On Thu, 2008-04-10 at 10:59 -0400, Frank Mori Hess wrote:
On Thursday 10 April 2008 09:57 am, Daniel Frey wrote:
On Thu, 2008-04-10 at 09:27 -0400, Frank Mori Hess wrote:
Also, on further thought, I don't think enable_shared_from_this_base needs to be a template class at all.
If you have an easier implementation without further overhead, I'd be happy to see it.
This patch against trunk illustrates what I have in mind: shared_ptr_observer doesn't need to be a template class. I derived enable_shared_from_this from shared_ptr_observer so I could verify it still passes all the smart_ptr tests.
I like that you call _internal_accept_owner on T* directly, still I think that I template class for tagging has some advantages. See the attached code I played with. In it, A has the role of the tag class. As the code shows, it is possible to have multiple classes like these, you just need some manual forwarding in the more complicated cases. Regards, Daniel

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Thursday 10 April 2008 19:13 pm, Daniel Frey wrote:
I like that you call _internal_accept_owner on T* directly, still I think that I template class for tagging has some advantages. See the attached code I played with. In it, A has the role of the tag class. As the code shows, it is possible to have multiple classes like these, you just need some manual forwarding in the more complicated cases.
I don't understand what the benefit will be when applied to shared_ptr_observer? All I get from the example is that if you have a class X derived from A<T>, you can tell whether X and T are the same type or not. Manual forwarding works just as well without a template parameter. Maybe if you explained (as if writing user documentation for the feature) what the template argument of shared_ptr_observer is supposed to be set to, and what effect it would have? The behavior associated with a non-template shared_ptr_observer tag can be spelled out in 1 or 2 sentences. - -- Frank -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) iD8DBQFH/2pH5vihyNWuA4URAquYAKDTKLDvhhPwR2iX1z1ZVTa+U10cfwCggxu4 UiOrwvqiVdcGY7uMhyjeDjc= =7v9/ -----END PGP SIGNATURE-----

On Fri, 2008-04-11 at 09:40 -0400, Frank Mori Hess wrote:
On Thursday 10 April 2008 19:13 pm, Daniel Frey wrote:
I like that you call _internal_accept_owner on T* directly, still I think that I template class for tagging has some advantages. See the attached code I played with. In it, A has the role of the tag class. As the code shows, it is possible to have multiple classes like these, you just need some manual forwarding in the more complicated cases.
I don't understand what the benefit will be when applied to shared_ptr_observer? All I get from the example is that if you have a class X derived from A<T>, you can tell whether X and T are the same type or not. Manual forwarding works just as well without a template parameter. Maybe if you explained (as if writing user documentation for the feature) what the template argument of shared_ptr_observer is supposed to be set to, and what effect it would have? The behavior associated with a non-template shared_ptr_observer tag can be spelled out in 1 or 2 sentences.
I enhanced the example and added some comments. The reason for having a template tag class is that you can fix otherwise problematic cases when multiple tags are present. I don't think we can do the redirection automatically (except when someone adds compile-time reflection that allows us to iterator over the base classes), but at least there is a way to support this use case by a little bit of extra work. Regards, Daniel

Daniel Frey:
I enhanced the example and added some comments. The reason for having a template tag class is that you can fix otherwise problematic cases when multiple tags are present.
I'm still not 100% convinced that we need this functionality in shared_ptr. But if we do, it seems that the proper way to add it is to make shared_ptr issue an unqualified call to sp_accept_owner( this, p ); which the user will now be free to add to the namespace of *p or one of its base classes. Your code, for example, would now have template<class T> void sp_accept_owner( shared_ptr<T> * p, shared_ptr_debugger * q ); in the namespace of shared_ptr_debugger, and another overload in the namespace of C4 that would resolve the ambiguity.

On Fri, 2008-04-11 at 19:11 +0300, Peter Dimov wrote:
I'm still not 100% convinced that we need this functionality in shared_ptr.
How many % is it currently? ;)
But if we do, it seems that the proper way to add it is to make shared_ptr issue an unqualified call to
sp_accept_owner( this, p );
which the user will now be free to add to the namespace of *p or one of its base classes. Your code, for example, would now have
template<class T> void sp_accept_owner( shared_ptr<T> * p, shared_ptr_debugger * q );
in the namespace of shared_ptr_debugger, and another overload in the namespace of C4 that would resolve the ambiguity.
That's a very good idea. And it's not very different from the current code anyway. Moving code around a bit, I ended up with the attach patch against HEAD. It also seems cleaner to me (compared with the HEAD version), as enable_shared_from_this is no longer forward declared in shared_ptr.hpp and the registration of the observer can be moved to enable_shared_from_this.hpp. I'll try to write an alternative enable_shared_from_this class with only a single plain pointer overhead based on the attached patch. At least to me enable_shared_from_this' efficiency/overhead is far more important than additional features that I never needed so far. Having a choice seems highly desirable. Regards, Daniel

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Friday 11 April 2008 12:11 pm, Peter Dimov wrote:
I'm still not 100% convinced that we need this functionality in shared_ptr. But if we do, it seems that the proper way to add it is to make shared_ptr issue an unqualified call to
sp_accept_owner( this, p );
It does provide an alternative to making shared_from_this() callable in constructors. As long as sp_accept_owner() is always run after enable_shared_from_this is set up (and there is no reason it can't be since shared_ptr is fully aware of enable_shared_from_this) then it is usable as a post constructor where shared_from_this can be used safely. Actually, you don't even need enable_shared_from_this if don't need to use shared_from_this() outside the postconstructor, since you are passed in the owning shared_ptr. - -- Frank -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) iD8DBQFH/6eb5vihyNWuA4URAm1sAKC1tyt47Sht/EUzduL1E8x4HUGMBgCdFXFE zuOYVtIF4UpU9sskqZYp13Q= =OlLr -----END PGP SIGNATURE-----

Frank Mori Hess:
On Friday 11 April 2008 12:11 pm, Peter Dimov wrote:
I'm still not 100% convinced that we need this functionality in shared_ptr. But if we do, it seems that the proper way to add it is to make shared_ptr issue an unqualified call to
sp_accept_owner( this, p );
It does provide an alternative to making shared_from_this() callable in constructors. As long as sp_accept_owner() is always run after enable_shared_from_this is set up (and there is no reason it can't be since shared_ptr is fully aware of enable_shared_from_this) then it is usable as a post constructor where shared_from_this can be used safely. Actually, you don't even need enable_shared_from_this if don't need to use shared_from_this() outside the postconstructor, since you are passed in the owning shared_ptr.
You're right! sp_accept_owner can indeed be used as a postconstructor. My original idea was for it to replace sp_enable_shared_from_this entirely, making enable_shared_from_this non-special and fully implementable in "user mode". This doesn't seem to be a problem for the use case you describe though. The programmer would just implement sp_accept_owner for the derived class and call sp_accept_owner( (esft*)this ) before using shared_from_this.

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Thursday 10 April 2008 06:40 am, Daniel Frey wrote:
The next logical step would be to add another ctor for the low_overhead_enable_shared_from_this, i.e. a ctor for shared_ptr which takes a plain pointer and a weak_count or a shared_count?).
Actually, you could use weak_ptr::_internal_assign, which was used by the old enable_shared_from_this, but I don't think it's used for anything now. - -- Frank -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) iD8DBQFH/h0i5vihyNWuA4URAhK9AJ4us1QaRqlyOY93jCJM1KFpbD4QogCguntp I8h2LwyzR4ZHhO74oiiJ0oI= =6ahW -----END PGP SIGNATURE-----
participants (3)
-
Daniel Frey
-
Frank Mori Hess
-
Peter Dimov