Fibbs
Fibbs

Reputation: 1420

Is there a weak_ptr equivalent to shared_from_this?

I have a class which I know will always be owned by a std::shared_ptr. However passing shared_ptr or even weak_ptr to functions and methods that don't need ownership or lifetime guarantees creates unnecessary overhead. To get around this I often pass raw pointers to functions. The class itself inherits from std::enable_shared_from_this so if the function needs to take ownership of the pointer it can use a method of the class to get a shared_ptr.

This is all working beautifully. However there are occasions where I don't really want to make a shared_ptr from a raw pointer, what I want instead is a weak_ptr.

From what I understand of the usual implementation of std::shared_ptr it has two atomic variables used as reference counters; one for shared_ptr, one for weak_ptr.

If all I have is a raw pointer to my class and I want a weak_ptr, I must first create a shared_ptr and convert it. Doing so means the reference counters are altered like this:

This seems to go against the idea that "you don't pay for what you don't use". Is there a way for my class to just provide weak_ptr without first creating a shared_ptr?

Upvotes: 12

Views: 14362

Answers (3)

Nicol Bolas
Nicol Bolas

Reputation: 474126

Is there a way for my class to just provide weak_ptr without first creating a shared_ptr?

Not in C++14; the only operation that enable_shared_from_this supports is creating a shared_ptr. Now, enable_shared_from_this should have sufficient information to construct a weak_ptr directly. But you can't do it from the outside, as the class doesn't expose its implementation details to you.

C++17 has support for fetching a weak_ptr from an enable_shared_from_this class via weak_from_this.

Upvotes: 13

Kerrek SB
Kerrek SB

Reputation: 477444

Proposal P0033 was accepted for C++17 in the October 2015 meeting, which adds weak_from_this to classes deriving from std::enable_shared_from_this.

Upvotes: 15

Richard Hodges
Richard Hodges

Reputation: 69912

It's almost so trivial to implement that it's not worth putting in the library...

#include <memory>

template<class T> std::weak_ptr<T> weak_from_this(T*p) {
  return { p->shared_from_this() };
}

struct S : std::enable_shared_from_this<S>
{
  auto foo() {
    return weak_from_this(this);
  }
};


int main()
{
  auto ps = std::make_shared<S>();
  auto wps = ps->foo();
}

Upvotes: 4

Related Questions