Click here to Skip to main content
15,887,596 members
Articles / Programming Languages / C++

Fast C++ Delegate: Boost.Function 'drop-in' replacement and multicast

Rate me:
Please Sign up or sign in to vote.
4.86/5 (51 votes)
1 Jun 200733 min read 291.8K   1.9K   110  
An article on the implementation of a fast C++ delegate with many advanced features.
/*
	(c) Sergey Ryazanov (http://home.onego.ru/~ryazanov)

	Template file. May be included many times with different predefined macros.
*/
#if SRUTIL_DELEGATE_PARAM_COUNT > 0
#define SRUTIL_DELEGATE_SEPARATOR ,
#else
#define SRUTIL_DELEGATE_SEPARATOR
#endif

// see BOOST_JOIN for explanation
#define SRUTIL_DELEGATE_JOIN_MACRO( X, Y) SRUTIL_DELEGATE_DO_JOIN( X, Y )
#define SRUTIL_DELEGATE_DO_JOIN( X, Y ) SRUTIL_DELEGATE_DO_JOIN2(X,Y)
#define SRUTIL_DELEGATE_DO_JOIN2( X, Y ) X##Y

namespace srutil
{
#ifdef SRUTIL_DELEGATE_PREFERRED_SYNTAX
#define SRUTIL_DELEGATE_CLASS_NAME delegate
#define SRUTIL_DELEGATE_INVOKER_CLASS_NAME delegate_invoker
#else
#define SRUTIL_DELEGATE_CLASS_NAME SRUTIL_DELEGATE_JOIN_MACRO(delegate,SRUTIL_DELEGATE_PARAM_COUNT)
#define SRUTIL_DELEGATE_INVOKER_CLASS_NAME SRUTIL_DELEGATE_JOIN_MACRO(delegate_invoker,SRUTIL_DELEGATE_PARAM_COUNT)
	template <typename R SRUTIL_DELEGATE_SEPARATOR SRUTIL_DELEGATE_TEMPLATE_PARAMS>
	class SRUTIL_DELEGATE_INVOKER_CLASS_NAME;
#endif

	template <typename R SRUTIL_DELEGATE_SEPARATOR SRUTIL_DELEGATE_TEMPLATE_PARAMS>
#ifdef SRUTIL_DELEGATE_PREFERRED_SYNTAX
	class SRUTIL_DELEGATE_CLASS_NAME<R (SRUTIL_DELEGATE_TEMPLATE_ARGS)>
#else
	class SRUTIL_DELEGATE_CLASS_NAME
#endif
	{
	public:
		typedef R return_type;
#ifdef SRUTIL_DELEGATE_PREFERRED_SYNTAX
		typedef return_type (SRUTIL_DELEGATE_CALLTYPE *signature_type)(SRUTIL_DELEGATE_TEMPLATE_ARGS);
		typedef SRUTIL_DELEGATE_INVOKER_CLASS_NAME<signature_type> invoker_type;
#else
		typedef SRUTIL_DELEGATE_INVOKER_CLASS_NAME<R SRUTIL_DELEGATE_SEPARATOR SRUTIL_DELEGATE_TEMPLATE_ARGS> invoker_type;
#endif

		SRUTIL_DELEGATE_CLASS_NAME()
			: object_ptr(0)
			, stub_ptr(0)
		{}

		template <return_type (*TMethod)(SRUTIL_DELEGATE_TEMPLATE_ARGS)>
		static SRUTIL_DELEGATE_CLASS_NAME from_function()
		{
			return from_stub(0, &function_stub<TMethod>);
		}

		template <class T, return_type (T::*TMethod)(SRUTIL_DELEGATE_TEMPLATE_ARGS)>
		static SRUTIL_DELEGATE_CLASS_NAME from_method(T* object_ptr)
		{
			return from_stub(object_ptr, &method_stub<T, TMethod>);
		}

		template <class T, return_type (T::*TMethod)(SRUTIL_DELEGATE_TEMPLATE_ARGS) const>
		static SRUTIL_DELEGATE_CLASS_NAME from_const_method(T const* object_ptr)
		{
			return from_stub(const_cast<T*>(object_ptr), &const_method_stub<T, TMethod>);
		}

		return_type operator()(SRUTIL_DELEGATE_PARAMS) const
		{
			return (*stub_ptr)(object_ptr SRUTIL_DELEGATE_SEPARATOR SRUTIL_DELEGATE_ARGS);
		}

		operator bool () const
		{
			return stub_ptr != 0;
		}

		bool operator!() const
		{
			return !(operator bool());
		}

	private:
		
		typedef return_type (SRUTIL_DELEGATE_CALLTYPE *stub_type)(void* object_ptr SRUTIL_DELEGATE_SEPARATOR SRUTIL_DELEGATE_PARAMS);

		void* object_ptr;
		stub_type stub_ptr;

		static SRUTIL_DELEGATE_CLASS_NAME from_stub(void* object_ptr, stub_type stub_ptr)
		{
			SRUTIL_DELEGATE_CLASS_NAME d;
			d.object_ptr = object_ptr;
			d.stub_ptr = stub_ptr;
			return d;
		}

		template <return_type (*TMethod)(SRUTIL_DELEGATE_TEMPLATE_ARGS)>
		static return_type SRUTIL_DELEGATE_CALLTYPE function_stub(void* SRUTIL_DELEGATE_SEPARATOR SRUTIL_DELEGATE_PARAMS)
		{
			return (TMethod)(SRUTIL_DELEGATE_ARGS);
		}

		template <class T, return_type (T::*TMethod)(SRUTIL_DELEGATE_TEMPLATE_ARGS)>
		static return_type SRUTIL_DELEGATE_CALLTYPE method_stub(void* object_ptr SRUTIL_DELEGATE_SEPARATOR SRUTIL_DELEGATE_PARAMS)
		{
			T* p = static_cast<T*>(object_ptr);
			return (p->*TMethod)(SRUTIL_DELEGATE_ARGS);
		}

		template <class T, return_type (T::*TMethod)(SRUTIL_DELEGATE_TEMPLATE_ARGS) const>
		static return_type SRUTIL_DELEGATE_CALLTYPE const_method_stub(void* object_ptr SRUTIL_DELEGATE_SEPARATOR SRUTIL_DELEGATE_PARAMS)
		{
			T const* p = static_cast<T*>(object_ptr);
			return (p->*TMethod)(SRUTIL_DELEGATE_ARGS);
		}
	};

	template <typename R SRUTIL_DELEGATE_SEPARATOR SRUTIL_DELEGATE_TEMPLATE_PARAMS>
#ifdef SRUTIL_DELEGATE_PREFERRED_SYNTAX
	class SRUTIL_DELEGATE_INVOKER_CLASS_NAME<R (SRUTIL_DELEGATE_TEMPLATE_ARGS)>
#else
	class SRUTIL_DELEGATE_INVOKER_CLASS_NAME
#endif
	{
		SRUTIL_DELEGATE_INVOKER_DATA

	public:
		SRUTIL_DELEGATE_INVOKER_CLASS_NAME(SRUTIL_DELEGATE_PARAMS)
#if SRUTIL_DELEGATE_PARAM_COUNT > 0
			:
#endif
			SRUTIL_DELEGATE_INVOKER_INITIALIZATION_LIST
		{
		}

		template <class TDelegate>
		R operator()(TDelegate d) const
		{
			return d(SRUTIL_DELEGATE_ARGS);
		}
	};
}

#undef SRUTIL_DELEGATE_CLASS_NAME
#undef SRUTIL_DELEGATE_SEPARATOR
#undef SRUTIL_DELEGATE_JOIN_MACRO
#undef SRUTIL_DELEGATE_DO_JOIN
#undef SRUTIL_DELEGATE_DO_JOIN2

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
Other
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