A free-standing weak_ptr equivalent to handle lifetime of non-shared callback objects I've been finding myself wanting the following pattern recently:

void perform_async_operation(std::function&lt;void(int)&gt;);

class some_class {
  public:
    void foo() {
      perform_async_operation([this](int result) {
        data_ = result;
      });
    }

  private:
    int data_;
};


Now, the issue here is that the lifetime of some_class if fully disconnected from when the callback will be invoked, and I do not want to move to shared ownership to put a shared_ptr in the lambda (like how the boost::ASIO examples handle that situation).

I do, however, have a saving grace: I know for certain that the callback will be invoked in the same thread that manages the lifetime of some_class.

In order to solve this, I've created a bastardized version of weak_ptr (with a matching equivalent of enabled_shared_from_this) that does not require the object to be managed by a shared_ptr in the first place.

#ifndef SLT_WEAK_REF_INCLUDED_H
#define SLT_WEAK_REF_INCLUDED_H

#include &lt;memory&gt;

template &lt;typename T&gt;
class weak_ref {
 public:
  weak_ref(std::shared_ptr&lt;T*&gt; weak_data) : weak_data_(std::move(weak_data)) {}

  operator bool() const { return *weak_data_ != nullptr; }
  T* operator-&gt;() const { return *weak_data_; }

 private:
  // Can be safely assumed to always be set.
  std::shared_ptr&lt;T*&gt; weak_data_;
};

template &lt;typename CRTP&gt;
class enable_weak_ref {
 public:
  enable_weak_ref() = default;
  enable_weak_ref(enable_weak_ref&amp;&amp; rhs)
      : weak_data_(std::move(rhs.weak_data_)) {
    if (weak_data_) {
      *weak_data_ = this;
    }
  }

  enable_weak_ref&amp; operator=(enable_weak_ref&amp;&amp; rhs) {
    weak_data_ = std::move(rhs.weak_data_);
    if (weak_data_) {
      *weak_data_ = static_cast&lt;CRTP*&gt;(this);
    }
  }

  // explicitely do nothing
  enable_weak_ref(enable_weak_ref const&amp; rhs) {}
  enable_weak_ref&amp; operator=(enable_weak_ref const&amp;) {}

  ~enable_weak_ref() {
    if (weak_data_) {
      *weak_data_ = nullptr;
    }
  }

  weak_ref&lt;CRTP&gt; get_weak_ref() {
    if (!weak_data_) {
      weak_data_ = std::make_shared&lt;CRTP*&gt;(static_cast&lt;CRTP*&gt;(this));
    }

    return weak_ref&lt;CRTP&gt;(weak_data_);
  }

 private:
  // TODO: perhaps switch to a simple manually ref-counted type here.
  // instead of the overkill shared_ptr&lt;&gt;
  std::shared_ptr&lt;CRTP*&gt; weak_data_;
};

#endif


sample usage:

#include "weak_ref.h"

#include &lt;queue&gt;
#include &lt;iostream&gt;
#include &lt;functional&gt;

std::queue&lt;std::function&lt;void(int)&gt;&gt; queue_;

void queue_delayed(std::function&lt;void(int)&gt; cb) {
  queue_.emplace(std::move(cb));
}

class my_class : public enable_weak_ref&lt;my_class&gt; {
public:
  my_class() {
    queue_delayed([ref = get_weak_ref()](int v){
      if(ref) {
        std::cout &lt;&lt; "passed " &lt;&lt; v &lt;&lt; std::endl;
        ref-&gt;value = v;
      }
      else {
        std::cout &lt;&lt; "saved " &lt;&lt; v &lt;&lt; std::endl;
      }
    });
  }

  int value = 0;
};

int main() {
  my_class a;
  queue_.front()(12);
  queue_.pop();
  {
    my_class b;
  }
  queue_.front()(5);
  queue_.pop();

  return 0;
}


Notes:


Moving an object in a lambda is a C++14 feature, without which, a lot of back-and-forth ref-counting happens. 
As mentioned, this is intentionally not thread-safe. Thread safety can be added if anyone needs it eventually.


Issues:


Is there a nicer way to tackle this I'm overlooking here?
weak_ref is very weak name, I'd gladly welcome better suggestions.
As always, comments on general code quality are most desired.
I never saw a similar pattern so it was really interesting to understand your code !

First, about the name weak_ref, it implies that it has the syntax of a reference, but it is not the case (for instance, operator-&gt; is for pointers). I personnaly named it something like ptr_to_instance.

Then, it seems the weak_ref should not be used on its own, without calling enable_weak_ref::get_weak_ref(). So I will make the weak_ref constructor private, making enable_weak_ref a friend. I will put the weak_ref class inside enable_weak_ref :

template&lt;typename CRTP&gt;
class enable_weak_ref {
  public:
    class weak_ref { /**/ };
    /**/
};


So instead of weak_ref&lt;T&gt; we have enable_weak_ref&lt;T&gt;::weak_ref. I think it makes more understandable the use of these classes.

Also, because weak_ref should not modify the pointer in weak_data_, I would use std::shared_ptr&lt;T* const&gt; so it is clear that this pointer is for read-only use.

If you do not want to use std::shared_ptr, you should create a int* (counting references), a CRTP** (which will hold this or nullptr) in enable_weak_ref, and weak_ref should have a int* const and a CRTP const* const (const specifier shows that weak_ref is linked to only one enable_weak_ref and can not be changed).