/* ======== SourceHook ======== * Copyright (C) 2004-2008 Metamod:Source Development Team * No warranties of any kind * * License: zlib/libpng * * Author(s): Pavol "PM OnoTo" Marko * ============================ */ /** * @brief This file provides a way for getting information about a member function. * @file sh_memfuncinfo.h */ #ifndef __SHINT_MEMFUNC_INFO_H__ #define __SHINT_MEMFUNC_INFO_H__ namespace SourceHook { // Don Clugston: // implicit_cast< > // I believe this was originally going to be in the C++ standard but // was left out by accident. It's even milder than static_cast. // I use it instead of static_cast<> to emphasize that I'm not doing // anything nasty. // Usage is identical to static_cast<> template inline OutputClass implicit_cast(InputClass input){ return input; } struct MemFuncInfo { bool isVirtual; // Is the function virtual? int thisptroffs; // The this pointer the function expects to be called with // If -1, you need to call the GetFuncInfo_GetThisPtr function int vtblindex; // The function's index in the vtable (0-based, 1=second entry, 2=third entry, ...) int vtbloffs; // The vtable pointer }; // Ideas by Don Clugston. // Check out his excellent paper: http://www.codeproject.com/cpp/FastDelegate.asp template struct MFI_Impl { template static inline void GetFuncInfo(MFP *mfp, MemFuncInfo &out) { static char weird_memfunc_pointer_exclamation_mark_arrow_error[N-1000]; } }; # if SH_COMP == SH_COMP_GCC template<> struct MFI_Impl<2*SH_PTRSIZE> // All of these have size==8/16 { struct GCC_MemFunPtr { union { void *funcadr; // always even intptr_t vtable_index_plus1; // = vindex+1, always odd }; intptr_t delta; }; template static inline void GetFuncInfo(MFP mfp, MemFuncInfo &out) { GCC_MemFunPtr *mfp_detail = (GCC_MemFunPtr*)&mfp; out.thisptroffs = mfp_detail->delta; if (mfp_detail->vtable_index_plus1 & 1) { out.vtblindex = (mfp_detail->vtable_index_plus1 - 1) / SH_PTRSIZE; out.vtbloffs = 0; out.isVirtual = true; } else out.isVirtual = false; } }; # elif SH_COMP == SH_COMP_MSVC namespace { int MFI_GetVtblOffset(void *mfp) { unsigned char *addr = (unsigned char*)mfp; if (*addr == 0xE9) // Jmp { // May or may not be! // Check where it'd jump addr += 5 /*size of the instruction*/ + *(unsigned long*)(addr + 1); } // Check whether it's a virtual function call // They look like this: // 004125A0 8B 01 mov eax,dword ptr [ecx] // 004125A2 FF 60 04 jmp dword ptr [eax+4] // ==OR== // 00411B80 8B 01 mov eax,dword ptr [ecx] // 00411B82 FF A0 18 03 00 00 jmp dword ptr [eax+318h] // However, for vararg functions, they look like this: // 0048F0B0 8B 44 24 04 mov eax,dword ptr [esp+4] // 0048F0B4 8B 00 mov eax,dword ptr [eax] // 0048F0B6 FF 60 08 jmp dword ptr [eax+8] // ==OR== // 0048F0B0 8B 44 24 04 mov eax,dword ptr [esp+4] // 0048F0B4 8B 00 mov eax,dword ptr [eax] // 00411B82 FF A0 18 03 00 00 jmp dword ptr [eax+318h] // With varargs, the this pointer is passed as if it was the first argument bool ok = false; if (addr[0] == 0x8B && addr[1] == 0x44 && addr[2] == 0x24 && addr[3] == 0x04 && addr[4] == 0x8B && addr[5] == 0x00) { addr += 6; ok = true; } else if (addr[0] == 0x8B && addr[1] == 0x01) { addr += 2; ok = true; } if (!ok) return -1; if (*addr++ == 0xFF) { if (*addr == 0x60) { return *++addr / 4; } else if (*addr == 0xA0) { return *((unsigned int*)++addr) / 4; } else if (*addr == 0x20) return 0; else return -1; } return -1; } } template<> struct MFI_Impl<1*SH_PTRSIZE> // simple ones { template static inline void GetFuncInfo(MFP mfp, MemFuncInfo &out) { out.vtblindex = MFI_GetVtblOffset(*(void**)&mfp); out.isVirtual = out.vtblindex >= 0 ? true : false; out.thisptroffs = 0; out.vtbloffs = 0; } }; template<> struct MFI_Impl<2*SH_PTRSIZE> // more complicated ones! { struct MSVC_MemFunPtr2 { void *funcadr; int delta; }; template static inline void GetFuncInfo(MFP mfp, MemFuncInfo &out) { out.vtblindex = MFI_GetVtblOffset(*(void**)&mfp); out.isVirtual = out.vtblindex >= 0 ? true : false; out.thisptroffs = reinterpret_cast(&mfp)->delta; out.vtbloffs = 0; } }; // By Don Clugston, adapted template<> struct MFI_Impl<3*SH_PTRSIZE> // WOW IT"S GETTING BIGGER OMGOMOGMG { class __single_inheritance GenericClass; class GenericClass {}; struct MicrosoftVirtualMFP { void (GenericClass::*codeptr)(); // points to the actual member function int delta; // #bytes to be added to the 'this' pointer int vtable_index; // or 0 if no virtual inheritance }; struct GenericVirtualClass : virtual public GenericClass { typedef GenericVirtualClass * (GenericVirtualClass::*ProbePtrType)(); GenericVirtualClass * GetThis() { return this; } }; template static inline void GetFuncInfo(MFP mfp, MemFuncInfo &out) { out.vtblindex = MFI_GetVtblOffset(*(void**)&mfp); out.isVirtual = out.vtblindex >= 0 ? true : false; // This pointer /* union { MFP func; GenericClass* (T::*ProbeFunc)(); MicrosoftVirtualMFP s; } u; u.func = mfp; union { GenericVirtualClass::ProbePtrType virtfunc; MicrosoftVirtualMFP s; } u2; // Check that the horrible_cast<>s will work typedef int ERROR_CantUsehorrible_cast[sizeof(mfp)==sizeof(u.s) && sizeof(mfp)==sizeof(u.ProbeFunc) && sizeof(u2.virtfunc)==sizeof(u2.s) ? 1 : -1]; // Unfortunately, taking the address of a MF prevents it from being inlined, so // this next line can't be completely optimised away by the compiler. u2.virtfunc = &GenericVirtualClass::GetThis; u.s.codeptr = u2.s.codeptr; out.thisptroffs = (reinterpret_cast(NULL)->*u.ProbeFunc)(); */ out.thisptroffs = -1; out.vtbloffs = 0; } }; // Don: Nasty hack for Microsoft and Intel (IA32 and Itanium) // unknown_inheritance classes go here // This is probably the ugliest bit of code I've ever written. Look at the casts! // There is a compiler bug in MSVC6 which prevents it from using this code. template<> struct MFI_Impl<4*SH_PTRSIZE> // THE BIGGEST ONE!!!1GABEN { template static inline void GetFuncInfo(MFP mfp, MemFuncInfo &out) { out.vtblindex = MFI_GetVtblOffset(*(void**)&mfp); out.isVirtual = out.vtblindex >= 0 ? true : false; // The member function pointer is 16 bytes long. We can't use a normal cast, but // we can use a union to do the conversion. union { MFP func; // In VC++ and ICL, an unknown_inheritance member pointer // is internally defined as: struct { void *m_funcaddress; // points to the actual member function int delta; // #bytes to be added to the 'this' pointer int vtordisp; // #bytes to add to 'this' to find the vtable int vtable_index; // or 0 if no virtual inheritance } s; } u; // Check that the horrible_cast will work typedef int ERROR_CantUsehorrible_cast[sizeof(u.func)==sizeof(u.s)? 1 : -1]; u.func = mfp; int virtual_delta = 0; if (u.s.vtable_index) { // Virtual inheritance is used /* // First, get to the vtable. // It is 'vtordisp' bytes from the start of the class. int * vtable = *reinterpret_cast( reinterpret_cast(thisptr) + u.s.vtordisp ); // 'vtable_index' tells us where in the table we should be looking. virtual_delta = u.s.vtordisp + *reinterpret_cast( reinterpret_cast(vtable) + u.s.vtable_index); // The int at 'virtual_delta' gives us the amount to add to 'this'. // Finally we can add the three components together. Phew! out.thisptr = reinterpret_cast( reinterpret_cast(thisptr) + u.s.delta + virtual_delta); */ out.vtbloffs = u.s.vtordisp; out.thisptroffs = -1; } else { out.vtbloffs = out.vtblindex < 0 ? 0 : u.s.delta; out.thisptroffs = u.s.delta; } }; }; # else # error Unsupported compiler # endif // This version does not take a this pointer // Useful for hookdecls, as they ensure that mfp is correct through a static_cast template inline void GetFuncInfo(X mfp, MemFuncInfo &out) { MFI_Impl::GetFuncInfo(mfp, out); } // Versions which do take a this template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(), MemFuncInfo &out) { RetType(Y::*mfp2)() = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)() const, MemFuncInfo &out) { RetType(Y::*mfp2)() const = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1), MemFuncInfo &out) { RetType(Y::*mfp2)(Param1) = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1) const, MemFuncInfo &out) { RetType(Y::*mfp2)(Param1) const = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2), MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2) = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2) const, MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2) const = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3), MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3) = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3) const, MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3) const = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4), MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4) = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4) const, MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4) const = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5), MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5) = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5) const, MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5) const = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6), MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6) = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6) const, MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6) const = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7), MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7) = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7) const, MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7) const = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8), MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8) = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8) const, MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8) const = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9), MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9) = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9) const, MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9) const = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10), MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10) = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10) const, MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10) const = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11), MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11) = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11) const, MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11) const = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12), MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12) = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12) const, MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12) const = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13), MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13) = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13) const, MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13) const = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14), MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14) = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14) const, MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14) const = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15), MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15) = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15) const, MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15) const = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16), MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16) = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16) const, MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16) const = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } // GCC & MSVC 7.1 need this, MSVC 7.0 doesn't like it #if SH_COMP != SH_COMP_MSVC || _MSC_VER > 1300 template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(...), MemFuncInfo &out) { RetType(Y::*mfp2)(...) = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(...) const, MemFuncInfo &out) { RetType(Y::*mfp2)(...) const = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, ...), MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, ...) = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, ...) const, MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, ...) const = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, ...), MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, ...) = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, ...) const, MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, ...) const = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, ...), MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, ...) = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, ...) const, MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, ...) const = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, ...), MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, ...) = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, ...) const, MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, ...) const = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, ...), MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, ...) = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, ...) const, MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, ...) const = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, ...), MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, ...) = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, ...) const, MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, ...) const = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, ...), MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, ...) = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, ...) const, MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, ...) const = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, ...), MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, ...) = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, ...) const, MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, ...) const = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, ...), MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, ...) = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, ...) const, MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, ...) const = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, ...), MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, ...) = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, ...) const, MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, ...) const = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, ...), MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, ...) = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, ...) const, MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, ...) const = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, ...), MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, ...) = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, ...) const, MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, ...) const = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, ...), MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, ...) = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, ...) const, MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, ...) const = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, ...), MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, ...) = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, ...) const, MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, ...) const = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, ...), MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, ...) = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, ...) const, MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, ...) const = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, ...), MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, ...) = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } template inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, ...) const, MemFuncInfo &out) { RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, ...) const = mfp; MFI_Impl::GetFuncInfo(mfp2, out); } #endif } #endif