Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>It is unfortunate that you work for a company which advocates reinventing wheels and using bronze age C++. However, given the circumstances and the code you posted, there is a fairly simple solution without making too many changes. I've had to do similar things before not because of company policy but because we were developing a software development kit and we did not want to require that users of the SDK have a specific version of boost installed.</p> <p>BTW, I believe what you are really after is a signals and slots mechanism: I suggest studying it if you want to make this design a bit more conforming to well-established solutions.</p> <p>I took a few liberal assumptions: the primary one being that Data does not have to be stored in the callback and can instead be passed by the sender. This should be a more flexible design. It is still very simple - you can take this a lot further (ex: variable-number of arguments and custom return types, a signal class, deferred notifications, etc).</p> <pre><code>template&lt;typename Data&gt; class CallbackInterface { public: virtual ~CallbackInterface() {} virtual void run(const Data&amp; data) = 0; virtual CallbackInterface* clone() const = 0; }; template&lt;typename Object, typename Data&gt; class CallbackMethod: public CallbackInterface&lt;Data&gt; { public: typedef void (Object::*PHandler)(const Data&amp;); CallbackMethod(Object* obj, PHandler handler) : pObj(obj), pHandler(handler) {} virtual void run(const Data&amp; data) { (pObj-&gt;*pHandler)(data); } virtual CallbackInterface* clone() const {return new CallbackMethod(*this); } protected: Object* pObj; PHandler pHandler; }; template &lt;class Data&gt; class Callback { public: template &lt;class Object&gt; Callback(Object* obj, void (Object::*method)(const Data&amp;) ): cb(new CallbackMethod&lt;Object, Data&gt;(obj, method)) { } Callback(const Callback&amp; other): cb(other.cb-&gt;clone() ) { } Callback&amp; operator=(const Callback&amp; other) { delete cb; cb = other.cb-&gt;clone(); return *this; } ~Callback() { delete cb; } void operator()(const Data&amp; data) const { cb-&gt;run(data); } private: CallbackInterface&lt;Data&gt;* cb; }; </code></pre> <p>Example usage:</p> <pre><code>struct Foo { void f(const int&amp; x) { cout &lt;&lt; "Foo: " &lt;&lt; x &lt;&lt; endl; } }; struct Bar { void f(const int&amp; x) { cout &lt;&lt; "Bar: " &lt;&lt; x &lt;&lt; endl; } }; int main() { Foo f; Callback&lt;int&gt; cb(&amp;f, &amp;Foo::f); cb(123); // outputs Foo: 123 Bar b; cb = Callback&lt;int&gt;(&amp;b, &amp;Bar::f); cb(456); // outputs Bar: 456 } </code></pre> <p>As you can see, the Callback object itself does not require the object type to be passed in as a template argument, thereby allowing it to point to methods of any type provided that the method conforms to the signature: void some_class::some_method(const Data&amp;). Store a list of these Callback objects in a class capable of calling all of them and you have yourself a signal with connected slots.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload