This is a simple delegate class that only works for methods of the format void ClassType::MethodType( InputType& ), but can easily be expanded to more generic functions, not shown simply because it would be too large.
class Delegate
{
public:
Delegate( void ) : Object( NULL ), Argument( NULL ) { }
virtual ~Delegate( void ) { }
template <class ClassType, class InputType, void (ClassType::*MethodType)( InputType )>
void Create( ClassType* SetObject, void* SetArgument = NULL )
{
Object = SetObject;
Argument = SetArgument;
StaticCall = &CallMethod<ClassType, InputType, MethodType>;
}
template <class InputType>
inline void operator()( InputType InputValue ) const
{
(*StaticCall)( Object, static_cast<void*>(InputValue) );
}
inline void operator()( void ) const
{
(*StaticCall)( Object, Argument );
}
protected:
typedef void (*FunctionCallType)( void*, void* );
void* Object;
void* Argument;
FunctionCallType StaticCall;
private:
template <class ClassType, class InputType, void (ClassType::*MethodType)( InputType )>
static inline void CallMethod( void* SetObject, void* PassArgument )
{
(static_cast<ClassType*>( SetObject )->*MethodType)( static_cast<InputType>(PassArgument) );
}
};
It's flexible and can be used to pool callback classes, but one problem I have with it is that so far it's on par with (or even slower when used in large vectors like I plan to) than a virtual call if it's used as a base class. I'm looking for any suggestions on how to increase performance since I'm out of ideas, even if it affects functionality.
The simplest performance measuring code I used (with -O3) was:
class VirtualBase
{
public:
virtual void TestCall( int* Data ) {}
};
class VirtualTest : public VirtualBase
{
public:
VirtualTest() : Value(0) {}
void TestCall( int* Data )
{
Value += *Data;
}
private:
int Value;
};
class DelTest : public Delegate
{
public:
DelTest() : Value(0)
{
Create<DelTest, int*, &DelTest::TestCall>( this );
}
void TestCall( int* Data )
{
Value += *Data;
}
private:
int Value;
};
int main( int argc, char **argv )
{
clock_t start;
int Value = 1;
VirtualBase* NewBase = new VirtualTest;
start = clock();
for( size_t Index = 0; Index < 1000000000; ++Index )
{
NewBase->TestCall( &Value );
}
delete NewBase;
std::cout << (( std::clock() - start ) / (double)CLOCKS_PER_SEC) << std::endl;
Delegate* NewDBase = new DelTest;
start = clock();
for( size_t Index = 0; Index < 1000000000; ++Index )
{
NewDBase->operator()( &Value );
}
delete NewDBase;
std::cout << (( std::clock() - start ) / (double)CLOCKS_PER_SEC) << std::endl;
return 0;
}
I should mention that I'd like the class to stay non-template, as it makes classes using callbacks to anything easy to iterate through in a single vector.