The enable_shared_from_this Class Template

2.6. The enable_shared_from_this Class Template

template<class Ty>
  class enable_shared_from_this {
  shared_ptr<Ty> shared_from_this();
  shared_ptr<const Ty> shared_from_this() const;
protected :
  enable_shared_from_this(const enable_shared_from_this&);
  enable_shared_from_this& operator=(
    const enable_shared_from_this&);
  ~ enable_shared_from_this();

The member function shared_ptr::get gives you a pointer to the resource that a shared_ptr object owns. To go the other way, getting a shared_ptr object that owns the resource pointed to by a raw pointer, the obvious approach is to construct a shared_ptr object. However, if the resource is already owned by another shared_ptr object, you'll now have two shared_ptr objects that know nothing about each other and own the same resource. This will lead to problems, as both of the shared_ptr objects or their progeny will eventually try to delete the same object. To avoid this problem, types that will be managed through shared_ptr objects can provide a member function that returns a shared_ptr object that shares ownership with the original manager object. This is tricky to implement without tampering with the implementation of shared_ptr, so the class template enable_shared_from_this provides the member function shared_from_this.

To use the template enable_shared_from_this with a class Ty, make enable_shared_from_this<Ty> a public base of Ty:

class C : public enable_shared_from_this <C>
  // ...

Now if you create an object of type shared_ptr<C> from a pointer to a fully constructed object of type C [5] the shared_ptr code will make a note in the enable_shared_from_this base subobject, and its member function shared_from_this will return a shared_ptr<C> object that shares ownership with the shared_ptr<C> object that you created.

[5] Don't do this from C's constructor. It probably won't work.


shared_ptr<Ty> enable_shared_from_this::shared_from_this();
shared_ptr<const Ty>
  enable_shared_from_this::shared_from_this() const;

The member functions return a shared_ptr object that shares ownership with the original owner of *this.

Figure. shared_from_this (smartptr/enshared.cpp)

#include <memory>
#include <ostream>
#include "sputil.h"
using std::tr1::shared_ptr;
using std::tr1::enable_shared_from_this;
using std::basic_ostream;

struct C : enable_shared_from_this <C>, resource
  C(int i0 = 0) : resource(i0) {}

static void show_sp(C * cp)
  show ("from this", spc);
int main()
  shared_ptr<C> sp(new C(1));
  show("original object", sp);
  C *cp = sp.get();
  show("after return", sp);
  return 0;

Creation, Destruction, and Assignment

  const enable_shared_from_this&);
enable_shared_from_this& enable_shared_from_this::operator=(
  const enable_shared_from_this&);
enable_shared_from_this::~ enable_shared_from_this();

The constructors, destructor, and assignment operator do not throw exceptions.

These members are protected to help prevent accidental misuse. Make sure that your derived class calls them as appropriate.

Figure. enable_shared_from_this (smartptr/enderive.cpp)

#include <memory>
#include "sputil.h"
using std::tr1::enable_shared_from_this;

class derived : public enable_shared_from_this<derived>
  typedef enable_shared_from_this<derived> base;
  derived() {}               // calls default constructor for base
  derived(const derived& der)
    : base(der) {}           // explicit call to copy constructor for base
  derived& operator =(const derived& der)
    base::operator =(der);   // explicit call to assignment operator
  ~derived () {}             // calls destructor for base

 Python   SQL   Java   php   Perl 
 game development   web development   internet   *nix   graphics   hardware 
 telecommunications   C++ 
 Flash   Active Directory   Windows