Boost logo

Boost Users :

Subject: [Boost-users] shared_ptr and circular dependency
From: Christopher Pisz (cpisz_at_[hidden])
Date: 2012-03-30 15:26:48


What are one's options when the code one is working on contains a circular
dependency and one is trying to update it to use a shared_ptr vs a raw pointer?

I don't think I can easily get rid of the preexisting circular dependency. The
original author has created an inheritance where the base needs the derived.
We all know this is wrong, but it would take quite a bit to analyze how it is
used and be removed.

Am I out of luck?

Fictitious Example (best minimal example including the problems the
preexisting code has):

// File MasterClient.h
#include "BaseClient.h"
#include <set>

class MasterClient : BaseClient
{
   public:

      // Constructor adds this to the collection of clients
      // It is later included in the processing of all clients
      MasterClient();

      // SNIP
   private:
      typedef std::set<Base *> Clients;
      Clients clients_;

      // Thread function that iterates over all clients
      // including this instance and makes calls on them
      void Process();
};

// file BaseClient.h
class MasterClient;

class BaseClient
{
   public:

      // Constructor
      BaseClient(MasterClient * master);

      // SNIP interface

   private:
      MasterClient * master_; // I really need this to be a shared_ptr

      // Thread function that makes calls to the MasterClient
      virtual void Process();
};

----------------------------
I gave it my best shot and have 2 errors that I can't figure out:
C2664: BaseClient::BaseClient(boost::shared_ptr<T>) cannot convert parameter 1
from boost::shared_ptr<T> to boost::shared_ptr<T>
C2385: ambiguous access of 'shared_from_this'

I have to use enable shared from this to be passing around the shared_ptr from
myself, no? I am also worried about using this in the intializer list, is it a
problem?

I believe both classes cannot inherit from it. I am not sure how to change it
up. any suggestions?

We are using VC2008, so I cannot use the standard shared_ptr yet, but I
believe the boost version is the same...

My attempt:

/*
* BaseClient.h
*/
#ifndef BASECLIENT_H
#define BASECLIENT_H

#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>

//-------------------------------
class MasterClient;

//-------------------------------
class BaseClient : public boost::enable_shared_from_this<BaseClient>
{
public:

    typedef boost::shared_ptr<BaseClient> SharedPtr;

    // Enforces that every instance must be a shared_ptr for shared_from_this
requirement
    static BaseClient::SharedPtr Create(boost::shared_ptr<MasterClient>
master);

protected:

    BaseClient(boost::shared_ptr<MasterClient> master);
    virtual ~BaseClient();

    boost::shared_ptr<MasterClient> master_;
};

#endif

/*
* BaseClient.cpp
*/

#include "BaseClient.h"
#include "MasterClient.h"

//-------------------------------
BaseClient::SharedPtr BaseClient::Create(boost::shared_ptr<MasterClient>
master)
{
    return BaseClient::SharedPtr(new BaseClient(master));
}

//-------------------------------
BaseClient::BaseClient(boost::shared_ptr<MasterClient> master)
    :
    master_(master)
{
    master->InsertClient(shared_from_this());
}

//-------------------------------
BaseClient::~BaseClient()
{
}

/*
* MasterClient.h
*/
#ifndef MASTERCLIENT_H
#define MASTERCLIENT_H

#include "BaseClient.h"

#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <set>

//-------------------------------
class MasterClient : public BaseClient , public
boost::enable_shared_from_this<MasterClient>
{
public:

    typedef boost::shared_ptr<MasterClient> SharedPtr;

    // Enforces that every instance must be a shared_ptr for shared_from_this
requirement
    static MasterClient::SharedPtr Create();

protected:

    typedef std::set<BaseClient::SharedPtr> Clients;
    Clients clients_;

    MasterClient();
    ~MasterClient();
};

#endif

/*
* MasterClient.cpp
*/

#include "MasterClient.h"

//-------------------------------
MasterClient::SharedPtr MasterClient::Create()
{
    return MasterClient::SharedPtr(new MasterClient());
}

//-------------------------------
MasterClient::MasterClient()
    :
    BaseClient(MasterClient::shared_from_this())
{
}

//-------------------------------
MasterClient::~MasterClient()
{
}


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net