Search code examples
c++design-patternsboostshared-ptr

CRTP pattern and enable_shared_from_this


In my current code I have an TNCPConnection class which is derived from enable_shared_from_this:

class TNCPConnection : public boost::enable_shared_from_this<TNCPConnection> { ... };

Now I need to create a second class ETCPConnection which will share a lot of code with the existing TNCPConnection class. So the obvious solution is to have an abstract base class CPConnectionBase which implements the common functionality.

I know that only one class in a inheritance hierarchy can derive from enable_shared_from_this. While looking for a solution I stumbled across the CRTP pattern, but I'm not sure if I understood this correctly. Here is my approach:

template <class Derived>
class CPConnectionBase : public boost::enable_shared_from_this<Derived>
{
public:

    CPConnectionBase(void) { }
    virtual ~CPConnectionBase(void) = 0 { }
};

class TNCPConnection : public CPConnectionBase<TNCPConnection> { ... };

class ETCPConnection : public CPConnectionBase<ETCPConnection> { ... };

Is this the correct way to solve my problem? Will reference counting work correctly with this approach? In particular I'd like to know if the template parameter of enable_shared_from_this must be Derived (as in the example above) or something like CPConnectionBase<Derived>?


Solution

  • If you use that approach each derived class will have its own unique base class. Even though they have the same name they will be different instantiations. Are you sure that having the base class inherit from enable_shared_from_this won't provide the capability to all children?

    Also, which will share a lot of code with the existing ... class. is not an immediate indicator to use inheritance. In general, inherit to extend, not to reuse. If all the base class does is implement common functionality but doesn't provide a common interface to the two classes you should probably rethink the approach. Either use composition and delegation to the common methods, or, if they don't have continuous state, put the common code into (possibly anonymous) namespaces and call them from the actual functional classes you need. You haven't provided quite enough information to determine exactly what you're trying to do.