1、暂命名为Functor,因为没考虑返回值的情况,这在多分派委托处理中,算是个麻烦事,以后类名可能改为Delegate。
2、根据i_like_cpp翻译的技术文章《 成员函数指针与高性能的C++委托》提供的思路做成的,不过原文所提到的FastDelegate实现太复杂,所以自己做了一个,可能不完善,不过初步测试基本功能达到了,而且实现要简单一些。
3、原本vector遍历用的是迭代器,不过测试发现速度比用下标访问慢10倍以上,改成下标访问,测试表明速度已经和直接调用差不多。实际测试结果非常相近,用GetTickCount获取的结果,有时是直接调用要快一些,有时是使用Functor要快一些,当然Functor不可能比直接调用还快。
4、实现没有写完,先写了3个版本做测试用,成型以后会实现更多版本(支持更多参数)。下午一时心血来潮写成的,离成型还很远,不过从效率测试来看值得做。
#include
<
vector
>
#include < functional >
#include < iostream >
#include < string >
#include < windows.h >
using namespace std;
struct Test
{
int n;
Test () : n(3) {}
void test0()
{
//cout << "Test::test0: " << n << endl;
}
void test1(int i)
{
//cout << "Test::test1: " << i << endl;
}
void test2(const string& a, int b)
{
//cout << "Test::test2: " << a << "|" << b << endl;
}
} ;
void test0 ()
{
//cout << "test0" << endl;
}
void test1 ( int i)
{
//cout << "test1: " << i << endl;
}
void test2( const string & a, int b)
{
//cout << "test2: " << a << "|" << b << endl;
}
struct NullType {} ;
template < typename R, typename A = NullType, typename B = NullType, typename C = NullType,
typename D = NullType, typename E = NullType, typename F = NullType, typename G = NullType,
typename H = NullType, typename I = NullType, typename J = NullType, typename K = NullType,
typename L = NullType, typename M = NullType, typename N = NullType, typename O = NullType >
class Functor
{
} ;
template < typename R >
struct Functor < R >
{
vector <pair<void*, void*> > _handlers;
typedef R(*F)();
void add (F f)
{
_handlers.push_back (make_pair ((void*)0, (void*)f));
}
template <typename T>
void add (const pair<T*, typename R(T::*)()>& f)
{
typedef R(T::*P)();
struct Pointer {P p;};
Pointer ptr = {f.second};
_handlers.push_back (make_pair ((void*)f.first, *(void**)&ptr));
}
void call ()
{
for (size_t i=0; i<_handlers.size (); i++)
{
void* p = _handlers[i].first;
if (p) // member function
{
void* mem_fun = _handlers[i].second;
__asm{
mov ecx, p
call mem_fun
}
}
else
{
(*(F)_handlers[i].second)();
}
}
}
} ;
template < typename R, typename A >
struct Functor < R, A >
{
vector <pair<void*, void*> > _handlers;
typedef R(*F)(A);
void add (F f)
{
_handlers.push_back (make_pair ((void*)0, (void*)f));
}
template <typename T>
void add (const pair<T*, typename R(T::*)(A)>& f)
{
typedef R(T::*P)(A);
struct Pointer {P p;};
Pointer ptr = {f.second};
_handlers.push_back (make_pair ((void*)f.first, *(void**)&ptr));
}
void call (A a)
{
for (size_t i=0; i<_handlers.size (); i++)
{
void* p = _handlers[i].first;
if (p) // member function
{
void* mem_fun = _handlers[i].second;
__asm{
push a
mov ecx, p
call mem_fun
}
}
else
{
(*(F)_handlers[i].second)(a);
}
}
}
} ;
template < typename R, typename A, typename B >
struct Functor < R, A, B >
{
vector <pair<void*, void*> > _handlers;
typedef R(*F)(A, B);
void add (F f)
{
_handlers.push_back (make_pair ((void*)0, (void*)f));
}
template <typename T>
void add (const pair<T*, typename R(T::*)(A, B)>& f)
{
typedef R(T::*P)(A, B);
struct Pointer {P p;};
Pointer ptr = {f.second};
_handlers.push_back (make_pair ((void*)f.first, *(void**)&ptr));
}
void call (A a, B b)
{
for (size_t i=0; i<_handlers.size (); i++)
{
void* p = _handlers[i].first;
if (p) // member function
{
void* mem_fun = _handlers[i].second;
__asm{
push b
push a
mov ecx, p
call mem_fun
}
}
else
{
(*(F)_handlers[i].second)(a, b);
}
}
}
} ;
int main( int argc, char * argv[])
{
Test t;
DWORD cur = GetTickCount ();
for (int i=0; i<10000000; i++)
{
t.test0();
}
cout << (GetTickCount() - cur) << endl;
Functor <void> f;
f.add (make_pair(&t, &Test::test0));
f.add (test0);
cur = GetTickCount ();
for (int i=0; i<1000000; i++)
{
f.call();
}
cout << (GetTickCount() - cur) << endl;
f.call ();
Functor<void, int> f1;
f1.add (test1);
f1.add (make_pair (&t, &Test::test1));
f1.add (test1);
f1.add (test1);
f1.call (93);
Functor<void, const string&, int> f2;
f2.add (test2);
f2.add (make_pair (&t, &Test::test2));
f2.add (test2);
f2.add (test2);
f2.call (string("hello"), 5);
return 0;
}
#include < functional >
#include < iostream >
#include < string >
#include < windows.h >
using namespace std;
struct Test
{
int n;
Test () : n(3) {}
void test0()
{
//cout << "Test::test0: " << n << endl;
}
void test1(int i)
{
//cout << "Test::test1: " << i << endl;
}
void test2(const string& a, int b)
{
//cout << "Test::test2: " << a << "|" << b << endl;
}
} ;
void test0 ()
{
//cout << "test0" << endl;
}
void test1 ( int i)
{
//cout << "test1: " << i << endl;
}
void test2( const string & a, int b)
{
//cout << "test2: " << a << "|" << b << endl;
}
struct NullType {} ;
template < typename R, typename A = NullType, typename B = NullType, typename C = NullType,
typename D = NullType, typename E = NullType, typename F = NullType, typename G = NullType,
typename H = NullType, typename I = NullType, typename J = NullType, typename K = NullType,
typename L = NullType, typename M = NullType, typename N = NullType, typename O = NullType >
class Functor
{
} ;
template < typename R >
struct Functor < R >
{
vector <pair<void*, void*> > _handlers;
typedef R(*F)();
void add (F f)
{
_handlers.push_back (make_pair ((void*)0, (void*)f));
}
template <typename T>
void add (const pair<T*, typename R(T::*)()>& f)
{
typedef R(T::*P)();
struct Pointer {P p;};
Pointer ptr = {f.second};
_handlers.push_back (make_pair ((void*)f.first, *(void**)&ptr));
}
void call ()
{
for (size_t i=0; i<_handlers.size (); i++)
{
void* p = _handlers[i].first;
if (p) // member function
{
void* mem_fun = _handlers[i].second;
__asm{
mov ecx, p
call mem_fun
}
}
else
{
(*(F)_handlers[i].second)();
}
}
}
} ;
template < typename R, typename A >
struct Functor < R, A >
{
vector <pair<void*, void*> > _handlers;
typedef R(*F)(A);
void add (F f)
{
_handlers.push_back (make_pair ((void*)0, (void*)f));
}
template <typename T>
void add (const pair<T*, typename R(T::*)(A)>& f)
{
typedef R(T::*P)(A);
struct Pointer {P p;};
Pointer ptr = {f.second};
_handlers.push_back (make_pair ((void*)f.first, *(void**)&ptr));
}
void call (A a)
{
for (size_t i=0; i<_handlers.size (); i++)
{
void* p = _handlers[i].first;
if (p) // member function
{
void* mem_fun = _handlers[i].second;
__asm{
push a
mov ecx, p
call mem_fun
}
}
else
{
(*(F)_handlers[i].second)(a);
}
}
}
} ;
template < typename R, typename A, typename B >
struct Functor < R, A, B >
{
vector <pair<void*, void*> > _handlers;
typedef R(*F)(A, B);
void add (F f)
{
_handlers.push_back (make_pair ((void*)0, (void*)f));
}
template <typename T>
void add (const pair<T*, typename R(T::*)(A, B)>& f)
{
typedef R(T::*P)(A, B);
struct Pointer {P p;};
Pointer ptr = {f.second};
_handlers.push_back (make_pair ((void*)f.first, *(void**)&ptr));
}
void call (A a, B b)
{
for (size_t i=0; i<_handlers.size (); i++)
{
void* p = _handlers[i].first;
if (p) // member function
{
void* mem_fun = _handlers[i].second;
__asm{
push b
push a
mov ecx, p
call mem_fun
}
}
else
{
(*(F)_handlers[i].second)(a, b);
}
}
}
} ;
int main( int argc, char * argv[])
{
Test t;
DWORD cur = GetTickCount ();
for (int i=0; i<10000000; i++)
{
t.test0();
}
cout << (GetTickCount() - cur) << endl;
Functor <void> f;
f.add (make_pair(&t, &Test::test0));
f.add (test0);
cur = GetTickCount ();
for (int i=0; i<1000000; i++)
{
f.call();
}
cout << (GetTickCount() - cur) << endl;
f.call ();
Functor<void, int> f1;
f1.add (test1);
f1.add (make_pair (&t, &Test::test1));
f1.add (test1);
f1.add (test1);
f1.call (93);
Functor<void, const string&, int> f2;
f2.add (test2);
f2.add (make_pair (&t, &Test::test2));
f2.add (test2);
f2.add (test2);
f2.call (string("hello"), 5);
return 0;
}