Делегаты на C++ | страница 7



> }

> C_DELEGATE‹TRet TEMPLATE_ARGS›& operator-=(IDelegate* pDelegate) {

>  Remove(pDelegate);

>  return *this;

> }

> TRet operator()(PARAMS) {

>  return Invoke(ARGS);

> }

>private:

> void Add(IDelegate* pDelegate) {

>  if(pDelegate != NULL) m_DelegateList.push_back(pDelegate);

> }

> void Remove(IDelegate* pDelegate) {

>  DelegateList::iterator it;

>  for(it = m_DelegateList.begin(); it!= m_DelegateList.end(); ++it) {

>   if((*it)-›Compare(pDelegate)) {

>    delete (*it);

>    m_DelegateList.erase(it);

>    break;

>   }

>  }

> }

> void RemoveAll() {

>  DelegateList::iterator it;

>  for(it = m_DelegateList.begin(); it!= m_DelegateList.end(); ++it) delete (*it);

>  m_DelegateList.clear();

> }

> TRet Invoke(PARAMS) {

>  DelegateList::const_iterator it;

>  for (it = m_DelegateList.begin(); it != --m_DelegateList.end(); ++it) (*it)-›Invoke(ARGS);

>  return m_DelegateList.back()-›Invoke(ARGS);

> }

>private:

> DelegateList m_DelegateList;

>};


Вынеся обобщённый таким образом делегат в отдельный файл delegate_impl.h, мы можем сгенерировать его специализацию для любого количества параметров. Например, специализация делегата для пяти параметров получается так:

>// 5 parameters…

>#define SUFFIX 5

>#define TEMPLATE_PARAMS \

>, class TP1, class TP2, class TP3, class TP4, class TP5

>#define TEMPLATE_ARGS , TP1, TP2, TP3, TP4, TP5

>#define PARAMS TP1 p1, TP2 p2, TP3 p3, TP4 p4, TP5 p5

>#define ARGS p1, p2, p3, p4, p5


>#include "delegate_impl.h"


>#undef SUFFIX

>#undef TEMPLATE_PARAMS

>#undef TEMPLATE_ARGS

>#undef PARAMS

>#undef ARGS


Подобные фрагменты для наборов от 0 до 10 параметров можно включить в отдельный файл delegate.h, который и будут подключать пользователи делегатов.

Вот пример использования библиотеки делегатов, которую мы только что получили. Обратите внимание, что он практически полностью соответствует примеру на языке C#, с которого началась эта статья.

>#include ‹iostream›

>#include ‹fstream›

>#include ‹string›

>using namespace std;

>#include "delegate.h"


>class App {

>public:

> // Определяем делегат Callback,

> // который принимает 1 параметр и ничего не возвращает.

> typedef CDelegate1‹void, string› Callback;


> // Это метод класса App.

> void OutputToConsole(string str) { cout ‹‹ str ‹‹ endl; }


> // А это статический метод класса App.

> static void OutputToFile(string str) {

>  ofstream fout("output.txt", ios::out | ios::app);

>  fout ‹‹ str ‹‹ endl; fout.close();

> }

>};


>int main() {

> App app;


> // Создаём делегат.

> App::Callback callback = NULL;

> if (!callback.IsNull()) callback("1");