C_DELEGATE‹TRet TEMPLATE_ARGS›& operator=(IDelegate* pDelegate) {
RemoveAll();
Add(pDelegate);
return *this;
}
C_DELEGATE‹TRet TEMPLATE_ARGS›& operator+=(IDelegate* pDelegate) {
Add(pDelegate);
return *this;
}
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;
};
Вынеся обобщённый таким образом делегат в отдельный файл
// 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 параметров можно включить в отдельный файл
Вот пример использования библиотеки делегатов, которую мы только что получили. Обратите внимание, что он практически полностью соответствует примеру на языке 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');
// Добавляем ссылку на OutputToFile.