Click here to Skip to main content
15,884,537 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I found a delegate code what implemented in C++, and it compiled under vs2017 and runs properly.

#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.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.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).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)
			{
				//do something...
			}
		}
	}

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);

	return 0;
}


But I use G++(version 7.4+) in MSYS2 or Ubuntu 18.0.4, I got compiling errors.

What I have tried:

Is anyone who knows problemes are? I'm confuse now. Who can point me out how to fix problems?
Posted
Updated 1-Jan-19 16:13pm
Comments
Richard MacCutchan 28-Dec-18 4:54am    
What errors?
jackyxinli 28-Dec-18 19:43pm    
$ g++ -Wall -std=c++11 -o delegate delegate.cpp
delegate.cpp: In lambda function:
delegate.cpp:77:26: error: expected primary-expression before '(' token
auto _fun = f.target<R(*)(Args...)>();
^
delegate.cpp:77:28: error: expected primary-expression before ')' token
auto _fun = f.target<R(*)(Args...)>();
^
delegate.cpp:77:34: error: expected primary-expression before '...' token
auto _fun = f.target<R(*)(Args...)>();
^~~
delegate.cpp:77:40: error: expected primary-expression before ')' token
auto _fun = f.target<R(*)(Args...)>();
^
delegate.cpp: In lambda function:
delegate.cpp:97:57: error: expected primary-expression before '>' token
auto _fun = f.target<delegate_class_mem<C, R, Args...>>();
^~
delegate.cpp:97:60: error: expected primary-expression before ')' token
auto _fun = f.target<delegate_class_mem<C, R, Args...>>();
^
delegate.cpp: In member function 'delegate<R(Args ...)>::this_type& delegate<R(Args ...)>::operator+=(delegate<R(Args ...)>::func_type)':
delegate.cpp:117:31: error: expected primary-expression before '(' token
auto _func = (*it).target<R(*)(Args...)>();
^
delegate.cpp:117:33: error: expected primary-expression before ')' token
auto _func = (*it).target<R(*)(Args...)>();
^
delegate.cpp:117:39: error: expected primary-expression before '...' token
auto _func = (*it).target<R(*)(Args...)>();
^~~
delegate.cpp:117:45: error: expected primary-expression before ')' token
auto _func = (*it).target<R(*)(Args...)>();
^
[no name] 28-Dec-18 5:22am    
jackyxinli 28-Dec-18 20:43pm    
I tried command like blow:
g++ -Wall -std=c++11 -o delegate delegate.cpp

or
g++ -Wall -std=c++0x -o delegate delegate.cpp

do not work

C++
#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)
			{
				//do something...
			}
		}
	}

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.
 
Share this answer
 
Comments
k5054 2-Jan-19 10:02am    
There's a detailed explanation of this here:
https://stackoverflow.com/questions/610245/where-and-why-do-i-have-to-put-the-template-and-typename-keywords/17579889#17579889

See the following comment also, which also explains the use of the template keyword in this situation
jackyxinli 2-Jan-19 19:30pm    
Thank you first, I also find defination of function in boost library. May I ask you about this syntax where can I find in C++ specification?
k5054 3-Jan-19 12:26pm    
My knowledge of templates doesn't extend far beyond being able to spell it correctly!

I, too, was interested in the reasons for that syntax and did some googling about to see what I could find. The above mentioned SO article seemed to explain it. If you scroll back from that there's a very long response that quotes the standard.

If you're really interested in what the standard says see http://eel.is/c++draft/temp#names-5 (more google-fu)

jackyxinli 6-Jan-19 22:33pm    
Thanks a lot. I find an article also in stackoverflow[https://stackoverflow.com/questions/12676190/how-to-call-a-template-member-function]

YES, template is more complicated than normal syntax in C++, so obscurity.
I use compile command like blow:
g++ -Wall -std=c++11 -o delegate delegate.cpp

or
g++ -Wall -std=c++0x -o delegate delegate.cpp

do not work
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900