In follow up to my article on Fast Delegates back in June, I used the C++ STL (Standard Template Library) to create a simple, one parameter Multicast Delegate for C++. The code provided here provides a mechanism for creating a Multicast Delegate by incorporating the FastDelegate library. I used the 'vector' template from the STL to implement dynamically adding and removing object method calls to the Delegate.
#pragma once
#include <vector>
#include "FastDelegate.h"
// http://www.codeproject.com/cpp/FastDelegate.asp
template<class RO> class Delegate {
// RO: Return Object in call
public:
typedef FastDelegate1<RO> OnMessageHandler;
void Add( OnMessageHandler function );
void Remove( OnMessageHandler function );
bool IsEmpty();
void operator()( RO );
protected:
private:
std::vector<OnMessageHandler> rOnFD;
};
template<class RO> void Delegate<RO>::Add(
OnMessageHandler function ) {
rOnFD.push_back( function );
}
template<class RO> void Delegate<RO>::Remove(
OnMessageHandler function ) {
std::vector<OnMessageHandler>::iterator rOnFD_Iter;
rOnFD_Iter = rOnFD.begin();
while ( rOnFD.end() != rOnFD_Iter ) {
if ( function == *rOnFD_Iter ) {
rOnFD_Iter.erase( rOnFD_Iter );
break;
}
rOnFD_Iter++;
}
}
template<class RO> bool Delegate<RO>::IsEmpty() {
return rOnFD.empty();
}
template<class RO> void Delegate<RO>::operator()( RO ro ) {
std::vector<OnMessageHandler>::iterator rOnFD_Iter;
rOnFD_Iter = rOnFD.begin();
while ( rOnFD.end() != rOnFD_Iter ) {
(*rOnFD_Iter)( ro );
rOnFD_Iter++;
}
}
// =======
// Here is a declaration of three events, with each event receiving a
// pointer to a object with class of CIQFSymbol:
Delegate<CIQFSymbol*> OnFundamentalMessage, OnUpdateMessage, OnSummaryMessage;
// Here is how to add a delegate to the MultiCast Delegate:
pSym->OnFundamentalMessage.Add(
MakeDelegate( this, &CGTScalpDlg::EmitDataFundamental ) );
// EmitDataFundamental is declared with:
void EmitDataFundamental( CIQFSymbol *pSym );
// The mulicast delegate can then be invoked with:
OnFundamentalMessage( this );
// =======
Caveats: I havn't proven that Delegate's Remove method works as intended yet, but theoretically it should, as
coded. Proper initialization, deconstruction cleanup, and thread safety are left as exercises for the reader.