Callbacks in C++


factor template

//----------------------------------------
// l i b r a r y c o d e 
//----------------------------------------
#include <string.h> //for memcpy, memcmp
class CallbackData
{
public:
  typedef void (CallbackData::*PMEMFUNC)();
  CallbackData(const void* pClient_, const void* ppMemfunc_):
    _pClient(pClient_)
  {memcpy(_ppMemfunc,ppMemfunc_,sizeof(PMEMFUNC));}

  const void* pClient() const {return _pClient;}
  const void* ppMemfunc() const {return _ppMemfunc;}

private:
  char _ppMemfunc[sizeof(PMEMFUNC)];
  const void* _pClient;
};
//----------------------------------------
template <class P1>
class Callback1Base
{
public:
  virtual void operator()(P1) const = 0;
  virtual Callback1Base<P1>* clone() const = 0;

protected:
  Callback1Base(const void* pClient_, const void* ppMemfunc_):
    _data(pClient_,ppMemfunc_)
  {} 

  const CallbackData& data() const {return _data;}

private:
  CallbackData _data;
};
//----------------------------------------
template <class P1, class Client, class PMemfunc>
class Callback1:
  public Callback1Base<P1>
{
public:
  Callback1(Client& client_, PMemfunc pMemfunc_):
  Callback1Base<P1>(&client_,&pMemfunc_)
  {}

  /*virtual*/ void operator()(P1 parm_) const
  {
    Client* pClient = (Client*) data().pClient();
    PMemfunc& pMemfunc = (*(PMemfunc*)(data().ppMemfunc()));
    (pClient->*pMemfunc)(parm_);
  }

  /*virtual*/ Callback1<P1,Client,PMemfunc>* clone() const 
  {return new Callback1<P1,Client,PMemfunc>(*this);}
};
//----------------------------------------
template <class P1, class Client, class TRT, class CallType, class TP1>
inline Callback1<P1,Client,TRT(CallType::*)(TP1)>*
make_callback(Callback1Base<P1>*,
              Client& client_,
              TRT (CallType::* const& memFunc_)(TP1))
{
  typedef TRT (CallType::*PMEMFUNC)(TP1);
  return new Callback1<P1,Client,PMEMFUNC>(client_, memFunc_);
}
//----------------------------------------
template <class P1, class Client, class TRT, class CallType, class TP1>
inline Callback1<P1,Client,TRT(CallType::*)(TP1)const>*
make_callback(Callback1Base<P1>*,
              Client& client_,
              TRT (CallType::* const& memFunc_)(TP1) const)
{
  typedef TRT (CallType::*PMEMFUNC)(TP1) const;
  return new Callback1<P1,Callee,PMEMFUNC>(client_, memFunc_);
}
//----------------------------------------
class Button
{
public:
  Button(Callback1Base<Button*>& callback_):
    _pCallback(callback_.clone()){}

  ~Button() {delete _pCallback;}
  void push() {(*_pCallback)(this);}

private:
  Callback1Base<Button*>* _pCallback;
};
//----------------------------------------
// c l i e n t c o d e
//----------------------------------------
#include <iostream.h>
class CdPlayer
{
public:
  void playButtonPushed(Button*) {cout << "PLAY" << endl;}
  void stopButtonPushed(Button*) {cout << "STOP" << endl;}
};
//----------------------------------------
main()
{
  CdPlayer aCdPlayer;
  Callback1Base<Button*>* pPlayCallback = 
    make_callback
    ((Callback1Base<Button*>*)0, aCdPlayer, &CdPlayer::playButtonPushed);

  Callback1Base<Button*>* pStopCallback = 
    make_callback
    ((Callback1Base<Button*>*)0, aCdPlayer, &CdPlayer::stopButtonPushed);

  Button playButton(*pPlayCallback);
  delete pPlayCallback;

  Button stopButton(*pStopCallback);
  delete pStopCallback;

  playButton.push();
  stopButton.push();

  return 0;
};

[View/Add Comments]


Callbacks in C++
Copyright © 1996-2000 Paul Jakubik
Created: 26 July 1996. Last update: 26 November 2000.
pauljakubik@yahoo.com