Add "weak_from_this" to std::enable_shared_from_this

1,198 views
Skip to first unread message

Jared Grubb

unread,
Aug 24, 2013, 4:57:24 PM8/24/13
to std-pr...@isocpp.org
I'd like to propose to add a new "weak_from_this" member function to the std::enable_shared_from_this class. This has two advantages:

1. Enables use of 'auto':
auto weak_handle = weak_from_this();

2. Minor efficiency bump over today's version:
std::weak_ptr<Foo> weak_handle = shared_from_this(); // downgrade of a temporary shared_ptr object

I think every implementation of std::enable_shared_from_this is just a wrapper of a weak_ptr anyway. Providing a method that copies the internal variable is more efficient than using shared_from_this, which lock()s the internal weak_ptr, only to just immediately degrade back to a weak reference.

This is my first attempt at proposing a feature, so forgive my newbness :)

Jared

Nicol Bolas

unread,
Aug 24, 2013, 9:00:57 PM8/24/13
to std-pr...@isocpp.org
On Saturday, August 24, 2013 1:57:24 PM UTC-7, Jared Grubb wrote:
I'd like to propose to add a new "weak_from_this" member function to the std::enable_shared_from_this class.

I would prefer something less limited: a `to_weak_ptr` function that takes a shared_ptr<T> and returns an appropriate weak_ptr<T>.
 
This has two advantages:

1. Enables use of 'auto':
       auto weak_handle = weak_from_this();

auto weak_handle = to_weak_ptr(shared_from_this());

2. Minor efficiency bump over today's version:
       std::weak_ptr<Foo> weak_handle = shared_from_this();  // downgrade of a temporary shared_ptr object 
I think every implementation of std::enable_shared_from_this is just a wrapper of a weak_ptr anyway.

But it doesn't have to be. And we shouldn't make features based on the assumption that something will be implemented in a certain way.

Jared Grubb

unread,
Aug 24, 2013, 9:47:53 PM8/24/13
to std-pr...@isocpp.org


On Saturday, August 24, 2013 6:00:57 PM UTC-7, Nicol Bolas wrote:
On Saturday, August 24, 2013 1:57:24 PM UTC-7, Jared Grubb wrote:
I'd like to propose to add a new "weak_from_this" member function to the std::enable_shared_from_this class.

I would prefer something less limited: a `to_weak_ptr` function that takes a shared_ptr<T> and returns an appropriate weak_ptr<T>.

I agree this is also a desirable feature. I was converting a couple of my libraries from boost::shared_ptr to std::shared_ptr, and as a transition, I was adding a bunch of "auto" in places, but got stuck in the weak_ptr cases, because I had to use the right weak_ptr variety, and there was no built-in "trait" I could consult to get the corresponding weak_ptr variety.
  
This has two advantages:

1. Enables use of 'auto':
       auto weak_handle = weak_from_this();

auto weak_handle = to_weak_ptr(shared_from_this());

2. Minor efficiency bump over today's version:
       std::weak_ptr<Foo> weak_handle = shared_from_this();  // downgrade of a temporary shared_ptr object 
I think every implementation of std::enable_shared_from_this is just a wrapper of a weak_ptr anyway.

But it doesn't have to be. And we shouldn't make features based on the assumption that something will be implemented in a certain way.

I argue the feature is helpful no matter how it is implemented (although, honestly, I cant really imagine any other way to do it that wouldnt involve effectively reinventing a weak_ptr).

In C++11, constructing a weak_ptr via "shared_from_this" will create a +1 strong reference, then a +1 weak reference, then a -1 strong reference in the ~shared_ptr(); so you require 3 reference count modifications.

If enable_shared_from_this uses a weak_ptr internally, then a "weak_from_this" is just a +1 weak reference with no calls to lock().

If enable_shared_from_this uses some other implementation, it could (at worst) implement weak_from_this using the naive "return shared_from_this();" version that achieves the same as C++11 does today; but it also could choose to do something more efficient.

So in all cases, you do no worse. But in most implementations, the implementation is a one-liner call to a copy constructor, you get 'auto' for free, and you gain a significant efficiency bump.

Jeffrey Yasskin

unread,
Aug 24, 2013, 10:57:18 PM8/24/13
to std-pr...@isocpp.org
Seems like a reasonable idea, although not a slam dunk. I see #2 as
more important for adding to the enable_shared_from_this interface
because it can't be implemented outside of the interface, while
Nicol's "to_weak_ptr" satisfies your #1 and can be implemented outside
of the standard. We'll need a paper in order to actually make the
change, and I think you'd have a higher chance of acceptance if that
paper explores the actual performance impact in 2-3 widely-used
implementations of enable_shared_from_this. You should also try to
find some indication of how often this feature would be used in real
codebases and how performance-critical such uses are. Also see if
anyone (especially standard library maintainers) can think of other
ways to get a similar speedup without adding to the interface.

Re Nicol's "enable_shared_from_this doesn't *have* to wrap weak_ptr",
that's ok, since this feature is implementable even in libraries that
aren't implemented that way; it just might not give as much of a
speedup.

See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/ for some
papers you can imitate, and "Paper submissions for the upcoming
mailing" on this mailing list for instructions on submitting a paper.

Jeffrey
Reply all
Reply to author
Forward
0 new messages