#include<algorithm>
#include<functional>
#include<iostream>
#include<list>
#include<string>
using namespace std;
#ifdef _DEBUG
#define OUTPUT(info) cout<<info <<endl<<endl;
#else
#define OUTPUT(info)
#endif
template<class C, typename R, typename ...Args>
class delegate_class_mem
{
public:
typedef R(C::*class_func_type)(Args...);
delegate_class_mem(class_func_type fun, C* class_ptr)
: _fun(fun), _class_ptr(class_ptr) {}
R operator()(Args&&...args)
{
return (_class_ptr->*_fun)(args...);
}
bool operator==(const delegate_class_mem<C, R, Args...>&other) const
{
if (_class_ptr == other._class_ptr && _fun == other._fun)
return true;
return false;
}
template<typename T>
bool operator==(const T&&)const
{
return false;
}
private:
C* _class_ptr;
class_func_type _fun;
};
template<typename ...T>
class delegate { };
template<typename R, typename ...Args>
class delegate<R(Args...)>
{
public:
typedef std::function<R(Args...)> delegate_func;
typedef std::list<delegate_func> function_list;
typedef R(*func_type)(Args...);
typedef delegate<R(Args...)> this_type;
delegate()
{
OUTPUT("function type:" << typeid(R(Args...)).name())
OUTPUT("args count:" << sizeof...(Args))
}
~delegate()
{
func_list.clear();
}
this_type& operator-=(func_type func)
{
auto itr = std::find_if(func_list.begin(), func_list.end(),
[&](delegate_func& f)->bool
{
auto _fun = f.template target<R(*)(Args...)>();
if (_fun && *_fun == func)
{
return true;
}
return false;
});
if (itr != func_list.end())
func_list.erase(itr);
return *this;
}
template<class C>
this_type& operator-=(delegate_class_mem<C, R, Args...>&& class_mem_h)
{
auto itr = std::find_if(func_list.begin(), func_list.end(),
[&](delegate_func& f)->bool
{
auto _fun = f.template target<delegate_class_mem<C, R, Args...>>();
if (_fun && *_fun == class_mem_h)
{
return true;
}
return false;
});
if (itr != func_list.end())
func_list.erase(itr);
return *this;
}
this_type& operator+=(func_type func)
{
bool exist = false;
for (auto it = func_list.begin(); it != func_list.end(); it++)
{
auto _func = (*it).template target<R(*)(Args...)>();
if (_func && *_func == func)
{
exist = true;
break;
}
}
if (!exist)
func_list.push_back(func);
return *this;
}
template<class C>
this_type& operator+=(delegate_class_mem<C, R, Args...>&& class_mem)
{
func_list.push_back(class_mem);
return *this;
}
void operator()(Args&& ...args)
{
for (auto it = func_list.begin(); it != func_list.end(); it++)
{
try
{
(*it)(args...);
}
catch (exception ex)
{
}
}
}
private:
function_list func_list;
};
template<typename C, typename R, typename ...Args>
auto makeDelegateClassHelper(R(C::*class_func_type)(Args...), C* class_ptr) ->delegate_class_mem<C, R, Args...>
{
return delegate_class_mem<C, R, Args...>(class_func_type, class_ptr);
}
void func1(std::string& str)
{
std::cout << "func1: " << str << endl;
}
void func2(std::string& str)
{
std::cout << "func2: " << str << endl;
}
int main(int argc, char *argv[])
{
std::string str("This is jacky_zz");
delegate<void(std::string&)> _delegate;
printf("func1: %p\n", func1);
printf("func2: %p\n", func2);
_delegate += func1;
_delegate += func1;
_delegate += func2;
_delegate += func2;
_delegate(str);
auto f = [](std::string& str) { std::cout << str << std::endl; };
f(str);
return 0;
}
I got no errors when I add 'template' before target of function. VS2017 & G++(7.4+) are all OK.