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 + -
显示快捷键?