diff --git a/sdk/include/jpeg/libjpeg.vcxproj b/sdk/include/jpeg/libjpeg.vcxproj
index 95cdbd8cee..87d1504053 100644
--- a/sdk/include/jpeg/libjpeg.vcxproj
+++ b/sdk/include/jpeg/libjpeg.vcxproj
@@ -13,6 +13,10 @@
Releasex64
+
+ VerifiedDX11ASAN
+ x64
+ VerifiedDX11x64
@@ -56,6 +60,15 @@
MultiBytex64
+
+ StaticLibrary
+ false
+ v143
+ false
+ MultiByte
+ x64
+ true
+ StaticLibraryv143
@@ -81,6 +94,10 @@
+
+
+
+
@@ -110,6 +127,12 @@
$(xrGameDir)bin_dbg\$(Platform)\$(Configuration)\$(xrIntDir)$(ProjectName)\
+
+ E:\STALKER\X-Ray Source\x_ray_1602_VS13\xray-16\src\3rd party;$(IncludePath);$(xrSdkDir)include;
+ C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x86;$(LibraryPath)
+ $(xrGameDir)bin_dbg\$(Platform)\$(Configuration)\
+ $(xrIntDir)$(ProjectName)\
+ E:\STALKER\X-Ray Source\x_ray_1602_VS13\xray-16\src\3rd party;$(IncludePath);$(xrSdkDir)include;C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x86;$(LibraryPath)
@@ -215,6 +238,32 @@
false
+
+
+ Disabled
+ false
+ ..\;%(AdditionalIncludeDirectories)
+ NotSet
+ ProgramDatabase
+ false
+ _DISABLE_VECTOR_ANNOTATION;_DISABLE_STRING_ANNOTATION;USE_VERIFY_IN_RELEASE;_VC80_UPGRADE=0x0710;_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS;%(PreprocessorDefinitions)
+ Neither
+ Level3
+ false
+ Disabled
+ false
+ stdcpp17
+ true
+
+
+ true
+ true
+ true
+
+
+ false
+
+ ..\;%(AdditionalIncludeDirectories)
diff --git a/sdk/include/ogg/libogg_static.vcxproj b/sdk/include/ogg/libogg_static.vcxproj
index cacca512c1..bfd98b427f 100644
--- a/sdk/include/ogg/libogg_static.vcxproj
+++ b/sdk/include/ogg/libogg_static.vcxproj
@@ -13,6 +13,10 @@
Releasex64
+
+ VerifiedDX11ASAN
+ x64
+ VerifiedDX11x64
@@ -49,6 +53,12 @@
Unicodefalse
+
+ StaticLibrary
+ v120
+ Unicode
+ false
+ StaticLibraryv143
@@ -77,6 +87,13 @@
Unicodex64
+
+ v143
+ StaticLibrary
+ Unicode
+ x64
+ true
+ StaticLibrarytrue
@@ -101,6 +118,10 @@
+
+
+
+
@@ -125,6 +146,10 @@
$(SolutionDir)..\$(Platform)\$(Configuration)\$(xrIntDir)$(ProjectName)\
+
+ $(SolutionDir)..\$(Platform)\$(Configuration)\
+ $(xrIntDir)$(ProjectName)\
+ $(SolutionDir)..\$(Platform)\$(Configuration)\$(xrIntDir)$(ProjectName)\
@@ -149,6 +174,11 @@
.liblibogg_static
+
+ $(xrGameDir)bin_dbg\$(Platform)\$(Configuration)\
+ .lib
+ libogg_static
+ $(xrGameDir)bin_dbg\$(Platform)\$(Configuration)\.lib
@@ -259,6 +289,34 @@
false
+
+
+ X64
+
+
+ Disabled
+ false
+ Neither
+ ..\include;%(AdditionalIncludeDirectories)
+ _DISABLE_VECTOR_ANNOTATION;_DISABLE_STRING_ANNOTATION;USE_VERIFY_IN_RELEASE;WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)
+ NotSet
+
+
+ ProgramDatabase
+ 4244;%(DisableSpecificWarnings)
+ false
+ false
+ Disabled
+ false
+ Level4
+ CompileAsC
+ stdcpp17
+ true
+
+
+ false
+
+ X64
diff --git a/sdk/include/theora/libtheora_static.vcxproj b/sdk/include/theora/libtheora_static.vcxproj
index ebd210f0d4..94b823e1a9 100644
--- a/sdk/include/theora/libtheora_static.vcxproj
+++ b/sdk/include/theora/libtheora_static.vcxproj
@@ -13,6 +13,10 @@
Releasex64
+
+ VerifiedDX11ASAN
+ x64
+ VerifiedDX11x64
@@ -55,6 +59,14 @@
falsex64
+
+ StaticLibrary
+ v143
+ Unicode
+ false
+ x64
+ true
+ StaticLibraryv143
@@ -84,6 +96,11 @@
+
+
+
+
+
@@ -113,6 +130,11 @@
$(xrIntDir)$(ProjectName)\libtheora_static
+
+ $(xrGameDir)bin_dbg\$(Platform)\$(Configuration)\
+ $(xrIntDir)$(ProjectName)\
+ libtheora_static
+ $(xrGameDir)bin_dbg\$(Platform)\$(Configuration)\$(xrIntDir)$(ProjectName)\
@@ -223,6 +245,34 @@
false
+
+
+ X64
+
+
+ Disabled
+ false
+ Neither
+ ..\..\include;..\..\lib;%(AdditionalIncludeDirectories)
+ _DISABLE_VECTOR_ANNOTATION;_DISABLE_STRING_ANNOTATION;USE_VERIFY_IN_RELEASE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_BIND_TO_CURRENT_CRT_VERSION;WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)
+
+
+ ProgramDatabase
+ 4244;4267;4057;4100;4245;%(DisableSpecificWarnings)
+ NotSet
+ false
+ Level4
+ false
+ Disabled
+ false
+ CompileAsC
+ stdcpp17
+ true
+
+
+ false
+
+ X64
@@ -283,11 +333,13 @@
$(IntDir)%(Filename)1.obj$(IntDir)%(Filename)1.obj$(IntDir)%(Filename)1.obj
+ $(IntDir)%(Filename)1.obj$(IntDir)%(Filename)1.obj$(IntDir)%(Filename)1.xdc$(IntDir)%(Filename)1.xdc$(IntDir)%(Filename)1.xdc$(IntDir)%(Filename)1.xdc
+ $(IntDir)%(Filename)1.xdc$(IntDir)%(Filename)1.xdc
@@ -300,6 +352,7 @@
truetruetrue
+ truetrue
@@ -312,11 +365,13 @@
$(IntDir)%(Filename)1.obj$(IntDir)%(Filename)1.obj$(IntDir)%(Filename)1.obj
+ $(IntDir)%(Filename)1.obj$(IntDir)%(Filename)1.obj$(IntDir)%(Filename)1.xdc$(IntDir)%(Filename)1.xdc$(IntDir)%(Filename)1.xdc$(IntDir)%(Filename)1.xdc
+ $(IntDir)%(Filename)1.xdc$(IntDir)%(Filename)1.xdc
@@ -328,11 +383,13 @@
$(IntDir)%(Filename)1.obj$(IntDir)%(Filename)1.obj$(IntDir)%(Filename)1.obj
+ $(IntDir)%(Filename)1.obj$(IntDir)%(Filename)1.obj$(IntDir)%(Filename)1.xdc$(IntDir)%(Filename)1.xdc$(IntDir)%(Filename)1.xdc$(IntDir)%(Filename)1.xdc
+ $(IntDir)%(Filename)1.xdc$(IntDir)%(Filename)1.xdc
diff --git a/sdk/include/vorbis/libvorbis_static.vcxproj b/sdk/include/vorbis/libvorbis_static.vcxproj
index f38cb0e1e0..6fe78e18da 100644
--- a/sdk/include/vorbis/libvorbis_static.vcxproj
+++ b/sdk/include/vorbis/libvorbis_static.vcxproj
@@ -13,6 +13,10 @@
Releasex64
+
+ VerifiedDX11ASAN
+ x64
+ VerifiedDX11x64
@@ -55,6 +59,14 @@
falsex64
+
+ StaticLibrary
+ v143
+ Unicode
+ false
+ x64
+ true
+ StaticLibraryv143
@@ -84,6 +96,11 @@
+
+
+
+
+
@@ -109,6 +126,10 @@
$(xrGameDir)bin_dbg\$(Platform)\$(Configuration)\$(xrIntDir)$(ProjectName)\
+
+ $(xrGameDir)bin_dbg\$(Platform)\$(Configuration)\
+ $(xrIntDir)$(ProjectName)\
+ $(xrGameDir)bin_dbg\$(Platform)\$(Configuration)\$(xrIntDir)$(ProjectName)\
@@ -218,6 +239,34 @@
false
+
+
+ X64
+
+
+ Disabled
+ false
+ Neither
+ ..\..\include;%(AdditionalIncludeDirectories)
+ _DISABLE_VECTOR_ANNOTATION;_DISABLE_STRING_ANNOTATION;USE_VERIFY_IN_RELEASE;WIN32;ANALYSIS;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)
+ NotSet
+
+
+ ProgramDatabase
+ 4244;4100;4267;4189;4305;4127;4706;%(DisableSpecificWarnings)
+ false
+ Level4
+ false
+ Disabled
+ false
+ CompileAsC
+ stdcpp17
+ true
+
+
+ false
+
+ X64
diff --git a/sdk/include/vorbis/libvorbisfile_static.vcxproj b/sdk/include/vorbis/libvorbisfile_static.vcxproj
index 48d879f505..2defbfa054 100644
--- a/sdk/include/vorbis/libvorbisfile_static.vcxproj
+++ b/sdk/include/vorbis/libvorbisfile_static.vcxproj
@@ -13,6 +13,10 @@
Releasex64
+
+ VerifiedDX11ASAN
+ x64
+ VerifiedDX11x64
@@ -53,6 +57,13 @@
Unicodex64
+
+ StaticLibrary
+ v143
+ Unicode
+ x64
+ true
+ StaticLibraryv143
@@ -82,6 +93,11 @@
+
+
+
+
+
@@ -107,6 +123,10 @@
$(xrGameDir)bin_dbg\$(Platform)\$(Configuration)\$(xrIntDir)$(ProjectName)\
+
+ $(xrGameDir)bin_dbg\$(Platform)\$(Configuration)\
+ $(xrIntDir)$(ProjectName)\
+ $(xrGameDir)bin_dbg\$(Platform)\$(Configuration)\$(xrIntDir)$(ProjectName)\
@@ -212,6 +232,31 @@
false
+
+
+ X64
+
+
+ ..\;%(AdditionalIncludeDirectories)
+ _DISABLE_VECTOR_ANNOTATION;_DISABLE_STRING_ANNOTATION;USE_VERIFY_IN_RELEASE;WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)
+ NotSet
+
+
+ ProgramDatabase
+ Disabled
+ Neither
+ Level3
+ false
+ Disabled
+ false
+ stdcpp17
+ true
+
+
+ $(OutDir)$(TargetName)$(TargetExt)
+ false
+
+ X64
diff --git a/src/3rd party/DXERR/DXERR.vcxproj b/src/3rd party/DXERR/DXERR.vcxproj
index 63237008b0..a32ea3ea61 100644
--- a/src/3rd party/DXERR/DXERR.vcxproj
+++ b/src/3rd party/DXERR/DXERR.vcxproj
@@ -13,6 +13,10 @@
Releasex64
+
+ VerifiedDX11ASAN
+ x64
+ VerifiedDX11x64
@@ -56,6 +60,15 @@
Unicodex64
+
+ StaticLibrary
+ false
+ v143
+ false
+ Unicode
+ x64
+ true
+ StaticLibraryv143
@@ -81,6 +94,10 @@
+
+
+
+
@@ -106,6 +123,11 @@
$(xrGameDir)bin_dbg\$(Platform)\$(Configuration)\$(xrIntDir)$(ProjectName)\
+
+ DxErr
+ $(xrGameDir)bin_dbg\$(Platform)\$(Configuration)\
+ $(xrIntDir)$(ProjectName)\
+ DxErr$(xrGameDir)bin_dbg\$(Platform)\$(Configuration)\
@@ -208,6 +230,32 @@
false
+
+
+ Disabled
+ false
+ NotSet
+ ProgramDatabase
+ false
+ _DISABLE_VECTOR_ANNOTATION;_DISABLE_STRING_ANNOTATION;USE_VERIFY_IN_RELEASE;_VC80_UPGRADE=0x0710;_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS;%(PreprocessorDefinitions)
+ Neither
+ Level3
+ false
+ true
+ Disabled
+ false
+ stdcpp17
+ true
+
+
+ true
+ true
+ true
+
+
+ false
+
+ AdvancedVectorExtensions
diff --git a/src/3rd party/NVTT/NVTT.vcxproj b/src/3rd party/NVTT/NVTT.vcxproj
index 9c68b2c5e5..183d0bdac9 100644
--- a/src/3rd party/NVTT/NVTT.vcxproj
+++ b/src/3rd party/NVTT/NVTT.vcxproj
@@ -13,6 +13,10 @@
Releasex64
+
+ VerifiedDX11ASAN
+ x64
+ VerifiedDX11x64
@@ -128,6 +132,8 @@
+
+
@@ -209,6 +215,15 @@
v143x64
+
+ StaticLibrary
+ false
+ true
+ MultiByte
+ v143
+ x64
+ true
+ StaticLibraryv143
@@ -234,6 +249,10 @@
+
+
+
+
@@ -255,6 +274,10 @@
$(xrGameDir)bin_dbg\$(Platform)\$(Configuration)\$(xrIntDir)$(ProjectName)\
+
+ $(xrGameDir)bin_dbg\$(Platform)\$(Configuration)\
+ $(xrIntDir)$(ProjectName)\
+ $(xrGameDir)bin_dbg\$(Platform)\$(Configuration)\$(xrIntDir)$(ProjectName)\
@@ -364,6 +387,34 @@
false
+
+
+ Disabled
+ false
+ include;src;src\nvcore;src\nvtt\squish;%(AdditionalIncludeDirectories)
+ _DISABLE_VECTOR_ANNOTATION;_DISABLE_STRING_ANNOTATION;USE_VERIFY_IN_RELEASE;WIN32;NDEBUG;_MBCS;%(PreprocessorDefinitions)
+ NotSet
+ Neither
+ false
+ false
+ 4005
+ ProgramDatabase
+ Level3
+ false
+ Disabled
+ false
+ stdcpp17
+ true
+
+
+ true
+ true
+ true
+
+
+ false
+
+ include;src;src\nvcore;src\nvtt\squish;%(AdditionalIncludeDirectories)
diff --git a/src/3rd party/OpenAL-new/OpenAL-new.vcxproj b/src/3rd party/OpenAL-new/OpenAL-new.vcxproj
index e43d573dc7..ca3507fb4f 100644
--- a/src/3rd party/OpenAL-new/OpenAL-new.vcxproj
+++ b/src/3rd party/OpenAL-new/OpenAL-new.vcxproj
@@ -13,6 +13,10 @@
Releasex64
+
+ VerifiedDX11ASAN
+ x64
+ VerifiedDX11x64
@@ -59,6 +63,15 @@
falsex64
+
+ StaticLibrary
+ v143
+ false
+ MultiByte
+ false
+ x64
+ true
+ StaticLibraryv143
@@ -81,6 +94,10 @@
+
+
+
+
@@ -101,9 +118,13 @@
$(ProjectName).lib$(xrGameDir)bin_dbg\$(Platform)\$(Configuration)\
+ $(xrGameDir)bin_dbg\$(Platform)\$(Configuration)\$(xrIntDir)$(ProjectName)\
+ $(xrIntDir)$(ProjectName)\$(ProjectName)
+ $(ProjectName).lib
+ .lib$(xrGameDir)bin_dbg\$(Platform)\$(Configuration)\$(xrIntDir)$(ProjectName)\$(ProjectName)
@@ -247,6 +268,51 @@
%(AdditionalOptions) /machine:x64
+
+
+ $(SolutionDir)3rd party\OpenAL-new\include;$(SolutionDir)3rd party\OpenAL-new;$(SolutionDir)3rd party\OpenAL-new\common;%(AdditionalIncludeDirectories)
+ %(AdditionalOptions) /w14640
+ $(IntDir)
+ Default
+ true
+ 4065;4127;4268;4324;5030;5051
+ false
+ Disabled
+ stdcpp17
+ false
+ Disabled
+ NotUsing
+ MultiThreadedDLL
+ false
+ false
+ Level4
+ _DISABLE_VECTOR_ANNOTATION;_DISABLE_STRING_ANNOTATION;%(PreprocessorDefinitions);USE_VERIFY_IN_RELEASE;WIN32;_WINDOWS;NDEBUG;AL_LIBTYPE_STATIC;AL_BUILD_LIBRARY;AL_ALEXT_PROTOTYPES;ALC_API=;AL_API=;_WIN32;NOMINMAX;RESTRICT=__restrict;_CRT_SECURE_NO_WARNINGS;_DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR;_DISABLE_VECTOR_ANNOTATION;_DISABLE_STRING_ANNOTATION
+ $(IntDir)
+ ProgramDatabase
+ false
+ false
+ false
+ false
+ false
+ true
+ Neither
+
+
+ %(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;AL_LIBTYPE_STATIC;AL_BUILD_LIBRARY;AL_ALEXT_PROTOTYPES;ALC_API=;AL_API=;_WIN32;NOMINMAX;RESTRICT=__restrict;_CRT_SECURE_NO_WARNINGS
+ $(SolutionDir)3rd party\OpenAL-new\include;$(SolutionDir)3rd party\OpenAL-new;$(SolutionDir)3rd party\OpenAL-new\common;%(AdditionalIncludeDirectories)
+
+
+ $(SolutionDir)3rd party\OpenAL-new\include;$(SolutionDir)3rd party\OpenAL-new;$(SolutionDir)3rd party\OpenAL-new\common;%(AdditionalIncludeDirectories)
+ $(ProjectDir)/$(IntDir)
+ %(Filename).h
+ %(Filename).tlb
+ %(Filename)_i.c
+ %(Filename)_p.c
+
+
+ %(AdditionalOptions) /machine:x64
+
+ $(SolutionDir)3rd party\OpenAL-new\include;$(SolutionDir)3rd party\OpenAL-new;$(SolutionDir)3rd party\OpenAL-new\common;%(AdditionalIncludeDirectories)
diff --git a/src/3rd party/crypto/crypto.vcxproj b/src/3rd party/crypto/crypto.vcxproj
index 5bbe3e0e99..b49af64d69 100644
--- a/src/3rd party/crypto/crypto.vcxproj
+++ b/src/3rd party/crypto/crypto.vcxproj
@@ -13,6 +13,10 @@
Releasex64
+
+ VerifiedDX11ASAN
+ x64
+ VerifiedDX11x64
@@ -54,6 +58,14 @@
falsex64
+
+ StaticLibrary
+ v143
+ MultiByte
+ false
+ x64
+ true
+ StaticLibraryv143
@@ -79,6 +91,10 @@
+
+
+
+
@@ -111,6 +127,12 @@
$(xrGameDir)bin_dbg\$(Platform)\$(Configuration)\$(xrIntDir)$(ProjectName)\
+
+ $(ProjectName)
+ .lib
+ $(xrGameDir)bin_dbg\$(Platform)\$(Configuration)\
+ $(xrIntDir)$(ProjectName)\
+ $(ProjectName).lib
@@ -215,6 +237,31 @@
Default
+
+
+ openssl;$(xrSdkDir)include;$(SolutionDir)include;%(AdditionalIncludeDirectories)
+ _DISABLE_VECTOR_ANNOTATION;_DISABLE_STRING_ANNOTATION;USE_VERIFY_IN_RELEASE;CRYPTO_BUILD;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+ ProgramDatabase
+ NotSet
+ false
+ Neither
+ false
+ 4005;4996
+ Disabled
+ false
+ Level4
+ false
+ Disabled
+ false
+ stdcpp17
+ true
+
+
+ $(xrLibDir)$(TargetName).lib
+ true
+ Default
+
+ openssl;$(xrSdkDir)include;$(SolutionDir)include;%(AdditionalIncludeDirectories)
diff --git a/src/3rd party/crypto/xr_dsa.cpp b/src/3rd party/crypto/xr_dsa.cpp
index c38ad66006..48b4316f4e 100644
--- a/src/3rd party/crypto/xr_dsa.cpp
+++ b/src/3rd party/crypto/xr_dsa.cpp
@@ -1,6 +1,7 @@
#include "xr_dsa.h"
#include "crypto.h"
#include
+#include "../xrCore/profiler.h"
namespace crypto
{
@@ -30,6 +31,7 @@ shared_str const xr_dsa::sign (private_key_t const & priv_key,
u8 const* data,
u32 const data_size)
{
+ PROF_EVENT("crypto::xr_dsa::sign");
BN_bin2bn(priv_key.m_value, sizeof(priv_key.m_value), m_dsa->priv_key);
unsigned int sign_size = DSA_size(m_dsa);
@@ -185,4 +187,4 @@ void xr_dsa::generate_params()
#endif //#ifdef DEBUG
-} //namespace crypto
\ No newline at end of file
+} //namespace crypto
diff --git a/src/3rd party/cximage/cximage.vcxproj b/src/3rd party/cximage/cximage.vcxproj
index 592b7ebebb..634986ce98 100644
--- a/src/3rd party/cximage/cximage.vcxproj
+++ b/src/3rd party/cximage/cximage.vcxproj
@@ -13,6 +13,10 @@
Releasex64
+
+ VerifiedDX11ASAN
+ x64
+ VerifiedDX11x64
@@ -59,6 +63,16 @@
falsex64
+
+ StaticLibrary
+ v143
+ false
+ MultiByte
+ false
+ false
+ x64
+ true
+ StaticLibraryv143
@@ -88,6 +102,11 @@
+
+
+
+
+
@@ -125,6 +144,13 @@
$(xrGameDir)bin_dbg\$(Platform)\$(Configuration)\$(xrIntDir)$(ProjectName)\
+
+ $(ProjectName)
+ .lib
+ $(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86)
+ $(xrGameDir)bin_dbg\$(Platform)\$(Configuration)\
+ $(xrIntDir)$(ProjectName)\
+ $(ProjectName).lib
@@ -286,6 +312,47 @@
$(xrLibDir)$(TargetName).lib
+
+
+ Disabled
+ false
+ Neither
+ false
+ $(XRAY_16X_LIBS);$(SolutionDir);%(AdditionalIncludeDirectories)
+ _DISABLE_VECTOR_ANNOTATION;_DISABLE_STRING_ANNOTATION;USE_VERIFY_IN_RELEASE;WIN32;NDEBUG;_LIB;JAS_WIN_MSVC_BUILD;CXIMAGE_BUILD;%(PreprocessorDefinitions)
+ NotSet
+ 4995;4100;4702;%(DisableSpecificWarnings)
+ ProgramDatabase
+ false
+ Level4
+ false
+ Disabled
+ false
+ stdcpp17
+ true
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+ 0x0809
+
+
+ /ignore:4075 %(AdditionalOptions)
+ $(OutDir)$(ProjectName).lib
+ $(XRAY_16X_LIBS)\jpeg\libraries\Release;$(xrLibDir);%(AdditionalLibraryDirectories)
+ true
+ true
+ false
+
+
+ true
+ .\Release/cximage.bsc
+
+
+
+ $(XRAY_16X_LIBS)\jpeg-8c\Release\;$(xrLibDir);%(AdditionalLibraryDirectories)
+ $(xrLibDir)$(TargetName).lib
+
+ $(XRAY_16X_LIBS);$(SolutionDir);%(AdditionalIncludeDirectories)
diff --git a/src/3rd party/fastdelegate/fastdelegate.h b/src/3rd party/fastdelegate/fastdelegate.h
index aa722586c7..fdb443d436 100644
--- a/src/3rd party/fastdelegate/fastdelegate.h
+++ b/src/3rd party/fastdelegate/fastdelegate.h
@@ -1,71 +1,78 @@
-// FastDelegate.h
-// Efficient delegates in C++ that generate only two lines of asm code!
+// FastDelegate.hpp
+// 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.
+// - Don Clugston, Mar 2004.
+// Major contributions were made by Jody Hagins.
+// Version 2.0 by Pa�l Jim�nez.
+// Version 2.0.1 by Benjamin YanXiang Huang
+//
// History:
-// 24-Apr-04 1.0 * Submitted to CodeProject.
+// 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()
+// * 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++
+// * 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.
+// * 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) >.
+// * 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.
+// * 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
+// * 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
+// 06-Feb-13 2.0 * GetMemento is now const
+// * Added hash method that makes use of new unchecked function unsafe_horrible_cast
+// * Removed VC6 code
+// * Use variadic templates (C++11)
+// * Added MakeDelegate for plain function pointers
+// * Use static_assert for compile-time checks (C++11)
+// 21-Jan-14 2.0.1* Fixed 2 typos (line 393 & 429) where a static_cast should have been a static_assert.
+// 21-Jun-14 2.0.2* Fixed incorrect union member name in the SimplifyMemFunc struct.
+
+#ifndef FASTDELEGATE_HPP
+#define FASTDELEGATE_HPP
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
-#include // to allow <,> comparisons
-
-//////////////////////////////////////////////////
-#define xr_stdcall __stdcall
-///////////////////////////////////////////////////
+#include // to allow <,> comparisons
////////////////////////////////////////////////////////////////////////////////
-// Configuration options
+// 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).
+// 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
@@ -75,7 +82,7 @@
//#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
////////////////////////////////////////////////////////////////////////////////
-// Compiler identification for workarounds
+// Compiler identification for workarounds
//
////////////////////////////////////////////////////////////////////////////////
@@ -83,17 +90,11 @@
// 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
+// 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
@@ -119,2859 +120,858 @@
#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
#endif
-#ifdef __GNUC__ // Workaround GCC bug #8271
- // At present, GCC doesn't recognize constness of MFPs in templates
+#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
+// 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.
+// 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
+// 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
- 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
- union horrible_union
- {
- OutputClass out;
- InputClass in;
- };
-
- template
- inline OutputClass horrible_cast(const InputClass input)
- {
- horrible_union 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.
+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
+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
+union horrible_union{
+ OutputClass out;
+ InputClass in;
+};
+
+template
+inline OutputClass horrible_cast(const InputClass input){
+ horrible_union 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.
+ static_assert(sizeof(InputClass)==sizeof(u) && sizeof(InputClass)==sizeof(OutputClass), "Cannot use horrible_cast<>");
+ u.in = input;
+ return u.out;
+}
+
+template
+inline OutputClass unsafe_horrible_cast(const InputClass input){
+ horrible_union u;
+ 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 workaround
-typedef const void * DefaultVoid;
-#else
- // On any other compiler, just use a normal void.
- typedef void DefaultVoid;
-#endif
+typedef void DefaultVoid;
+
+// Translate from 'DefaultVoid' to 'void'.
+// Everything else is unchanged
+template
+struct DefaultVoidToVoid { typedef T type; };
+
+template <>
+struct DefaultVoidToVoid { typedef void type; };
+
+// Translate from 'void' into 'DefaultVoid'
+// Everything else is unchanged
+template
+struct VoidToDefaultVoid { typedef T type; };
+
+template <>
+struct VoidToDefaultVoid { typedef DefaultVoid type; };
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Fast Delegates, part 1:
+//
+// Conversion of member function pointer to a standard form
+//
+////////////////////////////////////////////////////////////////////////////////
- // Translate from 'DefaultVoid' to 'void'.
- // Everything else is unchanged
- template
- struct DefaultVoidToVoid
- {
- typedef T type;
- };
-
- template <>
- struct DefaultVoidToVoid
- {
- typedef void type;
- };
-
- // Translate from 'void' into 'DefaultVoid'
- // Everything else is unchanged
- template
- struct VoidToDefaultVoid
- {
- typedef T type;
- };
-
- template <>
- struct VoidToDefaultVoid
- {
- 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.
+// 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;
+ // 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
- {
- };
+ // ...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;
+ class GenericClass;
#endif
- // The size of a single inheritance member function pointer.
- const int SINGLE_MEMFUNCPTR_SIZE = sizeof(void (xr_stdcall 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
- // to distinguish between the sizes. Because some compilers don't support partial
- // template specialisation, I use full specialisation of a wrapper struct.
-
- // general case -- don't know how to convert it. Force a compile failure
- template
- struct SimplifyMemFunc
- {
- template
- inline static GenericClass* xr_stdcall Convert(X* pthis, XFuncType function_to_bind,
- GenericMemFuncType& bound_func)
- {
- // Unsupported member function type -- force a compile failure.
- // (it's illegal to have a array with negative size).
- typedef char ERROR_Unsupported_member_function_pointer_on_this_compiler[N - 100];
- return 0;
- }
- };
-
- // For compilers where all member func ptrs are the same size, everything goes here.
- // For non-standard compilers, only single_inheritance classes go here.
- template <>
- struct SimplifyMemFunc
- {
- template
- inline static GenericClass* xr_stdcall Convert(X* pthis, XFuncType function_to_bind,
- GenericMemFuncType& bound_func)
- {
+// 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
+// to distinguish between the sizes. Because some compilers don't support partial
+// template specialisation, I use full specialisation of a wrapper struct.
+
+// general case -- don't know how to convert it. Force a compile failure
+template
+struct SimplifyMemFunc {
+ template
+ inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind,
+ GenericMemFuncType &bound_func) {
+ // Unsupported member function type -- force a compile failure.
+ // (it's illegal to have a array with negative size).
+ static_assert(N - 100, "Unsupported member function pointer on this compiler");
+ return 0;
+ }
+};
+
+// For compilers where all member func ptrs are the same size, everything goes here.
+// For non-standard compilers, only single_inheritance classes go here.
+template <>
+struct SimplifyMemFunc {
+ template
+ inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind,
+ GenericMemFuncType &bound_func) {
#if defined __DMC__
- // Digital Mars doesn't allow you to cast between abitrary PMF's,
- // even though the standard says you can. The 32-bit compiler lets you
- // static_cast through an int, but the DOS compiler doesn't.
- bound_func = horrible_cast(function_to_bind);
+ // Digital Mars doesn't allow you to cast between abitrary PMF's,
+ // even though the standard says you can. The 32-bit compiler lets you
+ // static_cast through an int, but the DOS compiler doesn't.
+ bound_func = horrible_cast(function_to_bind);
#else
- bound_func = reinterpret_cast(function_to_bind);
+ bound_func = reinterpret_cast(function_to_bind);
#endif
- return reinterpret_cast(pthis);
- }
- };
+ return reinterpret_cast(pthis);
+ }
+};
- ////////////////////////////////////////////////////////////////////////////////
- // Fast Delegates, part 1b:
- //
- // Workarounds for Microsoft and Intel
- //
- ////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+// Fast Delegates, part 1b:
+//
+// Workarounds for Microsoft and Intel
+//
+////////////////////////////////////////////////////////////////////////////////
- // Compilers with member function pointers which violate the standard (MSVC, Intel, Codeplay),
- // need to be treated as a special case.
+// Compilers with member function pointers which violate the standard (MSVC, Intel, Codeplay),
+// need to be treated as a special case.
#ifdef FASTDLGT_MICROSOFT_MFP
- // We use unions to perform horrible_casts. I would like to use #pragma pack(push, 1)
- // at the start of each function for extra safety, but VC6 seems to ICE
- // intermittently if you do this inside a template.
-
- // __multiple_inheritance classes go here
- // Nasty hack for Microsoft and Intel (IA32 and Itanium)
- template <>
- struct SimplifyMemFunc
- {
- template
- inline static GenericClass* xr_stdcall Convert(X* pthis, XFuncType function_to_bind,
- GenericMemFuncType& bound_func)
- {
- // We need to use a horrible_cast to do this conversion.
- // In MSVC, a multiple inheritance member pointer is internally defined as:
- union
- {
- XFuncType func;
-
- struct
- {
- GenericMemFuncType funcaddress; // points to the actual member function
- int delta; // #BYTES to be added to the 'this' pointer
- } s;
- } u;
- // Check that the horrible_cast will work
- typedef int ERROR_CantUsehorrible_cast[sizeof(function_to_bind) == sizeof(u.s) ? 1 : -1];
- u.func = function_to_bind;
- bound_func = u.s.funcaddress;
- return reinterpret_cast(reinterpret_cast(pthis) + u.s.delta);
- }
- };
-
- // virtual inheritance is a real nuisance. It's inefficient and complicated.
- // On MSVC and Intel, there isn't enough information in the pointer itself to
- // enable conversion to a closure pointer. Earlier versions of this code didn't
- // work for all cases, and generated a compile-time error instead.
- // But a very clever hack invented by John M. Dlugosz solves this problem.
- // My code is somewhat different to his: I have no asm code, and I make no
- // assumptions about the calling convention that is used.
-
- // In VC++ and ICL, a virtual_inheritance member pointer
- // is internally defined as:
- 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
- };
-
- // The CRUCIAL feature of Microsoft/Intel MFPs which we exploit is that the
- // m_codeptr member is *always* called, regardless of the values of the other
- // members. (This is *not* true for other compilers, eg GCC, which obtain the
- // function address from the vtable if a virtual function is being called).
- // Dlugosz's trick is to make the codeptr point to a probe function which
- // returns the 'this' pointer that was used.
-
- // Define a generic class that uses virtual inheritance.
- // It has a trival member function that returns the value of the 'this' pointer.
- struct GenericVirtualClass : virtual public GenericClass
- {
- typedef GenericVirtualClass* (GenericVirtualClass::*ProbePtrType)();
- GenericVirtualClass* GetThis() { return this; }
- };
-
- // __virtual_inheritance classes go here
- template <>
- struct SimplifyMemFunc
- {
- template
- inline static GenericClass* xr_stdcall Convert(X* pthis, XFuncType function_to_bind,
- GenericMemFuncType& bound_func)
- {
-#pragma pack(push)
-#pragma pack(1)
- union
- {
- XFuncType func;
- GenericClass* (X::*ProbeFunc)();
- MicrosoftVirtualMFP s;
- } u;
-#pragma pack(pop)
-
- u.func = function_to_bind;
- bound_func = reinterpret_cast(u.s.codeptr);
- union
- {
- GenericVirtualClass::ProbePtrType virtfunc;
- MicrosoftVirtualMFP s;
- } u2;
- // Check that the horrible_cast<>s will work
- typedef int ERROR_CantUsehorrible_cast[sizeof(function_to_bind) == sizeof(u.s)
- && sizeof(function_to_bind) == 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;
- return (pthis->*u.ProbeFunc)();
- }
- };
-
-#if (_MSC_VER <1300)
-
- // Nasty hack for Microsoft Visual C++ 6.0
- // unknown_inheritance classes go here
-// There is a compiler bug in MSVC6 which generates incorrect code in this case!!
+// We use unions to perform horrible_casts. I would like to use #pragma pack(push, 1)
+// at the start of each function for extra safety, but VC6 seems to ICE
+// intermittently if you do this inside a template.
+
+// __multiple_inheritance classes go here
+// Nasty hack for Microsoft and Intel (IA32 and Itanium)
+template<>
+struct SimplifyMemFunc< SINGLE_MEMFUNCPTR_SIZE + sizeof(int) > {
+ template
+ inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind,
+ GenericMemFuncType &bound_func) {
+ // We need to use a horrible_cast to do this conversion.
+ // In MSVC, a multiple inheritance member pointer is internally defined as:
+ union {
+ XFuncType func;
+ struct {
+ GenericMemFuncType funcaddress; // points to the actual member function
+ int delta; // #BYTES to be added to the 'this' pointer
+ }s;
+ } u;
+ // Check that the horrible_cast will work
+ static_assert(sizeof(function_to_bind)==sizeof(u.s), "Cannot use horrible_cast<>");
+ u.func = function_to_bind;
+ bound_func = u.s.funcaddress;
+ return reinterpret_cast(reinterpret_cast(pthis) + u.s.delta);
+ }
+};
+
+// virtual inheritance is a real nuisance. It's inefficient and complicated.
+// On MSVC and Intel, there isn't enough information in the pointer itself to
+// enable conversion to a closure pointer. Earlier versions of this code didn't
+// work for all cases, and generated a compile-time error instead.
+// But a very clever hack invented by John M. Dlugosz solves this problem.
+// My code is somewhat different to his: I have no asm code, and I make no
+// assumptions about the calling convention that is used.
+
+// In VC++ and ICL, a virtual_inheritance member pointer
+// is internally defined as:
+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
+};
+// The CRUCIAL feature of Microsoft/Intel MFPs which we exploit is that the
+// m_codeptr member is *always* called, regardless of the values of the other
+// members. (This is *not* true for other compilers, eg GCC, which obtain the
+// function address from the vtable if a virtual function is being called).
+// Dlugosz's trick is to make the codeptr point to a probe function which
+// returns the 'this' pointer that was used.
+
+// Define a generic class that uses virtual inheritance.
+// It has a trival member function that returns the value of the 'this' pointer.
+struct GenericVirtualClass : virtual public GenericClass
+{
+ typedef GenericVirtualClass * (GenericVirtualClass::*ProbePtrType)();
+ GenericVirtualClass * GetThis() { return this; }
+};
+
+// __virtual_inheritance classes go here
+template <>
+struct SimplifyMemFunc
+{
+
+ template
+ inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind,
+ GenericMemFuncType &bound_func) {
+ union {
+ XFuncType func;
+ GenericClass* (X::*ProbeFunc)();
+ MicrosoftVirtualMFP s;
+ } u;
+ u.func = function_to_bind;
+ bound_func = reinterpret_cast(u.s.codeptr);
+ union {
+ GenericVirtualClass::ProbePtrType virtfunc;
+ MicrosoftVirtualMFP s;
+ } u2;
+ // Check that the horrible_cast<>s will work
+ static_assert(sizeof(function_to_bind)==sizeof(u.s) && sizeof(function_to_bind)==sizeof(u.ProbeFunc) && sizeof(u2.virtfunc)==sizeof(u2.s), "Cannot use horrible_cast<>");
+ /*typedef int ERROR_CantUsehorrible_cast[sizeof(function_to_bind)==sizeof(u.s)
+ && sizeof(function_to_bind)==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;
+ return (pthis->*u.ProbeFunc)();
+ }
+};
+
+// 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 SimplifyMemFunc
{
- template
- inline static GenericClass * xr_stdcall Convert(X *pthis, XFuncType function_to_bind,
- GenericMemFuncType &bound_func) {
- // There is an apalling but obscure compiler bug in MSVC6 and earlier:
- // vtable_index and 'vtordisp' are always set to 0 in the
- // unknown_inheritance case!
- // This means that an incorrect function could be called!!!
- // Compiling with the /vmg option leads to potentially incorrect code.
- // This is probably the reason that the IDE has a user interface for specifying
- // the /vmg option, but it is disabled - you can only specify /vmg on
- // the command line. In VC1.5 and earlier, the compiler would ICE if it ever
- // encountered this situation.
- // It is OK to use the /vmg option if /vmm or /vms is specified.
-
- // Fortunately, the wrong function is only called in very obscure cases.
- // It only occurs when a derived class overrides a virtual function declared
- // in a virtual base class, and the member function
- // points to the *Derived* version of that function. The problem can be
- // completely averted in 100% of cases by using the *Base class* for the
- // member fpointer. Ie, if you use the base class as an interface, you'll
- // stay out of trouble.
- // Occasionally, you might want to point directly to a derived class function
- // that isn't an override of a base class. In this case, both vtable_index
- // and 'vtordisp' are zero, but a virtual_inheritance pointer will be generated.
- // We can generate correct code in this case. To prevent an incorrect call from
- // ever being made, on MSVC6 we generate a warning, and call a function to
- // make the program crash instantly.
- typedef char ERROR_VC6CompilerBug[-100];
- return 0;
- }
+ template
+ inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind,
+ GenericMemFuncType &bound_func) {
+ // 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 {
+ XFuncType func;
+ // In VC++ and ICL, an unknown_inheritance member pointer
+ // is internally defined as:
+ struct {
+ GenericMemFuncType 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
+ static_assert(sizeof(XFuncType)==sizeof(u.s), "Cannot use horrible_cast<>");
+ //typedef int ERROR_CantUsehorrible_cast[sizeof(XFuncType)==sizeof(u.s)? 1 : -1];
+ u.func = function_to_bind;
+ bound_func = u.s.funcaddress;
+ 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.
+ const int * vtable = *reinterpret_cast(
+ reinterpret_cast(pthis) + 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!
+ return reinterpret_cast(
+ reinterpret_cast(pthis) + u.s.delta + virtual_delta);
+ };
};
+#endif // MS/Intel hacks
-#else
+} // namespace detail
- // 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 SimplifyMemFunc
- {
- template
- inline static GenericClass* xr_stdcall Convert(X* pthis, XFuncType function_to_bind,
- GenericMemFuncType& bound_func)
- {
- // 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
- {
- XFuncType func;
-
- // In VC++ and ICL, an unknown_inheritance member pointer
- // is internally defined as:
- struct
- {
- GenericMemFuncType 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(XFuncType) == sizeof(u.s) ? 1 : -1];
- u.func = function_to_bind;
- bound_func = u.s.funcaddress;
- 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.
- const int* vtable = *reinterpret_cast(
- reinterpret_cast(pthis) + 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!
- return reinterpret_cast(
- reinterpret_cast(pthis) + u.s.delta + virtual_delta);
- };
- };
-#endif // MSVC 7 and greater
+////////////////////////////////////////////////////////////////////////////////
+// Fast Delegates, part 2:
+//
+// Define the delegate storage, and cope with static functions
+//
+////////////////////////////////////////////////////////////////////////////////
-#endif // MS/Intel hacks
- } // namespace detail
-
- ////////////////////////////////////////////////////////////////////////////////
- // Fast Delegates, part 2:
- //
- // Define the delegate storage, and cope with static functions
- //
- ////////////////////////////////////////////////////////////////////////////////
-
- // DelegateMemento -- an opaque structure which can hold an arbitary delegate.
- // It knows nothing about the calling convention or number of arguments used by
- // the function pointed to.
- // It supplies comparison operators so that it can be stored in STL collections.
- // It cannot be set to anything other than null, nor invoked directly:
- // it must be converted to a specific delegate.
-
- // Implementation:
- // There are two possible implementations: the Safe method and the Evil method.
- // DelegateMemento - Safe version
- //
- // This implementation is standard-compliant, but a bit tricky.
- // A static function pointer is stored inside the class.
- // Here are the valid values:
- // +-- Static pointer --+--pThis --+-- pMemFunc-+-- Meaning------+
- // | 0 | 0 | 0 | Empty |
- // | !=0 |(dontcare)| Invoker | Static function|
- // | 0 | !=0 | !=0* | Method call |
- // +--------------------+----------+------------+----------------+
- // * For Metrowerks, this can be 0. (first virtual function in a
- // single_inheritance class).
- // When stored stored inside a specific delegate, the 'dontcare' entries are replaced
- // with a reference to the delegate itself. This complicates the = and == operators
- // for the delegate class.
-
- // DelegateMemento - 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. In this case the DelegateMemento implementation is simple:
- // +--pThis --+-- pMemFunc-+-- Meaning---------------------+
- // | 0 | 0 | Empty |
- // | !=0 | !=0* | Static function or method call|
- // +----------+------------+-------------------------------+
- // * For Metrowerks, this can be 0. (first virtual function in a
- // single_inheritance class).
- // Note that the Sun C++ and MSVC documentation explicitly state that they
- // support static_cast between void * and function pointers.
-
- class DelegateMemento
- {
- protected:
- // 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;
+// DelegateMemento -- an opaque structure which can hold an arbitary delegate.
+// It knows nothing about the calling convention or number of arguments used by
+// the function pointed to.
+// It supplies comparison operators so that it can be stored in STL collections.
+// It cannot be set to anything other than null, nor invoked directly:
+// it must be converted to a specific delegate.
+
+// Implementation:
+// There are two possible implementations: the Safe method and the Evil method.
+// DelegateMemento - Safe version
+//
+// This implementation is standard-compliant, but a bit tricky.
+// A static function pointer is stored inside the class.
+// Here are the valid values:
+// +-- Static pointer --+--pThis --+-- pMemFunc-+-- Meaning------+
+// | 0 | 0 | 0 | Empty |
+// | !=0 |(dontcare)| Invoker | Static function|
+// | 0 | !=0 | !=0* | Method call |
+// +--------------------+----------+------------+----------------+
+// * For Metrowerks, this can be 0. (first virtual function in a
+// single_inheritance class).
+// When stored stored inside a specific delegate, the 'dontcare' entries are replaced
+// with a reference to the delegate itself. This complicates the = and == operators
+// for the delegate class.
+
+// DelegateMemento - 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. In this case the DelegateMemento implementation is simple:
+// +--pThis --+-- pMemFunc-+-- Meaning---------------------+
+// | 0 | 0 | Empty |
+// | !=0 | !=0* | Static function or method call|
+// +----------+------------+-------------------------------+
+// * For Metrowerks, this can be 0. (first virtual function in a
+// single_inheritance class).
+// Note that the Sun C++ and MSVC documentation explicitly state that they
+// support static_cast between void * and function pointers.
+
+class DelegateMemento {
+protected:
+ // 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 (xr_stdcall *GenericFuncPtr)(); // arbitrary code pointer
- GenericFuncPtr m_pStaticFunction;
+ typedef void (*GenericFuncPtr)(); // arbitrary code pointer
+ GenericFuncPtr m_pStaticFunction;
#endif
- public:
+public:
#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;
- }
+ 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;
- }
+ DelegateMemento() : m_pthis(0), m_pFunction(0) {};
+ void clear() { m_pthis=0; m_pFunction=0; }
#endif
- public:
+public:
#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;
- }
+ 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;
- }
+ 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
+ // 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;
+ 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 (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 std::memcmp(&m_pFunction, &right.m_pFunction, sizeof(m_pFunction)) < 0;
+
+ }
+ // Provide a simple hashing method.
+ inline size_t Hash() const {
+ return reinterpret_cast(m_pthis) ^ detail::unsafe_horrible_cast(m_pFunction);
+ }
+ // 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_pthis(right.m_pthis), m_pFunction(right.m_pFunction)
#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
- , m_pStaticFunction (right.m_pStaticFunction)
+ , m_pStaticFunction (right.m_pStaticFunction)
#endif
- {
- }
-
- protected:
- void SetMementoFrom(const DelegateMemento& right)
- {
- m_pFunction = right.m_pFunction;
- m_pthis = right.m_pthis;
+ {}
+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;
+ 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 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
- inline void bindmemfunc(X* pthis, XMemFunc function_to_bind)
- {
- m_pthis = SimplifyMemFunc
- ::Convert(pthis, function_to_bind, m_pFunction);
+ }
+};
+
+
+// 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;
+ 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
- inline void bindconstmemfunc(const X* pthis, XMemFunc function_to_bind)
- {
- m_pthis = SimplifyMemFunc
- ::Convert(const_cast(pthis), function_to_bind, m_pFunction);
+ }
+ // 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(pthis), function_to_bind, m_pFunction);
#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
- m_pStaticFunction = 0;
+ 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);
+ }
+#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;
+ 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(m_pFunction); }
+ // These functions are required for invoking the stored function
+ inline GenericClass *GetClosureThis() const { return m_pthis; }
+ inline GenericMemFunc GetClosureMemPtr() const { return reinterpret_cast(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.
+// 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
+// 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(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);
+ // 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(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(function_to_bind);
- }
- inline UnvoidStaticFuncPtr GetStaticFunction() const {
- return reinterpret_cast(m_pStaticFunction);
- }
+ m_pStaticFunction=reinterpret_cast(function_to_bind);
+ }
+ inline UnvoidStaticFuncPtr GetStaticFunction() const {
+ return reinterpret_cast(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
- 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
- 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(function_to_bind);
- // MSVC, SunC++ and DMC accept the following (non-standard) code:
- // m_pthis = static_cast(static_cast(function_to_bind));
- // BCC32, Comeau and DMC accept this method. MSVC7.1 needs __int64 instead of long
- // m_pthis = reinterpret_cast(reinterpret_cast(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(this);
- }
+// 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.
+ static_assert(sizeof(GenericClass *)==sizeof(function_to_bind), "Cannot use evil method");
+ m_pthis = horrible_cast(function_to_bind);
+ // MSVC, SunC++ and DMC accept the following (non-standard) code:
+// m_pthis = static_cast(static_cast(function_to_bind));
+ // BCC32, Comeau and DMC accept this method. MSVC7.1 needs __int64 instead of long
+// m_pthis = reinterpret_cast(reinterpret_cast(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.
+ static_assert(sizeof(UnvoidStaticFuncPtr)==sizeof(this), "Cannot use evil method");
+ return horrible_cast(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(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
- // 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(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(&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.
-
- // Implicit conversion to "bool" is achieved using the safe_bool idiom,
- // using member data pointers (MDP). This allows "if (dg)..." syntax
- // Because some compilers (eg codeplay) don't have a unique value for a zero
- // MDP, an extra padding member is added to the SafeBool struct.
- // Some compilers (eg VC6) won't implicitly convert from 0 to an MDP, so
- // in that case the static function constructor is not made explicit; this
- // allows "if (dg==0) ..." to compile.
-
- //N=0
- template
- class FastDelegate0
- {
- private:
- typedef typename detail::DefaultVoidToVoid::type DesiredRetType;
- typedef DesiredRetType (xr_stdcall *StaticFunctionPtr)();
- typedef RetType (xr_stdcall *UnvoidStaticFunctionPtr)();
- typedef RetType (xr_stdcall detail::GenericClass::*GenericMemFn)();
- typedef detail::ClosurePtr ClosureType;
- ClosureType m_Closure;
- public:
- // Typedefs to aid generic programming
- typedef FastDelegate0 type;
-
- // Construction and comparison functions
- FastDelegate0() { clear(); }
-
- FastDelegate0(const FastDelegate0& x)
- {
- m_Closure.CopyFrom(this, x.m_Closure);
- }
-
- void operator =(const FastDelegate0& x)
- {
- m_Closure.CopyFrom(this, x.m_Closure);
- }
-
- bool operator ==(const FastDelegate0& x) const
- {
- return m_Closure.IsEqual(x.m_Closure);
- }
-
- bool operator !=(const FastDelegate0& x) const
- {
- return !m_Closure.IsEqual(x.m_Closure);
- }
-
- bool operator <(const FastDelegate0& x) const
- {
- return m_Closure.IsLess(x.m_Closure);
- }
-
- bool operator >(const FastDelegate0& x) const
- {
- return x.m_Closure.IsLess(m_Closure);
- }
-
- // Binding to non-const member functions
- template
- FastDelegate0(Y* pthis, DesiredRetType (xr_stdcall X::* function_to_bind)())
- {
- m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind);
- }
-
- template
- inline void bind(Y* pthis, DesiredRetType (xr_stdcall X::* function_to_bind)())
- {
- m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind);
- }
-
- // Binding to const member functions.
- template
- FastDelegate0(const Y* pthis, DesiredRetType (xr_stdcall X::* function_to_bind)() const)
- {
- m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind);
- }
-
- template
- inline void bind(const Y* pthis, DesiredRetType (xr_stdcall X::* function_to_bind)() const)
- {
- m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind);
- }
-
- // Static functions. We convert them into a member function call.
- // This constructor also provides implicit conversion
- FastDelegate0(DesiredRetType (xr_stdcall *function_to_bind)())
- {
- bind(function_to_bind);
- }
-
- // for efficiency, prevent creation of a temporary
- void operator =(DesiredRetType (xr_stdcall *function_to_bind)())
- {
- bind(function_to_bind);
- }
-
- inline void bind(DesiredRetType (xr_stdcall *function_to_bind)())
- {
- m_Closure.bindstaticfunc(this, &FastDelegate0::InvokeStaticFunction,
- function_to_bind);
- }
-
- // Invoke the delegate
- RetType operator()() const
- {
- return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))();
- }
-
- // Implicit conversion to "bool" using the safe_bool idiom
- private:
- typedef struct SafeBoolStruct
- {
- int a_data_pointer_to_this_is_0_on_buggy_compilers;
- StaticFunctionPtr m_nonzero;
- } UselessTypedef;
-
- typedef StaticFunctionPtr SafeBoolStruct::* unspecified_bool_type;
- public:
- operator unspecified_bool_type() const
- {
- return empty() ? 0 : &SafeBoolStruct::m_nonzero;
- }
-
- // necessary to allow ==0 to work despite the safe_bool idiom
- inline bool operator==(StaticFunctionPtr funcptr)
- {
- return m_Closure.IsEqualToStaticFuncPtr(funcptr);
- }
-
- inline bool operator!=(StaticFunctionPtr funcptr)
- {
- return !m_Closure.IsEqualToStaticFuncPtr(funcptr);
- }
-
- inline bool operator !() const
- {
- // Is it bound to anything?
- return !m_Closure;
- }
-
- inline bool empty() const
- {
- return !m_Closure;
- }
-
- void clear() { m_Closure.clear(); }
- // Conversion to and from the DelegateMemento storage class
- const DelegateMemento& GetMemento() { return m_Closure; }
- void SetMemento(const DelegateMemento& any) { m_Closure.CopyFrom(this, any); }
-
- private: // Invoker for static functions
- RetType xr_stdcall InvokeStaticFunction() const
- {
- return (*(m_Closure.GetStaticFunction()))();
- }
- };
-
- //N=1
- template
- class FastDelegate1
- {
- private:
- typedef typename detail::DefaultVoidToVoid::type DesiredRetType;
- typedef DesiredRetType (xr_stdcall *StaticFunctionPtr)(Param1 p1);
- typedef RetType (xr_stdcall *UnvoidStaticFunctionPtr)(Param1 p1);
- typedef RetType (xr_stdcall detail::GenericClass::*GenericMemFn)(Param1 p1);
- typedef detail::ClosurePtr ClosureType;
- ClosureType m_Closure;
- public:
- // Typedefs to aid generic programming
- typedef FastDelegate1 type;
-
- // Construction and comparison functions
- FastDelegate1() { clear(); }
-
- FastDelegate1(const FastDelegate1& x)
- {
- m_Closure.CopyFrom(this, x.m_Closure);
- }
-
- void operator =(const FastDelegate1& x)
- {
- m_Closure.CopyFrom(this, x.m_Closure);
- }
-
- bool operator ==(const FastDelegate1& x) const
- {
- return m_Closure.IsEqual(x.m_Closure);
- }
-
- bool operator !=(const FastDelegate1& x) const
- {
- return !m_Closure.IsEqual(x.m_Closure);
- }
-
- bool operator <(const FastDelegate1& x) const
- {
- return m_Closure.IsLess(x.m_Closure);
- }
-
- bool operator >(const FastDelegate1& x) const
- {
- return x.m_Closure.IsLess(m_Closure);
- }
-
- // Binding to non-const member functions
- template
- FastDelegate1(Y* pthis, DesiredRetType (xr_stdcall X::* function_to_bind)(Param1 p1))
- {
- m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind);
- }
-
- template
- inline void bind(Y* pthis, DesiredRetType (xr_stdcall X::* function_to_bind)(Param1 p1))
- {
- m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind);
- }
-
- // Binding to const member functions.
- template
- FastDelegate1(const Y* pthis, DesiredRetType (xr_stdcall X::* function_to_bind)(Param1 p1) const)
- {
- m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind);
- }
-
- template
- inline void bind(const Y* pthis, DesiredRetType (xr_stdcall X::* function_to_bind)(Param1 p1) const)
- {
- m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind);
- }
-
- // Static functions. We convert them into a member function call.
- // This constructor also provides implicit conversion
- FastDelegate1(DesiredRetType (xr_stdcall *function_to_bind)(Param1 p1))
- {
- bind(function_to_bind);
- }
-
- // for efficiency, prevent creation of a temporary
- void operator =(DesiredRetType (xr_stdcall *function_to_bind)(Param1 p1))
- {
- bind(function_to_bind);
- }
-
- inline void bind(DesiredRetType (xr_stdcall *function_to_bind)(Param1 p1))
- {
- m_Closure.bindstaticfunc(this, &FastDelegate1::InvokeStaticFunction,
- function_to_bind);
- }
-
- // Invoke the delegate
- RetType operator()(Param1 p1) const
- {
- return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1);
- }
-
- // Implicit conversion to "bool" using the safe_bool idiom
- private:
- typedef struct SafeBoolStruct
- {
- int a_data_pointer_to_this_is_0_on_buggy_compilers;
- StaticFunctionPtr m_nonzero;
- } UselessTypedef;
-
- typedef StaticFunctionPtr SafeBoolStruct::* unspecified_bool_type;
- public:
- operator unspecified_bool_type() const
- {
- return empty() ? 0 : &SafeBoolStruct::m_nonzero;
- }
-
- // necessary to allow ==0 to work despite the safe_bool idiom
- inline bool operator==(StaticFunctionPtr funcptr)
- {
- return m_Closure.IsEqualToStaticFuncPtr(funcptr);
- }
-
- inline bool operator!=(StaticFunctionPtr funcptr)
- {
- return !m_Closure.IsEqualToStaticFuncPtr(funcptr);
- }
-
- inline bool operator !() const
- {
- // Is it bound to anything?
- return !m_Closure;
- }
-
- inline bool empty() const
- {
- return !m_Closure;
- }
-
- void clear() { m_Closure.clear(); }
- // Conversion to and from the DelegateMemento storage class
- const DelegateMemento& GetMemento() { return m_Closure; }
- void SetMemento(const DelegateMemento& any) { m_Closure.CopyFrom(this, any); }
-
- private: // Invoker for static functions
- // this -- parameter, function
- // p1 - function, parameter
- RetType xr_stdcall InvokeStaticFunction(Param1 p1) const
- {
- return (*(m_Closure.GetStaticFunction()))(p1);
- }
- };
-
- //N=2
- template
- class FastDelegate2
- {
- private:
- typedef typename detail::DefaultVoidToVoid::type DesiredRetType;
- typedef DesiredRetType (xr_stdcall *StaticFunctionPtr)(Param1 p1, Param2 p2);
- typedef RetType (xr_stdcall *UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2);
- typedef RetType (xr_stdcall detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2);
- typedef detail::ClosurePtr ClosureType;
- ClosureType m_Closure;
- public:
- // Typedefs to aid generic programming
- typedef FastDelegate2 type;
-
- // Construction and comparison functions
- FastDelegate2() { clear(); }
-
- FastDelegate2(const FastDelegate2& x)
- {
- m_Closure.CopyFrom(this, x.m_Closure);
- }
-
- void operator =(const FastDelegate2& x)
- {
- m_Closure.CopyFrom(this, x.m_Closure);
- }
-
- bool operator ==(const FastDelegate2& x) const
- {
- return m_Closure.IsEqual(x.m_Closure);
- }
-
- bool operator !=(const FastDelegate2& x) const
- {
- return !m_Closure.IsEqual(x.m_Closure);
- }
-
- bool operator <(const FastDelegate2& x) const
- {
- return m_Closure.IsLess(x.m_Closure);
- }
-
- bool operator >(const FastDelegate2& x) const
- {
- return x.m_Closure.IsLess(m_Closure);
- }
-
- // Binding to non-const member functions
- template
- FastDelegate2(Y* pthis, DesiredRetType (xr_stdcall X::* function_to_bind)(Param1 p1, Param2 p2))
- {
- m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind);
- }
-
- template
- inline void bind(Y* pthis, DesiredRetType (xr_stdcall X::* function_to_bind)(Param1 p1, Param2 p2))
- {
- m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind);
- }
-
- // Binding to const member functions.
- template
- FastDelegate2(const Y* pthis, DesiredRetType (xr_stdcall X::* function_to_bind)(Param1 p1, Param2 p2) const)
- {
- m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind);
- }
-
- template
- inline void bind(const Y* pthis, DesiredRetType (xr_stdcall X::* function_to_bind)(Param1 p1, Param2 p2) const)
- {
- m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind);
- }
-
- // Static functions. We convert them into a member function call.
- // This constructor also provides implicit conversion
- FastDelegate2(DesiredRetType (xr_stdcall *function_to_bind)(Param1 p1, Param2 p2))
- {
- bind(function_to_bind);
- }
-
- // for efficiency, prevent creation of a temporary
- void operator =(DesiredRetType (xr_stdcall *function_to_bind)(Param1 p1, Param2 p2))
- {
- bind(function_to_bind);
- }
-
- inline void bind(DesiredRetType (xr_stdcall *function_to_bind)(Param1 p1, Param2 p2))
- {
- m_Closure.bindstaticfunc(this, &FastDelegate2::InvokeStaticFunction,
- function_to_bind);
- }
-
- // Invoke the delegate
- RetType operator()(Param1 p1, Param2 p2) const
- {
- return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2);
- }
-
- // Implicit conversion to "bool" using the safe_bool idiom
- private:
- typedef struct SafeBoolStruct
- {
- int a_data_pointer_to_this_is_0_on_buggy_compilers;
- StaticFunctionPtr m_nonzero;
- } UselessTypedef;
-
- typedef StaticFunctionPtr SafeBoolStruct::* unspecified_bool_type;
- public:
- operator unspecified_bool_type() const
- {
- return empty() ? 0 : &SafeBoolStruct::m_nonzero;
- }
-
- // necessary to allow ==0 to work despite the safe_bool idiom
- inline bool operator==(StaticFunctionPtr funcptr)
- {
- return m_Closure.IsEqualToStaticFuncPtr(funcptr);
- }
-
- inline bool operator!=(StaticFunctionPtr funcptr)
- {
- return !m_Closure.IsEqualToStaticFuncPtr(funcptr);
- }
-
- inline bool operator !() const
- {
- // Is it bound to anything?
- return !m_Closure;
- }
-
- inline bool empty() const
- {
- return !m_Closure;
- }
-
- void clear() { m_Closure.clear(); }
- // Conversion to and from the DelegateMemento storage class
- const DelegateMemento& GetMemento() { return m_Closure; }
- void SetMemento(const DelegateMemento& any) { m_Closure.CopyFrom(this, any); }
-
- private: // Invoker for static functions
- RetType xr_stdcall InvokeStaticFunction(Param1 p1, Param2 p2) const
- {
- return (*(m_Closure.GetStaticFunction()))(p1, p2);
- }
- };
-
- //N=3
- template
- class FastDelegate3
- {
- private:
- typedef typename detail::DefaultVoidToVoid::type DesiredRetType;
- typedef DesiredRetType (xr_stdcall *StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3);
- typedef RetType (xr_stdcall *UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3);
- typedef RetType (xr_stdcall detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3);
- typedef detail::ClosurePtr ClosureType;
- ClosureType m_Closure;
- public:
- // Typedefs to aid generic programming
- typedef FastDelegate3 type;
-
- // Construction and comparison functions
- FastDelegate3() { clear(); }
-
- FastDelegate3(const FastDelegate3& x)
- {
- m_Closure.CopyFrom(this, x.m_Closure);
- }
-
- void operator =(const FastDelegate3& x)
- {
- m_Closure.CopyFrom(this, x.m_Closure);
- }
-
- bool operator ==(const FastDelegate3& x) const
- {
- return m_Closure.IsEqual(x.m_Closure);
- }
-
- bool operator !=(const FastDelegate3& x) const
- {
- return !m_Closure.IsEqual(x.m_Closure);
- }
-
- bool operator <(const FastDelegate3& x) const
- {
- return m_Closure.IsLess(x.m_Closure);
- }
-
- bool operator >(const FastDelegate3& x) const
- {
- return x.m_Closure.IsLess(m_Closure);
- }
-
- // Binding to non-const member functions
- template
- FastDelegate3(Y* pthis, DesiredRetType (xr_stdcall X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3))
- {
- m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind);
- }
-
- template
- inline void bind(Y* pthis, DesiredRetType (xr_stdcall X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3))
- {
- m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind);
- }
-
- // Binding to const member functions.
- template
- FastDelegate3(const Y* pthis,
- DesiredRetType (xr_stdcall X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) const)
- {
- m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind);
- }
-
- template
- inline void bind(const Y* pthis,
- DesiredRetType (xr_stdcall X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) const)
- {
- m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind);
- }
-
- // Static functions. We convert them into a member function call.
- // This constructor also provides implicit conversion
- FastDelegate3(DesiredRetType (xr_stdcall *function_to_bind)(Param1 p1, Param2 p2, Param3 p3))
- {
- bind(function_to_bind);
- }
-
- // for efficiency, prevent creation of a temporary
- void operator =(DesiredRetType (xr_stdcall *function_to_bind)(Param1 p1, Param2 p2, Param3 p3))
- {
- bind(function_to_bind);
- }
-
- inline void bind(DesiredRetType (xr_stdcall *function_to_bind)(Param1 p1, Param2 p2, Param3 p3))
- {
- m_Closure.bindstaticfunc(this, &FastDelegate3::InvokeStaticFunction,
- function_to_bind);
- }
-
- // Invoke the delegate
- RetType operator()(Param1 p1, Param2 p2, Param3 p3) const
- {
- return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3);
- }
-
- // Implicit conversion to "bool" using the safe_bool idiom
- private:
- typedef struct SafeBoolStruct
- {
- int a_data_pointer_to_this_is_0_on_buggy_compilers;
- StaticFunctionPtr m_nonzero;
- } UselessTypedef;
-
- typedef StaticFunctionPtr SafeBoolStruct::* unspecified_bool_type;
- public:
- operator unspecified_bool_type() const
- {
- return empty() ? 0 : &SafeBoolStruct::m_nonzero;
- }
-
- // necessary to allow ==0 to work despite the safe_bool idiom
- inline bool operator==(StaticFunctionPtr funcptr)
- {
- return m_Closure.IsEqualToStaticFuncPtr(funcptr);
- }
-
- inline bool operator!=(StaticFunctionPtr funcptr)
- {
- return !m_Closure.IsEqualToStaticFuncPtr(funcptr);
- }
-
- inline bool operator !() const
- {
- // Is it bound to anything?
- return !m_Closure;
- }
-
- inline bool empty() const
- {
- return !m_Closure;
- }
-
- void clear() { m_Closure.clear(); }
- // Conversion to and from the DelegateMemento storage class
- const DelegateMemento& GetMemento() { return m_Closure; }
- void SetMemento(const DelegateMemento& any) { m_Closure.CopyFrom(this, any); }
-
- private: // Invoker for static functions
- RetType xr_stdcall InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3) const
- {
- return (*(m_Closure.GetStaticFunction()))(p1, p2, p3);
- }
- };
-
- //N=4
- template
- class FastDelegate4
- {
- private:
- typedef typename detail::DefaultVoidToVoid::type DesiredRetType;
- typedef DesiredRetType (xr_stdcall *StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4);
- typedef RetType (xr_stdcall *UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4);
- typedef RetType (xr_stdcall detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4);
- typedef detail::ClosurePtr ClosureType;
- ClosureType m_Closure;
- public:
- // Typedefs to aid generic programming
- typedef FastDelegate4 type;
-
- // Construction and comparison functions
- FastDelegate4() { clear(); }
-
- FastDelegate4(const FastDelegate4& x)
- {
- m_Closure.CopyFrom(this, x.m_Closure);
- }
-
- void operator =(const FastDelegate4& x)
- {
- m_Closure.CopyFrom(this, x.m_Closure);
- }
-
- bool operator ==(const FastDelegate4& x) const
- {
- return m_Closure.IsEqual(x.m_Closure);
- }
-
- bool operator !=(const FastDelegate4& x) const
- {
- return !m_Closure.IsEqual(x.m_Closure);
- }
-
- bool operator <(const FastDelegate4& x) const
- {
- return m_Closure.IsLess(x.m_Closure);
- }
-
- bool operator >(const FastDelegate4& x) const
- {
- return x.m_Closure.IsLess(m_Closure);
- }
-
- // Binding to non-const member functions
- template
- FastDelegate4(
- Y* pthis, DesiredRetType (xr_stdcall X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4))
- {
- m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind);
- }
-
- template
- inline void bind(
- Y* pthis, DesiredRetType (xr_stdcall X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4))
- {
- m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind);
- }
-
- // Binding to const member functions.
- template
- FastDelegate4(const Y* pthis,
- DesiredRetType (xr_stdcall X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3,
- Param4 p4) const)
- {
- m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind);
- }
-
- template
- inline void bind(const Y* pthis,
- DesiredRetType (xr_stdcall X::* function_to_bind)(
- Param1 p1, Param2 p2, Param3 p3, Param4 p4) const)
- {
- m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind);
- }
-
- // Static functions. We convert them into a member function call.
- // This constructor also provides implicit conversion
- FastDelegate4(DesiredRetType (xr_stdcall *function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4))
- {
- bind(function_to_bind);
- }
-
- // for efficiency, prevent creation of a temporary
- void operator =(DesiredRetType (xr_stdcall *function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4))
- {
- bind(function_to_bind);
- }
-
- inline void bind(DesiredRetType (xr_stdcall *function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4))
- {
- m_Closure.bindstaticfunc(this, &FastDelegate4::InvokeStaticFunction,
- function_to_bind);
- }
-
- // Invoke the delegate
- RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const
- {
- return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4);
- }
-
- // Implicit conversion to "bool" using the safe_bool idiom
- private:
- typedef struct SafeBoolStruct
- {
- int a_data_pointer_to_this_is_0_on_buggy_compilers;
- StaticFunctionPtr m_nonzero;
- } UselessTypedef;
-
- typedef StaticFunctionPtr SafeBoolStruct::* unspecified_bool_type;
- public:
- operator unspecified_bool_type() const
- {
- return empty() ? 0 : &SafeBoolStruct::m_nonzero;
- }
-
- // necessary to allow ==0 to work despite the safe_bool idiom
- inline bool operator==(StaticFunctionPtr funcptr)
- {
- return m_Closure.IsEqualToStaticFuncPtr(funcptr);
- }
-
- inline bool operator!=(StaticFunctionPtr funcptr)
- {
- return !m_Closure.IsEqualToStaticFuncPtr(funcptr);
- }
-
- inline bool operator !() const
- {
- // Is it bound to anything?
- return !m_Closure;
- }
-
- inline bool empty() const
- {
- return !m_Closure;
- }
-
- void clear() { m_Closure.clear(); }
- // Conversion to and from the DelegateMemento storage class
- const DelegateMemento& GetMemento() { return m_Closure; }
- void SetMemento(const DelegateMemento& any) { m_Closure.CopyFrom(this, any); }
-
- private: // Invoker for static functions
- RetType xr_stdcall InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const
- {
- return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4);
- }
- };
-
- //N=5
- template
- class FastDelegate5
- {
- private:
- typedef typename detail::DefaultVoidToVoid::type DesiredRetType;
- typedef DesiredRetType (xr_stdcall *StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5);
- typedef RetType (xr_stdcall *UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5);
- typedef RetType (xr_stdcall detail::GenericClass::*GenericMemFn)(
- Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5);
- typedef detail::ClosurePtr ClosureType;
- ClosureType m_Closure;
- public:
- // Typedefs to aid generic programming
- typedef FastDelegate5 type;
-
- // Construction and comparison functions
- FastDelegate5() { clear(); }
-
- FastDelegate5(const FastDelegate5& x)
- {
- m_Closure.CopyFrom(this, x.m_Closure);
- }
-
- void operator =(const FastDelegate5& x)
- {
- m_Closure.CopyFrom(this, x.m_Closure);
- }
-
- bool operator ==(const FastDelegate5& x) const
- {
- return m_Closure.IsEqual(x.m_Closure);
- }
-
- bool operator !=(const FastDelegate5& x) const
- {
- return !m_Closure.IsEqual(x.m_Closure);
- }
-
- bool operator <(const FastDelegate5& x) const
- {
- return m_Closure.IsLess(x.m_Closure);
- }
-
- bool operator >(const FastDelegate5& x) const
- {
- return x.m_Closure.IsLess(m_Closure);
- }
-
- // Binding to non-const member functions
- template
- FastDelegate5(
- Y* pthis, DesiredRetType (xr_stdcall X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4,
- Param5 p5))
- {
- m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind);
- }
-
- template
- inline void bind(
- Y* pthis, DesiredRetType (xr_stdcall X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4,
- Param5 p5))
- {
- m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind);
- }
-
- // Binding to const member functions.
- template
- FastDelegate5(const Y* pthis,
- DesiredRetType (xr_stdcall X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4,
- Param5 p5) const)
- {
- m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind);
- }
-
- template
- inline void bind(const Y* pthis,
- DesiredRetType (xr_stdcall X::* function_to_bind)(
- Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const)
- {
- m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind);
- }
-
- // Static functions. We convert them into a member function call.
- // This constructor also provides implicit conversion
- FastDelegate5(
- DesiredRetType (xr_stdcall *function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5))
- {
- bind(function_to_bind);
- }
-
- // for efficiency, prevent creation of a temporary
- void operator =(
- DesiredRetType (xr_stdcall *function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5))
- {
- bind(function_to_bind);
- }
-
- inline void bind(
- DesiredRetType (xr_stdcall *function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5))
- {
- m_Closure.bindstaticfunc(this, &FastDelegate5::InvokeStaticFunction,
- function_to_bind);
- }
-
- // Invoke the delegate
- RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const
- {
- return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5);
- }
-
- // Implicit conversion to "bool" using the safe_bool idiom
- private:
- typedef struct SafeBoolStruct
- {
- int a_data_pointer_to_this_is_0_on_buggy_compilers;
- StaticFunctionPtr m_nonzero;
- } UselessTypedef;
-
- typedef StaticFunctionPtr SafeBoolStruct::* unspecified_bool_type;
- public:
- operator unspecified_bool_type() const
- {
- return empty() ? 0 : &SafeBoolStruct::m_nonzero;
- }
-
- // necessary to allow ==0 to work despite the safe_bool idiom
- inline bool operator==(StaticFunctionPtr funcptr)
- {
- return m_Closure.IsEqualToStaticFuncPtr(funcptr);
- }
-
- inline bool operator!=(StaticFunctionPtr funcptr)
- {
- return !m_Closure.IsEqualToStaticFuncPtr(funcptr);
- }
-
- inline bool operator !() const
- {
- // Is it bound to anything?
- return !m_Closure;
- }
-
- inline bool empty() const
- {
- return !m_Closure;
- }
-
- void clear() { m_Closure.clear(); }
- // Conversion to and from the DelegateMemento storage class
- const DelegateMemento& GetMemento() { return m_Closure; }
- void SetMemento(const DelegateMemento& any) { m_Closure.CopyFrom(this, any); }
-
- private: // Invoker for static functions
- RetType xr_stdcall InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const
- {
- return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5);
- }
- };
-
- //N=6
- template
- class FastDelegate6
- {
- private:
- typedef typename detail::DefaultVoidToVoid::type DesiredRetType;
- typedef DesiredRetType (xr_stdcall *StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5,
- Param6 p6);
- typedef RetType (xr_stdcall *UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5,
- Param6 p6);
- typedef RetType (xr_stdcall detail::GenericClass::*GenericMemFn)(
- Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6);
- typedef detail::ClosurePtr ClosureType;
- ClosureType m_Closure;
- public:
- // Typedefs to aid generic programming
- typedef FastDelegate6 type;
-
- // Construction and comparison functions
- FastDelegate6() { clear(); }
-
- FastDelegate6(const FastDelegate6& x)
- {
- m_Closure.CopyFrom(this, x.m_Closure);
- }
-
- void operator =(const FastDelegate6& x)
- {
- m_Closure.CopyFrom(this, x.m_Closure);
- }
-
- bool operator ==(const FastDelegate6& x) const
- {
- return m_Closure.IsEqual(x.m_Closure);
- }
-
- bool operator !=(const FastDelegate6& x) const
- {
- return !m_Closure.IsEqual(x.m_Closure);
- }
-
- bool operator <(const FastDelegate6& x) const
- {
- return m_Closure.IsLess(x.m_Closure);
- }
-
- bool operator >(const FastDelegate6& x) const
- {
- return x.m_Closure.IsLess(m_Closure);
- }
-
- // Binding to non-const member functions
- template
- FastDelegate6(
- Y* pthis, DesiredRetType (xr_stdcall X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4,
- Param5 p5, Param6 p6))
- {
- m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind);
- }
-
- template
- inline void bind(
- Y* pthis, DesiredRetType (xr_stdcall X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4,
- Param5 p5, Param6 p6))
- {
- m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind);
- }
-
- // Binding to const member functions.
- template
- FastDelegate6(const Y* pthis,
- DesiredRetType (xr_stdcall X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4,
- Param5 p5, Param6 p6) const)
- {
- m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind);
- }
-
- template
- inline void bind(const Y* pthis,
- DesiredRetType (xr_stdcall X::* function_to_bind)(
- Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const)
- {
- m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind);
- }
-
- // Static functions. We convert them into a member function call.
- // This constructor also provides implicit conversion
- FastDelegate6(
- DesiredRetType (xr_stdcall *function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5,
- Param6 p6))
- {
- bind(function_to_bind);
- }
-
- // for efficiency, prevent creation of a temporary
- void operator =(
- DesiredRetType (xr_stdcall *function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5,
- Param6 p6))
- {
- bind(function_to_bind);
- }
-
- inline void bind(
- DesiredRetType (xr_stdcall *function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5,
- Param6 p6))
- {
- m_Closure.bindstaticfunc(this, &FastDelegate6::InvokeStaticFunction,
- function_to_bind);
- }
-
- // Invoke the delegate
- RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const
- {
- return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6);
- }
-
- // Implicit conversion to "bool" using the safe_bool idiom
- private:
- typedef struct SafeBoolStruct
- {
- int a_data_pointer_to_this_is_0_on_buggy_compilers;
- StaticFunctionPtr m_nonzero;
- } UselessTypedef;
-
- typedef StaticFunctionPtr SafeBoolStruct::* unspecified_bool_type;
- public:
- operator unspecified_bool_type() const
- {
- return empty() ? 0 : &SafeBoolStruct::m_nonzero;
- }
-
- // necessary to allow ==0 to work despite the safe_bool idiom
- inline bool operator==(StaticFunctionPtr funcptr)
- {
- return m_Closure.IsEqualToStaticFuncPtr(funcptr);
- }
-
- inline bool operator!=(StaticFunctionPtr funcptr)
- {
- return !m_Closure.IsEqualToStaticFuncPtr(funcptr);
- }
-
- inline bool operator !() const
- {
- // Is it bound to anything?
- return !m_Closure;
- }
-
- inline bool empty() const
- {
- return !m_Closure;
- }
-
- void clear() { m_Closure.clear(); }
- // Conversion to and from the DelegateMemento storage class
- const DelegateMemento& GetMemento() { return m_Closure; }
- void SetMemento(const DelegateMemento& any) { m_Closure.CopyFrom(this, any); }
-
- private: // Invoker for static functions
- RetType xr_stdcall InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const
- {
- return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6);
- }
- };
-
- //N=7
- template
- class FastDelegate7
- {
- private:
- typedef typename detail::DefaultVoidToVoid::type DesiredRetType;
- typedef DesiredRetType (xr_stdcall *StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5,
- Param6 p6, Param7 p7);
- typedef RetType (xr_stdcall *UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5,
- Param6 p6, Param7 p7);
- typedef RetType (xr_stdcall detail::GenericClass::*GenericMemFn)(
- Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7);
- typedef detail::ClosurePtr ClosureType;
- ClosureType m_Closure;
- public:
- // Typedefs to aid generic programming
- typedef FastDelegate7 type;
-
- // Construction and comparison functions
- FastDelegate7() { clear(); }
-
- FastDelegate7(const FastDelegate7& x)
- {
- m_Closure.CopyFrom(this, x.m_Closure);
- }
-
- void operator =(const FastDelegate7& x)
- {
- m_Closure.CopyFrom(this, x.m_Closure);
- }
-
- bool operator ==(const FastDelegate7& x) const
- {
- return m_Closure.IsEqual(x.m_Closure);
- }
-
- bool operator !=(const FastDelegate7& x) const
- {
- return !m_Closure.IsEqual(x.m_Closure);
- }
-
- bool operator <(const FastDelegate7& x) const
- {
- return m_Closure.IsLess(x.m_Closure);
- }
-
- bool operator >(const FastDelegate7& x) const
- {
- return x.m_Closure.IsLess(m_Closure);
- }
-
- // Binding to non-const member functions
- template
- FastDelegate7(Y* pthis, DesiredRetType (xr_stdcall X::* function_to_bind)(
- Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7))
- {
- m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind);
- }
-
- template
- inline void bind(Y* pthis, DesiredRetType (xr_stdcall X::* function_to_bind)(
- Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7))
- {
- m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind);
- }
-
- // Binding to const member functions.
- template
- FastDelegate7(const Y* pthis,
- DesiredRetType (xr_stdcall X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4,
- Param5 p5, Param6 p6, Param7 p7) const)
- {
- m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind);
- }
-
- template
- inline void bind(const Y* pthis,
- DesiredRetType (xr_stdcall X::* function_to_bind)(
- Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const)
- {
- m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind);
- }
-
- // Static functions. We convert them into a member function call.
- // This constructor also provides implicit conversion
- FastDelegate7(
- DesiredRetType (xr_stdcall *function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5,
- Param6 p6, Param7 p7))
- {
- bind(function_to_bind);
- }
-
- // for efficiency, prevent creation of a temporary
- void operator =(
- DesiredRetType (xr_stdcall *function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5,
- Param6 p6, Param7 p7))
- {
- bind(function_to_bind);
- }
-
- inline void bind(
- DesiredRetType (xr_stdcall *function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5,
- Param6 p6, Param7 p7))
- {
- m_Closure.bindstaticfunc(this, &FastDelegate7::InvokeStaticFunction,
- function_to_bind);
- }
-
- // Invoke the delegate
- RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const
- {
- return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7);
- }
-
- // Implicit conversion to "bool" using the safe_bool idiom
- private:
- typedef struct SafeBoolStruct
- {
- int a_data_pointer_to_this_is_0_on_buggy_compilers;
- StaticFunctionPtr m_nonzero;
- } UselessTypedef;
-
- typedef StaticFunctionPtr SafeBoolStruct::* unspecified_bool_type;
- public:
- operator unspecified_bool_type() const
- {
- return empty() ? 0 : &SafeBoolStruct::m_nonzero;
- }
-
- // necessary to allow ==0 to work despite the safe_bool idiom
- inline bool operator==(StaticFunctionPtr funcptr)
- {
- return m_Closure.IsEqualToStaticFuncPtr(funcptr);
- }
-
- inline bool operator!=(StaticFunctionPtr funcptr)
- {
- return !m_Closure.IsEqualToStaticFuncPtr(funcptr);
- }
-
- inline bool operator !() const
- {
- // Is it bound to anything?
- return !m_Closure;
- }
-
- inline bool empty() const
- {
- return !m_Closure;
- }
-
- void clear() { m_Closure.clear(); }
- // Conversion to and from the DelegateMemento storage class
- const DelegateMemento& GetMemento() { return m_Closure; }
- void SetMemento(const DelegateMemento& any) { m_Closure.CopyFrom(this, any); }
-
- private: // Invoker for static functions
- RetType xr_stdcall InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6,
- Param7 p7) const
- {
- return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7);
- }
- };
-
- //N=8
- template
- class FastDelegate8
- {
- private:
- typedef typename detail::DefaultVoidToVoid::type DesiredRetType;
- typedef DesiredRetType (xr_stdcall *StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5,
- Param6 p6, Param7 p7, Param8 p8);
- typedef RetType (xr_stdcall *UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5,
- Param6 p6, Param7 p7, Param8 p8);
- typedef RetType (xr_stdcall detail::GenericClass::*GenericMemFn)(
- Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8);
- typedef detail::ClosurePtr ClosureType;
- ClosureType m_Closure;
- public:
- // Typedefs to aid generic programming
- typedef FastDelegate8 type;
-
- // Construction and comparison functions
- FastDelegate8() { clear(); }
-
- FastDelegate8(const FastDelegate8& x)
- {
- m_Closure.CopyFrom(this, x.m_Closure);
- }
-
- void operator =(const FastDelegate8& x)
- {
- m_Closure.CopyFrom(this, x.m_Closure);
- }
-
- bool operator ==(const FastDelegate8& x) const
- {
- return m_Closure.IsEqual(x.m_Closure);
- }
-
- bool operator !=(const FastDelegate8& x) const
- {
- return !m_Closure.IsEqual(x.m_Closure);
- }
-
- bool operator <(const FastDelegate8& x) const
- {
- return m_Closure.IsLess(x.m_Closure);
- }
-
- bool operator >(const FastDelegate8& x) const
- {
- return x.m_Closure.IsLess(m_Closure);
- }
-
- // Binding to non-const member functions
- template
- FastDelegate8(Y* pthis, DesiredRetType (xr_stdcall X::* function_to_bind)(
- Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8))
- {
- m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind);
- }
-
- template
- inline void bind(Y* pthis, DesiredRetType (xr_stdcall X::* function_to_bind)(
- Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8))
- {
- m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind);
- }
-
- // Binding to const member functions.
- template
- FastDelegate8(const Y* pthis,
- DesiredRetType (xr_stdcall X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4,
- Param5 p5, Param6 p6, Param7 p7,
- Param8 p8) const)
- {
- m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind);
- }
-
- template
- inline void bind(const Y* pthis,
- DesiredRetType (xr_stdcall X::* function_to_bind)(
- Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7,
- Param8 p8) const)
- {
- m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind);
- }
-
- // Static functions. We convert them into a member function call.
- // This constructor also provides implicit conversion
- FastDelegate8(DesiredRetType (xr_stdcall *function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4,
- Param5 p5, Param6 p6, Param7 p7, Param8 p8))
- {
- bind(function_to_bind);
- }
-
- // for efficiency, prevent creation of a temporary
- void operator =(DesiredRetType (xr_stdcall *function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4,
- Param5 p5, Param6 p6, Param7 p7, Param8 p8))
- {
- bind(function_to_bind);
- }
-
- inline void bind(DesiredRetType (xr_stdcall *function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4,
- Param5 p5, Param6 p6, Param7 p7, Param8 p8))
- {
- m_Closure.bindstaticfunc(this, &FastDelegate8::InvokeStaticFunction,
- function_to_bind);
- }
-
- // Invoke the delegate
- RetType operator()(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const
- {
- return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8);
- }
-
- // Implicit conversion to "bool" using the safe_bool idiom
- private:
- typedef struct SafeBoolStruct
- {
- int a_data_pointer_to_this_is_0_on_buggy_compilers;
- StaticFunctionPtr m_nonzero;
- } UselessTypedef;
-
- typedef StaticFunctionPtr SafeBoolStruct::* unspecified_bool_type;
- public:
- operator unspecified_bool_type() const
- {
- return empty() ? 0 : &SafeBoolStruct::m_nonzero;
- }
-
- // necessary to allow ==0 to work despite the safe_bool idiom
- inline bool operator==(StaticFunctionPtr funcptr)
- {
- return m_Closure.IsEqualToStaticFuncPtr(funcptr);
- }
-
- inline bool operator!=(StaticFunctionPtr funcptr)
- {
- return !m_Closure.IsEqualToStaticFuncPtr(funcptr);
- }
-
- inline bool operator !() const
- {
- // Is it bound to anything?
- return !m_Closure;
- }
-
- inline bool empty() const
- {
- return !m_Closure;
- }
-
- void clear() { m_Closure.clear(); }
- // Conversion to and from the DelegateMemento storage class
- const DelegateMemento& GetMemento() { return m_Closure; }
- void SetMemento(const DelegateMemento& any) { m_Closure.CopyFrom(this, any); }
-
- private: // Invoker for static functions
- RetType xr_stdcall InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6,
- Param7 p7, Param8 p8) const
- {
- return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8);
- }
- };
-
-
- ////////////////////////////////////////////////////////////////////////////////
- // Fast Delegates, part 4:
- //
- // FastDelegate<> class (Original author: Jody Hagins)
- // Allows boost::function style syntax like:
- // FastDelegate< double (int, long) >
- // instead of:
- // FastDelegate2< int, long, double >
- //
- ////////////////////////////////////////////////////////////////////////////////
+ // 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(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
+// 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(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(&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.
+
+// Implicit conversion to "bool" is achieved using the safe_bool idiom,
+// using member data pointers (MDP). This allows "if (dg)..." syntax
+// Because some compilers (eg codeplay) don't have a unique value for a zero
+// MDP, an extra padding member is added to the SafeBool struct.
+// Some compilers (eg VC6) won't implicitly convert from 0 to an MDP, so
+// in that case the static function constructor is not made explicit; this
+// allows "if (dg==0) ..." to compile.
+
+template
+class FastDelegateImpl {
+private:
+ typedef typename detail::DefaultVoidToVoid::type DesiredRetType;
+ typedef DesiredRetType (*StaticFunctionPtr)(Args...);
+ typedef RetType (*UnvoidStaticFunctionPtr)(Args...);
+ typedef RetType (detail::GenericClass::*GenericMemFn)(Args...);
+ typedef detail::ClosurePtr ClosureType;
+ ClosureType m_Closure;
+public:
+ // Typedefs to aid generic programming
+ typedef FastDelegateImpl type;
+
+ // Construction and comparison functions
+ FastDelegateImpl() { clear(); }
+ FastDelegateImpl(const FastDelegateImpl &x) {
+ m_Closure.CopyFrom(this, x.m_Closure); }
+ void operator = (const FastDelegateImpl &x) {
+ m_Closure.CopyFrom(this, x.m_Closure); }
+ bool operator ==(const FastDelegateImpl &x) const {
+ return m_Closure.IsEqual(x.m_Closure); }
+ bool operator !=(const FastDelegateImpl &x) const {
+ return !m_Closure.IsEqual(x.m_Closure); }
+ bool operator <(const FastDelegateImpl &x) const {
+ return m_Closure.IsLess(x.m_Closure); }
+ bool operator >(const FastDelegateImpl &x) const {
+ return x.m_Closure.IsLess(m_Closure); }
+ // Binding to non-const member functions
+ template < typename X, typename Y >
+ FastDelegateImpl(Y *pthis, DesiredRetType (X::* function_to_bind)(Args... args) ) {
+ m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); }
+ template < typename X, typename Y >
+ inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Args... args)) {
+ m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); }
+ // Binding to const member functions.
+ template < typename X, typename Y >
+ FastDelegateImpl(const Y *pthis, DesiredRetType (X::* function_to_bind)(Args... args) const) {
+ m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); }
+ template < typename X, typename Y >
+ inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Args... args) const) {
+ m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); }
+ // Static functions. We convert them into a member function call.
+ // This constructor also provides implicit conversion
+ FastDelegateImpl(DesiredRetType (*function_to_bind)(Args... args) ) {
+ bind(function_to_bind); }
+ // for efficiency, prevent creation of a temporary
+ void operator = (DesiredRetType (*function_to_bind)(Args... args) ) {
+ bind(function_to_bind); }
+ inline void bind(DesiredRetType (*function_to_bind)(Args... args)) {
+ m_Closure.bindstaticfunc(this, &FastDelegateImpl::InvokeStaticFunction,
+ function_to_bind); }
+ // Invoke the delegate
+ RetType operator() (Args... args) const {
+ return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(args...); }
+ // Implicit conversion to "bool" using the safe_bool idiom
+private:
+ typedef struct SafeBoolStruct {
+ int a_data_pointer_to_this_is_0_on_buggy_compilers;
+ StaticFunctionPtr m_nonzero;
+ } UselessTypedef;
+ typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
+public:
+ operator unspecified_bool_type() const {
+ return empty()? 0: &SafeBoolStruct::m_nonzero;
+ }
+ // necessary to allow ==0 to work despite the safe_bool idiom
+ inline bool operator==(StaticFunctionPtr funcptr) {
+ return m_Closure.IsEqualToStaticFuncPtr(funcptr); }
+ inline bool operator!=(StaticFunctionPtr funcptr) {
+ return !m_Closure.IsEqualToStaticFuncPtr(funcptr); }
+ inline bool operator ! () const { // Is it bound to anything?
+ return !m_Closure; }
+ inline bool empty() const {
+ return !m_Closure; }
+ void clear() { m_Closure.clear();}
+ // Conversion to and from the DelegateMemento storage class
+ const DelegateMemento & GetMemento() const { return m_Closure; }
+ void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
+
+private: // Invoker for static functions
+ RetType InvokeStaticFunction(Args... args) const {
+ return (*(m_Closure.GetStaticFunction()))(args...); }
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// Fast Delegates, part 4:
+//
+// FastDelegate<> class (Original author: Jody Hagins)
+// Allows boost::function style syntax like:
+// FastDelegate< double (int, long) >
+// instead of:
+// FastDelegate2< int, long, double >
+//
+////////////////////////////////////////////////////////////////////////////////
#ifdef FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
- // Declare FastDelegate as a class template. It will be specialized
- // later for all number of arguments.
- template
- class FastDelegate;
-
- //N=0
- // Specialization to allow use of
- // FastDelegate< R ( ) >
- // instead of
- // FastDelegate0 < R >
- template
- class FastDelegate
- // Inherit from FastDelegate0 so that it can be treated just like a FastDelegate0
- : public FastDelegate0
- {
- public:
- // Make using the base type a bit easier via typedef.
- typedef FastDelegate0 BaseType;
-
- // Allow users access to the specific type of this delegate.
- typedef FastDelegate SelfType;
-
- // Mimic the base class constructors.
- FastDelegate() : BaseType()
- {
- }
-
- template
- FastDelegate(Y* pthis,
- R (xr_stdcall X::* function_to_bind)())
- : BaseType(pthis, function_to_bind)
- {
- }
-
- template
- FastDelegate(const Y* pthis,
- R (xr_stdcall X::* function_to_bind)() const)
- : BaseType(pthis, function_to_bind)
- {
- }
-
- FastDelegate(R (xr_stdcall *function_to_bind)())
- : BaseType(function_to_bind)
- {
- }
-
- void operator =(const BaseType& x)
- {
- *static_cast(this) = x;
- }
- };
-
- //N=1
- // Specialization to allow use of
- // FastDelegate< R ( Param1 ) >
- // instead of
- // FastDelegate1 < Param1, R >
- template
- class FastDelegate
- // Inherit from FastDelegate1 so that it can be treated just like a FastDelegate1
- : public FastDelegate1
- {
- public:
- // Make using the base type a bit easier via typedef.
- typedef FastDelegate1 BaseType;
-
- // Allow users access to the specific type of this delegate.
- typedef FastDelegate SelfType;
-
- // Mimic the base class constructors.
- FastDelegate() : BaseType()
- {
- }
-
- template
- FastDelegate(Y* pthis,
- R (xr_stdcall X::* function_to_bind)(Param1 p1))
- : BaseType(pthis, function_to_bind)
- {
- }
-
- template
- FastDelegate(const Y* pthis,
- R (xr_stdcall X::* function_to_bind)(Param1 p1) const)
- : BaseType(pthis, function_to_bind)
- {
- }
-
- FastDelegate(R (xr_stdcall *function_to_bind)(Param1 p1))
- : BaseType(function_to_bind)
- {
- }
-
- void operator =(const BaseType& x)
- {
- *static_cast(this) = x;
- }
- };
-
- //N=2
- // Specialization to allow use of
- // FastDelegate< R ( Param1, Param2 ) >
- // instead of
- // FastDelegate2 < Param1, Param2, R >
- template
- class FastDelegate
- // Inherit from FastDelegate2 so that it can be treated just like a FastDelegate2
- : public FastDelegate2
- {
- public:
- // Make using the base type a bit easier via typedef.
- typedef FastDelegate2 BaseType;
-
- // Allow users access to the specific type of this delegate.
- typedef FastDelegate SelfType;
-
- // Mimic the base class constructors.
- FastDelegate() : BaseType()
- {
- }
-
- template
- FastDelegate(Y* pthis,
- R (xr_stdcall X::* function_to_bind)(Param1 p1, Param2 p2))
- : BaseType(pthis, function_to_bind)
- {
- }
-
- template
- FastDelegate(const Y* pthis,
- R (xr_stdcall X::* function_to_bind)(Param1 p1, Param2 p2) const)
- : BaseType(pthis, function_to_bind)
- {
- }
-
- FastDelegate(R (xr_stdcall *function_to_bind)(Param1 p1, Param2 p2))
- : BaseType(function_to_bind)
- {
- }
-
- void operator =(const BaseType& x)
- {
- *static_cast(this) = x;
- }
- };
-
- //N=3
- // Specialization to allow use of
- // FastDelegate< R ( Param1, Param2, Param3 ) >
- // instead of
- // FastDelegate3 < Param1, Param2, Param3, R >
- template
- class FastDelegate
- // Inherit from FastDelegate3 so that it can be treated just like a FastDelegate3
- : public FastDelegate3
- {
- public:
- // Make using the base type a bit easier via typedef.
- typedef FastDelegate3 BaseType;
-
- // Allow users access to the specific type of this delegate.
- typedef FastDelegate SelfType;
-
- // Mimic the base class constructors.
- FastDelegate() : BaseType()
- {
- }
-
- template
- FastDelegate(Y* pthis,
- R (xr_stdcall X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3))
- : BaseType(pthis, function_to_bind)
- {
- }
-
- template
- FastDelegate(const Y* pthis,
- R (xr_stdcall X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) const)
- : BaseType(pthis, function_to_bind)
- {
- }
-
- FastDelegate(R (xr_stdcall *function_to_bind)(Param1 p1, Param2 p2, Param3 p3))
- : BaseType(function_to_bind)
- {
- }
-
- void operator =(const BaseType& x)
- {
- *static_cast(this) = x;
- }
- };
-
- //N=4
- // Specialization to allow use of
- // FastDelegate< R ( Param1, Param2, Param3, Param4 ) >
- // instead of
- // FastDelegate4 < Param1, Param2, Param3, Param4, R >
- template
- class FastDelegate
- // Inherit from FastDelegate4 so that it can be treated just like a FastDelegate4
- : public FastDelegate4
- {
- public:
- // Make using the base type a bit easier via typedef.
- typedef FastDelegate4 BaseType;
-
- // Allow users access to the specific type of this delegate.
- typedef FastDelegate SelfType;
-
- // Mimic the base class constructors.
- FastDelegate() : BaseType()
- {
- }
-
- template
- FastDelegate(Y* pthis,
- R (xr_stdcall X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4))
- : BaseType(pthis, function_to_bind)
- {
- }
-
- template
- FastDelegate(const Y* pthis,
- R (xr_stdcall X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const)
- : BaseType(pthis, function_to_bind)
- {
- }
-
- FastDelegate(R (xr_stdcall *function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4))
- : BaseType(function_to_bind)
- {
- }
-
- void operator =(const BaseType& x)
- {
- *static_cast(this) = x;
- }
- };
-
- //N=5
- // Specialization to allow use of
- // FastDelegate< R ( Param1, Param2, Param3, Param4, Param5 ) >
- // instead of
- // FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R >
- template
- class FastDelegate
- // Inherit from FastDelegate5 so that it can be treated just like a FastDelegate5
- : public FastDelegate5
- {
- public:
- // Make using the base type a bit easier via typedef.
- typedef FastDelegate5 BaseType;
-
- // Allow users access to the specific type of this delegate.
- typedef FastDelegate SelfType;
-
- // Mimic the base class constructors.
- FastDelegate() : BaseType()
- {
- }
-
- template
- FastDelegate(Y* pthis,
- R (xr_stdcall X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5))
- : BaseType(pthis, function_to_bind)
- {
- }
-
- template