1

I have base class A which has factory method to create instances of derived classes B and C. B and C has start() overridden. There is do_work() which calls getInstance() and then calls start(). Now labmda inside spawn() does not store the instance of captures this pointer. So there is a scope problem. If I pass instance(boost::shared_ptr) to start explicitly and then capture it in lambda, then it works. How do I avoid passing instance to start()?

    class B : public A {
      public:
        void start(){
            boost::spawn(io_service, [this](boost::asio::yield_context yield) 
          {  
             // work
            });
         }

    }
    class C: public A {
         public: 
         void start(){
            boost::spawn(io_service, [this](boost::asio::yield_context yield) 
          {  
             // work
            });
         }
    }
    do_work() {
       auto object = A::getInstance(); // this returns boost::shared_ptr and it does not store that instance
       object->start();

    }

  class A {
  public:
      virtual void start () =0;  
      static boost::shared_ptr<A> getInstance() {
       return boost::shared_ptr<A>(new B());
     }

   }
debonair
  • 2,505
  • 4
  • 33
  • 73
  • didn't try to compile it but it can't compile: you don't close the `boost::spawn` with `)` in `class C`, post code that we can compile – David Haim Oct 04 '18 at 19:09
  • Can we see your definition of `class A`? – Kenneth Davis Oct 04 '18 at 19:10
  • 1
    Maybe you can use [enable_shared_from_this](https://stackoverflow.com/questions/712279/what-is-the-usefulness-of-enable-shared-from-this) – D Drmmr Oct 04 '18 at 19:16
  • @DavidHai please check update question – debonair Oct 04 '18 at 19:58
  • 1
    It took me a while to figure out what the question was, due to all the problems with your "code". Hint: make it a [SSCCE](http://sscce.org), so you don't cause so much confusion. – sehe Oct 04 '18 at 23:34

2 Answers2

3

You should use enable_shared_from_this:

Live On Coliru

#define BOOST_COROUTINES_NO_DEPRECATION_WARNING
#include <boost/enable_shared_from_this.hpp>
#include <boost/asio.hpp>
#include <boost/asio/spawn.hpp>

boost::asio::io_service io_service;

class A : public boost::enable_shared_from_this<A> {
  public:
    virtual void start() = 0;
    static boost::shared_ptr<A> getInstance();
};

class B : public A {
  public:
    void start() {
        auto self = shared_from_this();
        boost::asio::spawn(io_service, [self](boost::asio::yield_context /*yield*/) {
            // work
        });
    }

};

class C : public A {
  public:
    void start() {
        auto self = shared_from_this();
        boost::asio::spawn(io_service, [self](boost::asio::yield_context /*yield*/) {
            // work
        });
    }
};

/*static*/ boost::shared_ptr<A> A::getInstance() { return boost::shared_ptr<A>(new B()); }

void do_work() {
    auto object = A::getInstance(); // this returns boost::shared_ptr and it does not store that instance
    object->start();
}

int main() {
}
sehe
  • 374,641
  • 47
  • 450
  • 633
0

Honestly, I don't know why the compiler let this pass. The start function doesn't exist in the A world.

Classes B and C haven't overridden anything unless there is a virtual function in their base class to override. Add a pure virtual start to class A, then decorate the B and C start functions with virtual. Then will those two classes have overridden something. I suspect that will result in the behavior you're expecting.

class A {
public:
  static boost::shared_ptr<A> getInstance() {
    return boost::shared_ptr<A>(new B());
  }
  virtual void start()=0;
};
class B : public A {
public:
  virtual void start() {
    // stuff specific to class B
  }
};
class C : public A {
public:
  virtual void start() {
    // stuff specific to class C
  }
};
  • Can anybody elaborate as to why this has been down voted? It is neither low quality nor unuseful. I now understand that this doesn't answer his question, but the OP edited his question to include this suggestion _after_ I posted it. Seems to me that meets the definition of "useful". Not whining, just looking for clarification. – Kenneth Davis Oct 05 '18 at 13:41