fastdelegate.h.svn-base
来自「ffshow源码」· SVN-BASE 代码 · 共 1,415 行 · 第 1/5 页
SVN-BASE
1,415 行
// FastDelegate.h // Efficient delegates in C++ that generate only two lines of asm code!// Documentation is found at http://www.codeproject.com/cpp/FastDelegate.asp//// - Don Clugston, Mar 2004.// Major contributions were made by Jody Hagins.// History:// 24-Apr-04 1.0 * Submitted to CodeProject. // 28-Apr-04 1.1 * Prevent most unsafe uses of evil static function hack.// * Improved syntax for horrible_cast (thanks Paul Bludov).// * Tested on Metrowerks MWCC and Intel ICL (IA32)// * Compiled, but not run, on Comeau C++ and Intel Itanium ICL.// 27-Jun-04 1.2 * Now works on Borland C++ Builder 5.5// * Now works on /clr "managed C++" code on VC7, VC7.1// * Comeau C++ now compiles without warnings.// * Prevent the virtual inheritance case from being used on // VC6 and earlier, which generate incorrect code.// * Improved warning and error messages. Non-standard hacks// now have compile-time checks to make them safer.// * implicit_cast used instead of static_cast in many cases.// * If calling a const member function, a const class pointer can be used.// * MakeDelegate() global helper function added to simplify pass-by-value.// * Added fastdelegate.clear()// 16-Jul-04 1.2.1* Workaround for gcc bug (const member function pointers in templates)// 30-Oct-04 1.3 * Support for (non-void) return values.// * No more workarounds in client code!// MSVC and Intel now use a clever hack invented by John Dlugosz:// - The FASTDELEGATEDECLARE workaround is no longer necessary.// - No more warning messages for VC6// * Less use of macros. Error messages should be more comprehensible.// * Added include guards// * Added FastDelegate::empty() to test if invocation is safe (Thanks Neville Franks).// * Now tested on VS 2005 Express Beta, PGI C++// 24-Dec-04 1.4 * Added DelegateMemento, to allow collections of disparate delegates.// * <,>,<=,>= comparison operators to allow storage in ordered containers.// * Substantial reduction of code size, especially the 'Closure' class.// * Standardised all the compiler-specific workarounds.// * MFP conversion now works for CodePlay (but not yet supported in the full code).// * Now compiles without warnings on _any_ supported compiler, including BCC 5.5.1// * New syntax: FastDelegate< int (char *, double) >. // 14-Feb-05 1.4.1* Now treats =0 as equivalent to .clear(), ==0 as equivalent to .empty(). (Thanks elfric).// * Now tested on Intel ICL for AMD64, VS2005 Beta for AMD64 and Itanium.// 30-Mar-05 1.5 * Safebool idiom: "if (dg)" is now equivalent to "if (!dg.empty())"// * Fully supported by CodePlay VectorC// * Bugfix for Metrowerks: empty() was buggy because a valid MFP can be 0 on MWCC!// * More optimal assignment,== and != operators for static function pointers.#ifndef FASTDELEGATE_H#define FASTDELEGATE_H#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000#include <memory.h> // to allow <,> comparisons////////////////////////////////////////////////////////////////////////////////// Configuration options//////////////////////////////////////////////////////////////////////////////////// Uncomment the following #define for optimally-sized delegates.// In this case, the generated asm code is almost identical to the code you'd get// if the compiler had native support for delegates.// It will not work on systems where sizeof(dataptr) < sizeof(codeptr). // Thus, it will not work for DOS compilers using the medium model.// It will also probably fail on some DSP systems.#define FASTDELEGATE_USESTATICFUNCTIONHACK// Uncomment the next line to allow function declarator syntax.// It is automatically enabled for those compilers where it is known to work.//#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX////////////////////////////////////////////////////////////////////////////////// Compiler identification for workarounds//////////////////////////////////////////////////////////////////////////////////// Compiler identification. It's not easy to identify Visual C++ because// many vendors fraudulently define Microsoft's identifiers.#if defined(_MSC_VER) && !defined(__MWERKS__) && !defined(__VECTOR_C) && !defined(__ICL) && !defined(__BORLANDC__)#define FASTDLGT_ISMSVC#if (_MSC_VER <1300) // Many workarounds are required for VC6.#define FASTDLGT_VC6#pragma warning(disable:4786) // disable this ridiculous warning#endif#endif// Does the compiler uses Microsoft's member function pointer structure?// If so, it needs special treatment.// Metrowerks CodeWarrior, Intel, and CodePlay fraudulently define Microsoft's // identifier, _MSC_VER. We need to filter Metrowerks out.#if defined(_MSC_VER) && !defined(__MWERKS__)#define FASTDLGT_MICROSOFT_MFP#if !defined(__VECTOR_C)// CodePlay doesn't have the __single/multi/virtual_inheritance keywords#define FASTDLGT_HASINHERITANCE_KEYWORDS#endif#endif// Does it allow function declarator syntax? The following compilers are known to work:#if defined(FASTDLGT_ISMSVC) && (_MSC_VER >=1310) // VC 7.1#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX#endif// Gcc(2.95+), and versions of Digital Mars, Intel and Comeau in common use.#if defined (__DMC__) || defined(__GNUC__) || defined(__ICL) || defined(__COMO__)#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX#endif// It works on Metrowerks MWCC 3.2.2. From boost.Config it should work on earlier ones too.#if defined (__MWERKS__)#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX#endif#ifdef __GNUC__ // Workaround GCC bug #8271 // At present, GCC doesn't recognize constness of MFPs in templates#define FASTDELEGATE_GCC_BUG_8271#endif////////////////////////////////////////////////////////////////////////////////// General tricks used in this code//// (a) Error messages are generated by typdefing an array of negative size to// generate compile-time errors.// (b) Warning messages on MSVC are generated by declaring unused variables, and// enabling the "variable XXX is never used" warning.// (c) Unions are used in a few compiler-specific cases to perform illegal casts.// (d) For Microsoft and Intel, when adjusting the 'this' pointer, it's cast to// (char *) first to ensure that the correct number of *bytes* are added.//////////////////////////////////////////////////////////////////////////////////// Helper templates//////////////////////////////////////////////////////////////////////////////////namespace fastdelegate {namespace detail { // we'll hide the implementation details in a nested namespace.// 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 <class OutputClass, class InputClass>inline OutputClass implicit_cast(InputClass input){ return input;}// horrible_cast< >// This is truly evil. It completely subverts C++'s type system, allowing you // to cast from any class to any other class. Technically, using a union // to perform the cast is undefined behaviour (even in C). But we can see if// it is OK by checking that the union is the same size as each of its members.// horrible_cast<> should only be used for compiler-specific workarounds. // Usage is identical to reinterpret_cast<>.// This union is declared outside the horrible_cast because BCC 5.5.1// can't inline a function with a nested class, and gives a warning.template <class OutputClass, class InputClass>union horrible_union{ OutputClass out; InputClass in;};template <class OutputClass, class InputClass>inline OutputClass horrible_cast(const InputClass input){ horrible_union<OutputClass, InputClass> u; // Cause a compile-time error if in, out and u are not the same size. // If the compile fails here, it means the compiler has peculiar // unions which would prevent the cast from working. typedef int ERROR_CantUseHorrible_cast[sizeof(InputClass)==sizeof(u) && sizeof(InputClass)==sizeof(OutputClass) ? 1 : -1]; u.in = input; return u.out;}////////////////////////////////////////////////////////////////////////////////// Workarounds//////////////////////////////////////////////////////////////////////////////////// Backwards compatibility: This macro used to be necessary in the virtual inheritance// case for Intel and Microsoft. Now it just forward-declares the class.#define FASTDELEGATEDECLARE(CLASSNAME) class CLASSNAME;// Prevent use of the static function hack with the DOS medium model.#ifdef __MEDIUM__#undef FASTDELEGATE_USESTATICFUNCTIONHACK#endif// DefaultVoid - a workaround for 'void' templates in VC6.//// (1) VC6 and earlier do not allow 'void' as a default template argument.// (2) They also doesn't allow you to return 'void' from a function.//// Workaround for (1): Declare a dummy type 'DefaultVoid' which we use// when we'd like to use 'void'. We convert it into 'void' and back// using the templates DefaultVoidToVoid<> and VoidToDefaultVoid<>.// Workaround for (2): On VC6, the code for calling a void function is// identical to the code for calling a non-void function in which the// return value is never used, provided the return value is returned// in the EAX register, rather than on the stack. // This is true for most fundamental types such as int, enum, void *.// Const void * is the safest option since it doesn't participate // in any automatic conversions. But on a 16-bit compiler it might// cause extra code to be generated, so we disable it for all compilers// except for VC6 (and VC5).#ifdef FASTDLGT_VC6// VC6 workaroundtypedef const void * DefaultVoid;#else// On any other compiler, just use a normal void.typedef void DefaultVoid;#endif// Translate from 'DefaultVoid' to 'void'.// Everything else is unchangedtemplate <class T>struct DefaultVoidToVoid { typedef T type; };template <>struct DefaultVoidToVoid<DefaultVoid> { typedef void type; };// Translate from 'void' into 'DefaultVoid'// Everything else is unchangedtemplate <class T>struct VoidToDefaultVoid { typedef T type; };template <>struct VoidToDefaultVoid<void> { typedef DefaultVoid type; };////////////////////////////////////////////////////////////////////////////////// Fast Delegates, part 1://// Conversion of member function pointer to a standard form//////////////////////////////////////////////////////////////////////////////////// GenericClass is a fake class, ONLY used to provide a type.// It is vitally important that it is never defined, so that the compiler doesn't// think it can optimize the invocation. For example, Borland generates simpler// code if it knows the class only uses single inheritance.// Compilers using Microsoft's structure need to be treated as a special case.#ifdef FASTDLGT_MICROSOFT_MFP#ifdef FASTDLGT_HASINHERITANCE_KEYWORDS // For Microsoft and Intel, we want to ensure that it's the most efficient type of MFP // (4 bytes), even when the /vmg option is used. Declaring an empty class // would give 16 byte pointers in this case.... class __single_inheritance GenericClass;#endif // ...but for Codeplay, an empty class *always* gives 4 byte pointers. // If compiled with the /clr option ("managed C++"), the JIT compiler thinks // it needs to load GenericClass before it can call any of its functions, // (compiles OK but crashes at runtime!), so we need to declare an // empty class to make it happy. // Codeplay and VC4 can't cope with the unknown_inheritance case either. class GenericClass {};#else class GenericClass;#endif// The size of a single inheritance member function pointer.const int SINGLE_MEMFUNCPTR_SIZE = sizeof(void (GenericClass::*)());// SimplifyMemFunc< >::Convert()//// A template function that converts an arbitrary member function pointer into the // simplest possible form of member function pointer, using a supplied 'this' pointer.// According to the standard, this can be done legally with reinterpret_cast<>.// For (non-standard) compilers which use member function pointers which vary in size // depending on the class, we need to use knowledge of the internal structure of a // member function pointer, as used by the compiler. Template specialization is used
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?