Click here to Skip to main content
15,896,259 members
Articles / Programming Languages / C++

A Minimalistic Signals and Slots Implementation

Rate me:
Please Sign up or sign in to vote.
4.60/5 (5 votes)
8 Aug 20068 min read 27.7K   349   24  
A lightweight and typesafe templated signals and slots implementation.
#pragma once
#include "invokable.h"
#include "trackable.h"

namespace semaphore {
	namespace internal {

template<class R, class T, class A1 = nil, class A2 = nil, class A3 = nil, class A4 = nil, class A5  = nil,
						   class A6 = nil, class A7 = nil, class A8 = nil, class A9 = nil, class A10 = nil>
class smart_member_function : public invokable<R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>
{
protected:
	typedef R (T::*function)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10);

public:
	virtual type gettype() const { return SmartMemberFunction; }

	smart_member_function(smart_member_function& rhs)  : invokable(), instance(rhs.instance), watch(rhs.instance->connect), ptr(rhs.ptr)
	{
		watch->ref();
	}

	smart_member_function(trackable* inst, function p) : invokable(), instance(dynamic_cast<T*>(inst)), watch(inst->connect()), ptr(p)
	{
		watch->ref();
	}

	virtual ~smart_member_function()
	{
		free();
	}

	virtual R operator()(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) const
	{
		if(watch->valid())
			return (instance->*ptr)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
	}

	virtual bool compare(const invokable* rhs) const
	{
		if(gettype() == rhs->gettype())
			return *this == *dynamic_cast<const smart_member_function<R, T, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>*>(rhs);
		return false;
	}

	bool operator==(const smart_member_function& rhs) const
	{
		return instance == rhs.instance && ptr == rhs.ptr;
	}

private:
	void free()
	{
		if(watch->deref())
			delete watch;
	}

	trackable::watcher* watch;
	T* instance;
	function ptr;
};

//////////////////////////////////////////////////////////////////////////////////////

template<class R, class T, class A1, class A2, class A3, class A4, class A5,
						   class A6, class A7, class A8, class A9>
class smart_member_function<R, T, A1, A2, A3, A4, A5, A6, A7, A8, A9> : public invokable<R, A1, A2, A3, A4, A5, A6, A7, A8, A9>
{
protected:
	typedef R (T::*function)(A1, A2, A3, A4, A5, A6, A7, A8, A9);

public:
	virtual type gettype() const { return SmartMemberFunction; }

	smart_member_function(smart_member_function& rhs)  : invokable(), instance(rhs.instance), watch(rhs.instance->connect), ptr(rhs.ptr)
	{
		watch->ref();
	}

	smart_member_function(trackable* inst, function p) : invokable(), instance(dynamic_cast<T*>(inst)), watch(inst->connect()), ptr(p)
	{
		watch->ref();
	}

	virtual ~smart_member_function()
	{
		free();
	}

	virtual R operator()(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) const
	{
		if(watch->valid())
			return (instance->*ptr)(a1, a2, a3, a4, a5, a6, a7, a8, a9);
	}

	virtual bool compare(const invokable* rhs) const
	{
		if(gettype() == rhs->gettype())
			return *this == *dynamic_cast<const smart_member_function<R, T, A1, A2, A3, A4, A5, A6, A7, A8, A9>*>(rhs);
		return false;
	}

	bool operator==(const smart_member_function& rhs) const
	{
		return instance == rhs.instance && ptr == rhs.ptr;
	}

private:
	void free()
	{
		if(watch->deref())
			delete watch;
	}

	trackable::watcher* watch;
	T* instance;
	function ptr;
};

//////////////////////////////////////////////////////////////////////////////////////

template<class R, class T, class A1, class A2, class A3, class A4, class A5,
						   class A6, class A7, class A8>
class smart_member_function<R, T, A1, A2, A3, A4, A5, A6, A7, A8> : public invokable<R, A1, A2, A3, A4, A5, A6, A7, A8>
{
protected:
	typedef R (T::*function)(A1, A2, A3, A4, A5, A6, A7, A8);

public:
	virtual type gettype() const { return SmartMemberFunction; }

	smart_member_function(smart_member_function& rhs)  : invokable(), instance(rhs.instance), watch(rhs.instance->connect), ptr(rhs.ptr)
	{
		watch->ref();
	}

	smart_member_function(trackable* inst, function p) : invokable(), instance(dynamic_cast<T*>(inst)), watch(inst->connect()), ptr(p)
	{
		watch->ref();
	}

	virtual ~smart_member_function()
	{
		free();
	}

	virtual R operator()(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) const
	{
		if(watch->valid())
			return (instance->*ptr)(a1, a2, a3, a4, a5, a6, a7, a8);
	}

	virtual bool compare(const invokable* rhs) const
	{
		if(gettype() == rhs->gettype())
			return *this == *dynamic_cast<const smart_member_function<R, T, A1, A2, A3, A4, A5, A6, A7, A8>*>(rhs);
		return false;
	}

	bool operator==(const smart_member_function& rhs) const
	{
		return instance == rhs.instance && ptr == rhs.ptr;
	}

private:
	void free()
	{
		if(watch->deref())
			delete watch;
	}

	trackable::watcher* watch;
	T* instance;
	function ptr;
};

//////////////////////////////////////////////////////////////////////////////////////

template<class R, class T, class A1, class A2, class A3, class A4, class A5,
						   class A6, class A7>
class smart_member_function<R, T, A1, A2, A3, A4, A5, A6, A7> : public invokable<R, A1, A2, A3, A4, A5, A6, A7>
{
protected:
	typedef R (T::*function)(A1, A2, A3, A4, A5, A6, A7);

public:
	virtual type gettype() const { return SmartMemberFunction; }

	smart_member_function(smart_member_function& rhs)  : invokable(), instance(rhs.instance), watch(rhs.instance->connect), ptr(rhs.ptr)
	{
		watch->ref();
	}

	smart_member_function(trackable* inst, function p) : invokable(), instance(dynamic_cast<T*>(inst)), watch(inst->connect()), ptr(p)
	{
		watch->ref();
	}

	virtual ~smart_member_function()
	{
		free();
	}

	virtual R operator()(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) const
	{
		if(watch->valid())
			return (instance->*ptr)(a1, a2, a3, a4, a5, a6, a7);
	}

	virtual bool compare(const invokable* rhs) const
	{
		if(gettype() == rhs->gettype())
			return *this == *dynamic_cast<const smart_member_function<R, T, A1, A2, A3, A4, A5, A6, A7>*>(rhs);
		return false;
	}

	bool operator==(const smart_member_function& rhs) const
	{
		return instance == rhs.instance && ptr == rhs.ptr;
	}

private:
	void free()
	{
		if(watch->deref())
			delete watch;
	}

	trackable::watcher* watch;
	T* instance;
	function ptr;
};

//////////////////////////////////////////////////////////////////////////////////////

template<class R, class T, class A1, class A2, class A3, class A4, class A5,
						   class A6>
class smart_member_function<R, T, A1, A2, A3, A4, A5, A6> : public invokable<R, A1, A2, A3, A4, A5, A6>
{
protected:
	typedef R (T::*function)(A1, A2, A3, A4, A5, A6);

public:
	virtual type gettype() const { return SmartMemberFunction; }

	smart_member_function(smart_member_function& rhs)  : invokable(), instance(rhs.instance), watch(rhs.instance->connect), ptr(rhs.ptr)
	{
		watch->ref();
	}

	smart_member_function(trackable* inst, function p) : invokable(), instance(dynamic_cast<T*>(inst)), watch(inst->connect()), ptr(p)
	{
		watch->ref();
	}

	virtual ~smart_member_function()
	{
		free();
	}

	virtual R operator()(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) const
	{
		if(watch->valid())
			return (instance->*ptr)(a1, a2, a3, a4, a5, a6);
	}

	virtual bool compare(const invokable* rhs) const
	{
		if(gettype() == rhs->gettype())
			return *this == *dynamic_cast<const smart_member_function<R, T, A1, A2, A3, A4, A5, A6>*>(rhs);
		return false;
	}

	bool operator==(const smart_member_function& rhs) const
	{
		return instance == rhs.instance && ptr == rhs.ptr;
	}

private:
	void free()
	{
		if(watch->deref())
			delete watch;
	}

	trackable::watcher* watch;
	T* instance;
	function ptr;
};

//////////////////////////////////////////////////////////////////////////////////////

template<class R, class T, class A1, class A2, class A3, class A4, class A5>
class smart_member_function<R, T, A1, A2, A3, A4, A5> : public invokable<R, A1, A2, A3, A4, A5>
{
protected:
	typedef R (T::*function)(A1, A2, A3, A4, A5);

public:
	virtual type gettype() const { return SmartMemberFunction; }

	smart_member_function(smart_member_function& rhs)  : invokable(), instance(rhs.instance), watch(rhs.instance->connect), ptr(rhs.ptr)
	{
		watch->ref();
	}

	smart_member_function(trackable* inst, function p) : invokable(), instance(dynamic_cast<T*>(inst)), watch(inst->connect()), ptr(p)
	{
		watch->ref();
	}

	virtual ~smart_member_function()
	{
		free();
	}

	virtual R operator()(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) const
	{
		if(watch->valid())
			return (instance->*ptr)(a1, a2, a3, a4, a5);
	}

	virtual bool compare(const invokable* rhs) const
	{
		if(gettype() == rhs->gettype())
			return *this == *dynamic_cast<const smart_member_function<R, T, A1, A2, A3, A4, A5>*>(rhs);
		return false;
	}

	bool operator==(const smart_member_function& rhs) const
	{
		return instance == rhs.instance && ptr == rhs.ptr;
	}

private:
	void free()
	{
		if(watch->deref())
			delete watch;
	}

	trackable::watcher* watch;
	T* instance;
	function ptr;
};

//////////////////////////////////////////////////////////////////////////////////////

template<class R, class T, class A1, class A2, class A3, class A4>
class smart_member_function<R, T, A1, A2, A3, A4> : public invokable<R, A1, A2, A3, A4>
{
protected:
	typedef R (T::*function)(A1, A2, A3, A4);

public:
	virtual type gettype() const { return SmartMemberFunction; }

	smart_member_function(smart_member_function& rhs)  : invokable(), instance(rhs.instance), watch(rhs.instance->connect), ptr(rhs.ptr)
	{
		watch->ref();
	}

	smart_member_function(trackable* inst, function p) : invokable(), instance(dynamic_cast<T*>(inst)), watch(inst->connect()), ptr(p)
	{
		watch->ref();
	}

	virtual ~smart_member_function()
	{
		free();
	}

	virtual R operator()(A1 a1, A2 a2, A3 a3, A4 a4) const
	{
		if(watch->valid())
			return (instance->*ptr)(a1, a2, a3, a4);
	}

	virtual bool compare(const invokable* rhs) const
	{
		if(gettype() == rhs->gettype())
			return *this == *dynamic_cast<const smart_member_function<R, T, A1, A2, A3, A4>*>(rhs);
		return false;
	}

	bool operator==(const smart_member_function& rhs) const
	{
		return instance == rhs.instance && ptr == rhs.ptr;
	}

private:
	void free()
	{
		if(watch->deref())
			delete watch;
	}

	trackable::watcher* watch;
	T* instance;
	function ptr;
};

//////////////////////////////////////////////////////////////////////////////////////

template<class R, class T, class A1, class A2, class A3>
class smart_member_function<R, T, A1, A2, A3> : public invokable<R, A1, A2, A3>
{
protected:
	typedef R (T::*function)(A1, A2, A3);

public:
	virtual type gettype() const { return SmartMemberFunction; }

	smart_member_function(smart_member_function& rhs)  : invokable(), instance(rhs.instance), watch(rhs.instance->connect), ptr(rhs.ptr)
	{
		watch->ref();
	}

	smart_member_function(trackable* inst, function p) : invokable(), instance(dynamic_cast<T*>(inst)), watch(inst->connect()), ptr(p)
	{
		watch->ref();
	}

	virtual ~smart_member_function()
	{
		free();
	}

	virtual R operator()(A1 a1, A2 a2, A3 a3) const
	{
		if(watch->valid())
			return (instance->*ptr)(a1, a2, a3);
	}

	virtual bool compare(const invokable* rhs) const
	{
		if(gettype() == rhs->gettype())
			return *this == *dynamic_cast<const smart_member_function<R, T, A1, A2, A3>*>(rhs);
		return false;
	}

	bool operator==(const smart_member_function& rhs) const
	{
		return instance == rhs.instance && ptr == rhs.ptr;
	}

private:
	void free()
	{
		if(watch->deref())
			delete watch;
	}

	trackable::watcher* watch;
	T* instance;
	function ptr;
};

//////////////////////////////////////////////////////////////////////////////////////

template<class R, class T, class A1, class A2>
class smart_member_function<R, T, A1, A2> : public invokable<R, A1, A2>
{
protected:
	typedef R (T::*function)(A1, A2);

public:
	virtual type gettype() const { return SmartMemberFunction; }

	smart_member_function(smart_member_function& rhs)  : invokable(), instance(rhs.instance), watch(rhs.instance->connect), ptr(rhs.ptr)
	{
		watch->ref();
	}

	smart_member_function(trackable* inst, function p) : invokable(), instance(dynamic_cast<T*>(inst)), watch(inst->connect()), ptr(p)
	{
		watch->ref();
	}

	virtual ~smart_member_function()
	{
		free();
	}

	virtual R operator()(A1 a1, A2 a2) const
	{
		if(watch->valid())
			return (instance->*ptr)(a1, a2);
	}

	virtual bool compare(const invokable* rhs) const
	{
		if(gettype() == rhs->gettype())
			return *this == *dynamic_cast<const smart_member_function<R, T, A1, A2>*>(rhs);
		return false;
	}

	bool operator==(const smart_member_function& rhs) const
	{
		return instance == rhs.instance && ptr == rhs.ptr;
	}

private:
	void free()
	{
		if(watch->deref())
			delete watch;
	}

	trackable::watcher* watch;
	T* instance;
	function ptr;
};

//////////////////////////////////////////////////////////////////////////////////////

template<class R, class T, class A1>
class smart_member_function<R, T, A1> : public invokable<R, A1>
{
protected:
	typedef R (T::*function)(A1);

public:
	virtual type gettype() const { return SmartMemberFunction; }

	smart_member_function(smart_member_function& rhs)  : invokable(), instance(rhs.instance), watch(rhs.instance->connect), ptr(rhs.ptr)
	{
		watch->ref();
	}

	smart_member_function(trackable* inst, function p) : invokable(), instance(dynamic_cast<T*>(inst)), watch(inst->connect()), ptr(p)
	{
		watch->ref();
	}

	virtual ~smart_member_function()
	{
		free();
	}

	virtual R operator()(A1 a1) const
	{
		if(watch->valid())
			return (instance->*ptr)(a1);
	}

	virtual bool compare(const invokable* rhs) const
	{
		if(gettype() == rhs->gettype())
			return *this == *dynamic_cast<const smart_member_function<R, T, A1>*>(rhs);
		return false;
	}

	bool operator==(const smart_member_function& rhs) const
	{
		return instance == rhs.instance && ptr == rhs.ptr;
	}

private:
	void free()
	{
		if(watch->deref())
			delete watch;
	}

	trackable::watcher* watch;
	T* instance;
	function ptr;
};

//////////////////////////////////////////////////////////////////////////////////////

template<class R, class T>
class smart_member_function<R, T> : public invokable<R>
{
protected:
	typedef R (T::*function)();

public:
	virtual type gettype() const { return SmartMemberFunction; }

	smart_member_function(smart_member_function& rhs)  : invokable(), instance(rhs.instance), watch(rhs.instance->connect), ptr(rhs.ptr)
	{
		watch->ref();
	}

	smart_member_function(trackable* inst, function p) : invokable(), instance(dynamic_cast<T*>(inst)), watch(inst->connect()), ptr(p)
	{
		watch->ref();
	}

	virtual ~smart_member_function()
	{
		free();
	}

	virtual R operator()() const
	{
		if(watch->valid())
			return (instance->*ptr)();
	}

	virtual bool compare(const invokable* rhs) const
	{
		if(gettype() == rhs->gettype())
			return *this == *dynamic_cast<const smart_member_function<R, T>*>(rhs);
		return false;
	}

	bool operator==(const smart_member_function& rhs) const
	{
		return instance == rhs.instance && ptr == rhs.ptr;
	}

private:
	void free()
	{
		if(watch->deref())
			delete watch;
	}

	trackable::watcher* watch;
	T* instance;
	function ptr;
};

} }

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Canada Canada
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions