fastdelegate.h.svn-base

来自「ffshow源码」· SVN-BASE 代码 · 共 1,415 行 · 第 1/5 页

SVN-BASE
1,415
字号
	// the data is protected, not private, because many	// compilers have problems with template friends.	typedef void (detail::GenericClass::*GenericMemFuncType)(); // arbitrary MFP.	detail::GenericClass *m_pthis;	GenericMemFuncType m_pFunction;#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)	typedef void (*GenericFuncPtr)(); // arbitrary code pointer	GenericFuncPtr m_pStaticFunction;#endifpublic:#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)	DelegateMemento() : m_pthis(0), m_pFunction(0), m_pStaticFunction(0) {};	void clear() {		m_pthis=0; m_pFunction=0; m_pStaticFunction=0;	}#else	DelegateMemento() : m_pthis(0), m_pFunction(0) {};	void clear() {	m_pthis=0; m_pFunction=0;	}#endifpublic:#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)	inline bool IsEqual (const DelegateMemento &x) const{	    // We have to cope with the static function pointers as a special case		if (m_pFunction!=x.m_pFunction) return false;		// the static function ptrs must either both be equal, or both be 0.		if (m_pStaticFunction!=x.m_pStaticFunction) return false;		if (m_pStaticFunction!=0) return m_pthis==x.m_pthis;		else return true;	}#else // Evil Method	inline bool IsEqual (const DelegateMemento &x) const{		return m_pthis==x.m_pthis && m_pFunction==x.m_pFunction;	}#endif	// Provide a strict weak ordering for DelegateMementos.	inline bool IsLess(const DelegateMemento &right) const {		// deal with static function pointers first#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)		if (m_pStaticFunction !=0 || right.m_pStaticFunction!=0) 				return m_pStaticFunction < right.m_pStaticFunction;#endif		if (m_pthis !=right.m_pthis) return m_pthis < right.m_pthis;	// There are no ordering operators for member function pointers, 	// but we can fake one by comparing each byte. The resulting ordering is	// arbitrary (and compiler-dependent), but it permits storage in ordered STL containers.		return memcmp(&m_pFunction, &right.m_pFunction, sizeof(m_pFunction)) < 0;	}	// BUGFIX (Mar 2005):	// We can't just compare m_pFunction because on Metrowerks,	// m_pFunction can be zero even if the delegate is not empty!	inline bool operator ! () const		// Is it bound to anything?	{ return m_pthis==0 && m_pFunction==0; }	inline bool empty() const		// Is it bound to anything?	{ return m_pthis==0 && m_pFunction==0; }public:	DelegateMemento & operator = (const DelegateMemento &right)  {		SetMementoFrom(right); 		return *this;	}	inline bool operator <(const DelegateMemento &right) {		return IsLess(right);	}	inline bool operator >(const DelegateMemento &right) {		return right.IsLess(*this);	}	DelegateMemento (const DelegateMemento &right)  : 		m_pFunction(right.m_pFunction), m_pthis(right.m_pthis)#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)		, m_pStaticFunction (right.m_pStaticFunction)#endif		{}protected:	void SetMementoFrom(const DelegateMemento &right)  {		m_pFunction = right.m_pFunction;		m_pthis = right.m_pthis;#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)		m_pStaticFunction = right.m_pStaticFunction;#endif	}};//						ClosurePtr<>//// A private wrapper class that adds function signatures to DelegateMemento.// It's the class that does most of the actual work.// The signatures are specified by:// GenericMemFunc: must be a type of GenericClass member function pointer. // StaticFuncPtr:  must be a type of function pointer with the same signature //                 as GenericMemFunc.// UnvoidStaticFuncPtr: is the same as StaticFuncPtr, except on VC6//                 where it never returns void (returns DefaultVoid instead).// An outer class, FastDelegateN<>, handles the invoking and creates the// necessary typedefs.// This class does everything else.namespace detail {template < class GenericMemFunc, class StaticFuncPtr, class UnvoidStaticFuncPtr>class ClosurePtr : public DelegateMemento {public:	// These functions are for setting the delegate to a member function.	// Here's the clever bit: we convert an arbitrary member function into a 	// standard form. XMemFunc should be a member function of class X, but I can't 	// enforce that here. It needs to be enforced by the wrapper class.	template < class X, class XMemFunc >	inline void bindmemfunc(X *pthis, XMemFunc function_to_bind ) {		m_pthis = SimplifyMemFunc< sizeof(function_to_bind) >			::Convert(pthis, function_to_bind, m_pFunction);#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)		m_pStaticFunction = 0;#endif	}	// For const member functions, we only need a const class pointer.	// Since we know that the member function is const, it's safe to 	// remove the const qualifier from the 'this' pointer with a const_cast.	// VC6 has problems if we just overload 'bindmemfunc', so we give it a different name.	template < class X, class XMemFunc>	inline void bindconstmemfunc(const X *pthis, XMemFunc function_to_bind) {		m_pthis= SimplifyMemFunc< sizeof(function_to_bind) >			::Convert(const_cast<X*>(pthis), function_to_bind, m_pFunction);#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)		m_pStaticFunction = 0;#endif	}#ifdef FASTDELEGATE_GCC_BUG_8271	// At present, GCC doesn't recognize constness of MFPs in templates	template < class X, class XMemFunc>	inline void bindmemfunc(const X *pthis, XMemFunc function_to_bind) {		bindconstmemfunc(pthis, function_to_bind);#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)		m_pStaticFunction = 0;#endif	}#endif	// These functions are required for invoking the stored function	inline GenericClass *GetClosureThis() const { return m_pthis; }	inline GenericMemFunc GetClosureMemPtr() const { return reinterpret_cast<GenericMemFunc>(m_pFunction); }// There are a few ways of dealing with static function pointers.// There's a standard-compliant, but tricky method.// There's also a straightforward hack, that won't work on DOS compilers using the// medium memory model. It's so evil that I can't recommend it, but I've// implemented it anyway because it produces very nice asm code.#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)//				ClosurePtr<> - Safe version//// This implementation is standard-compliant, but a bit tricky.// I store the function pointer inside the class, and the delegate then// points to itself. Whenever the delegate is copied, these self-references// must be transformed, and this complicates the = and == operators.public:	// The next two functions are for operator ==, =, and the copy constructor.	// We may need to convert the m_pthis pointers, so that	// they remain as self-references.	template< class DerivedClass >	inline void CopyFrom (DerivedClass *pParent, const DelegateMemento &x) {		SetMementoFrom(x);		if (m_pStaticFunction!=0) {			// transform self references...			m_pthis=reinterpret_cast<GenericClass *>(pParent);		}	}	// For static functions, the 'static_function_invoker' class in the parent 	// will be called. The parent then needs to call GetStaticFunction() to find out 	// the actual function to invoke.	template < class DerivedClass, class ParentInvokerSig >	inline void bindstaticfunc(DerivedClass *pParent, ParentInvokerSig static_function_invoker, 				StaticFuncPtr function_to_bind ) {		if (function_to_bind==0) { // cope with assignment to 0			m_pFunction=0;		} else { 			bindmemfunc(pParent, static_function_invoker);        }		m_pStaticFunction=reinterpret_cast<GenericFuncPtr>(function_to_bind);	}	inline UnvoidStaticFuncPtr GetStaticFunction() const { 		return reinterpret_cast<UnvoidStaticFuncPtr>(m_pStaticFunction); 	}#else//				ClosurePtr<> - Evil version//// For compilers where data pointers are at least as big as code pointers, it is // possible to store the function pointer in the this pointer, using another // horrible_cast. Invocation isn't any faster, but it saves 4 bytes, and// speeds up comparison and assignment. If C++ provided direct language support// for delegates, they would produce asm code that was almost identical to this.// Note that the Sun C++ and MSVC documentation explicitly state that they // support static_cast between void * and function pointers.	template< class DerivedClass >	inline void CopyFrom (DerivedClass *pParent, const DelegateMemento &right) {		SetMementoFrom(right);	}	// For static functions, the 'static_function_invoker' class in the parent 	// will be called. The parent then needs to call GetStaticFunction() to find out 	// the actual function to invoke.	// ******** EVIL, EVIL CODE! *******	template < 	class DerivedClass, class ParentInvokerSig>	inline void bindstaticfunc(DerivedClass *pParent, ParentInvokerSig static_function_invoker, 				StaticFuncPtr function_to_bind) {		if (function_to_bind==0) { // cope with assignment to 0			m_pFunction=0;		} else { 		   // We'll be ignoring the 'this' pointer, but we need to make sure we pass		   // a valid value to bindmemfunc().			bindmemfunc(pParent, static_function_invoker);        }		// WARNING! Evil hack. We store the function in the 'this' pointer!		// Ensure that there's a compilation failure if function pointers 		// and data pointers have different sizes.		// If you get this error, you need to #undef FASTDELEGATE_USESTATICFUNCTIONHACK.		typedef int ERROR_CantUseEvilMethod[sizeof(GenericClass *)==sizeof(function_to_bind) ? 1 : -1];		m_pthis = horrible_cast<GenericClass *>(function_to_bind);		// MSVC, SunC++ and DMC accept the following (non-standard) code://		m_pthis = static_cast<GenericClass *>(static_cast<void *>(function_to_bind));		// BCC32, Comeau and DMC accept this method. MSVC7.1 needs __int64 instead of long//		m_pthis = reinterpret_cast<GenericClass *>(reinterpret_cast<long>(function_to_bind));	}	// ******** EVIL, EVIL CODE! *******	// This function will be called with an invalid 'this' pointer!!	// We're just returning the 'this' pointer, converted into	// a function pointer!	inline UnvoidStaticFuncPtr GetStaticFunction() const {		// Ensure that there's a compilation failure if function pointers 		// and data pointers have different sizes.		// If you get this error, you need to #undef FASTDELEGATE_USESTATICFUNCTIONHACK.		typedef int ERROR_CantUseEvilMethod[sizeof(UnvoidStaticFuncPtr)==sizeof(this) ? 1 : -1];		return horrible_cast<UnvoidStaticFuncPtr>(this);	}#endif // !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)	// Does the closure contain this static function?	inline bool IsEqualToStaticFuncPtr(StaticFuncPtr funcptr){		if (funcptr==0) return empty(); 	// For the Evil method, if it doesn't actually contain a static function, this will return an arbitrary	// value that is not equal to any valid function pointer.		else return funcptr==reinterpret_cast<StaticFuncPtr>(GetStaticFunction());	}};} // namespace detail//////////////////////////////////////////////////////////////////////////////////						Fast Delegates, part 3:////				Wrapper classes to ensure type safety//////////////////////////////////////////////////////////////////////////////////// Once we have the member function conversion templates, it's easy to make the// wrapper classes. So that they will work with as many compilers as possible, // the classes are of the form//   FastDelegate3<int, char *, double>// They can cope with any combination of parameters. The max number of parameters// allowed is 8, but it is trivial to increase this limit.// Note that we need to treat const member functions seperately.// All this class does is to enforce type safety, and invoke the delegate with// the correct list of parameters.// Because of the weird rule about the class of derived member function pointers,// you sometimes need to apply a downcast to the 'this' pointer.// This is the reason for the use of "implicit_cast<X*>(pthis)" in the code below. // If CDerivedClass is derived from CBaseClass, but doesn't override SimpleVirtualFunction,// without this trick you'd need to write://		MyDelegate(static_cast<CBaseClass *>(&d), &CDerivedClass::SimpleVirtualFunction);// but with the trick you can write//		MyDelegate(&d, &CDerivedClass::SimpleVirtualFunction);// RetType is the type the compiler uses in compiling the template. For VC6,// it cannot be void. DesiredRetType is the real type which is returned from// all of the functions. It can be void.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?