Skip to content

Instantly share code, notes, and snippets.

@seiren-naru-shirayuri
Last active February 3, 2023 13:47
Show Gist options
  • Save seiren-naru-shirayuri/71285c02c8fd8b185be57c4374d850ae to your computer and use it in GitHub Desktop.
Save seiren-naru-shirayuri/71285c02c8fd8b185be57c4374d850ae to your computer and use it in GitHub Desktop.
A Universal callback thunk for Win32 API callbacks.
!Win32CallbackThunk

Note: This code rely on an unresolved CWG issue: https://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1626

A Universal callback thunk for Win32 API callbacks.

This gist is released under GLWTPL.

Tested on MSVC 19.33 in C++20 mode.

There are two kind of thunks, ReplacementCallbackThunk and InsertionCallbackThunk, where:

ReplacementCallbackThunk replaces the n-th parameter of the of the original callback with this pointer. If the prototype of the original callback is R __stdcall (Param0, Param1, ..., ParamN-1, ParamN, ParamN+1, ...), the prototype of user callback would be R __stdcall (Param0, Param1, ..., ParamN-1, Class*, ParamN+1, ...).

InsertionCallbackThunk inserts this pointer before the first parameter of the original callback, effectively turns the callback into a member function. If the prototype of the original callback is R __stdcall (Param0, Param1, ...), the prototype of user callback would be R(__thiscall Class::*)(Param0, Param1, ...).

Note that the return value of callbacks must be returnable in eax/edx:eax (in x86) or rax (in x64).

In x64, declare a constexpr bool bGenerateFunctionTable constant before including CallbackThunk.hpp. Set bGenerateFunctionTable to true to generate function table for callback thunks to assist stack unwinding, set bGenerateFunctionTable to false otherwise.

See WinMain.cpp for an example.

#pragma once
#if !defined(_M_IX86) && !defined(_M_X64)
#error Unsupported processor architecture
#endif
#include <new>
#include <type_traits>
#include <vector>
#include <string>
#include <array>
#include <utility>
#include <cstddef>
#include <cstdint>
#include <cassert>
#include "stdext.hpp"
#include <Windows.h>
namespace Detail
{
/*
Execuable allocator for callback thunks
*/
inline HANDLE hExecutableHeap = HeapCreate(HEAP_CREATE_ENABLE_EXECUTE, 0, 0);
struct ExecutableNewDeleteAllocator
{
[[nodiscard]] void* operator new(std::size_t size)
{
return HeapAlloc(hExecutableHeap, HEAP_ZERO_MEMORY, size);
}
[[nodiscard]] void* operator new(std::size_t size, std::align_val_t align)
{
if (static_cast<std::size_t>(align) <= MEMORY_ALLOCATION_ALIGNMENT)
{
return operator new(size);
}
else
{
throw std::bad_alloc{};
}
}
void operator delete(void* ptr) noexcept
{
HeapFree(hExecutableHeap, 0, ptr);
}
void operator delete(void* ptr, std::size_t) noexcept
{
operator delete(ptr);
}
void operator delete(void* ptr, std::align_val_t align) noexcept
{
assert(static_cast<std::size_t>(align) <= MEMORY_ALLOCATION_ALIGNMENT && "Invalid alignment");
operator delete(ptr);
}
void operator delete(void* ptr, std::size_t, std::align_val_t align) noexcept
{
operator delete(ptr, align);
}
};
}
#if defined(_M_IX86)
/*
Callback thunk that replaces the nth parameter of the original callback with this pointer
Note that the return type of the callback must be returnable in eax register
For callback R __stdcall (Param0, Param1, ..., ParamN-1, ParamN, ParamN+1, ...), the user callback is R __stdcall (Param0, Param1, ..., ParamN-1, Class*, ParamN+1, ...)
*/
template <typename C, typename F, std::size_t I>
requires std::is_class_v<C> && stdext::is_function_pointer_v<F> && stdext::is_stdcall_v<std::remove_pointer_t<F>> && (stdext::arity_v<std::remove_pointer_t<F>> > 0) && (I < stdext::arity_v<std::remove_pointer_t<F>>)
class ReplacementCallbackThunk
{
public:
static_assert(I < 31, "Too many parameters in the callback function.");
ReplacementCallbackThunk(C* pThis, stdext::replace_parameter_t<std::remove_pointer_t<F>, C*, I>* pCallbackProc) :
m_pTrampoline(new CallbackThunk{ .pThis = reinterpret_cast<std::uint32_t>(pThis) })
{
m_pTrampoline->pCallbackProcOffset = reinterpret_cast<std::uint32_t>(pCallbackProc) - reinterpret_cast<std::uint32_t>(m_pTrampoline) - sizeof(*m_pTrampoline);
FlushInstructionCache(GetCurrentProcess(), m_pTrampoline, sizeof(*m_pTrampoline));
}
~ReplacementCallbackThunk()
{
delete m_pTrampoline;
}
F GetAddress() const noexcept
{
return reinterpret_cast<F>(m_pTrampoline);
}
private:
#pragma pack (push, 1)
struct Trampoline : public Detail::ExecutableNewDeleteAllocator
{
std::uint32_t mov_dword_ptr_esp_plus_imm = 0x2444c7 | (4 + I * 4) << 24;
std::uint32_t pThis = 0; // mov dword ptr[esp+(4+imm*4)], pThis
std::uint8_t jmp = 0xe9;
std::uint32_t pCallbackProcOffset = 0; // jmp pCallbackProcOffset
};
#pragma pack (pop)
Trampoline* m_pTrampoline;
};
/*
Callback thunk that inserts this pointer before the first parameter of the original callback
Note that the return type of the callback must be returnable in eax register
For callback R __stdcall (Param0, Param1, ...), the user callback is R(__thiscall Class::*)(Param0, Param1, ...)
*/
template <typename C, typename F>
requires std::is_class_v<C> && stdext::is_function_pointer_v<F> && stdext::is_stdcall_v<std::remove_pointer_t<F>>
class InsertionCallbackThunk
{
public:
InsertionCallbackThunk(C* pThis, stdext::add_thiscall_t<std::remove_pointer_t<F> C::*> pCallbackProc) :
m_pTrampoline(new CallbackThunk{ .pThis = reinterpret_cast<std::uint32_t>(pThis) })
{
m_pTrampoline->pCallbackProcOffset = *reinterpret_cast<std::uint32_t*>(&pCallbackProc) - reinterpret_cast<std::uint32_t>(m_pTrampoline) - sizeof(*m_pTrampoline);
FlushInstructionCache(GetCurrentProcess(), m_pTrampoline, sizeof(*m_pTrampoline));
}
~InsertionCallbackThunk()
{
delete m_pTrampoline;
}
F GetAddress() const noexcept
{
return reinterpret_cast<F>(m_pTrampoline);
}
private:
#pragma pack (push, 1)
struct Trampoline : public Detail::ExecutableNewDeleteAllocator
{
std::uint8_t mov_ecx = 0xb9;
std::uint32_t pThis = 0; // mov ecx, pThis
std::uint8_t jmp = 0xe9;
std::uint32_t pCallbackProcOffset = 0; // jmp pCallbackProcOffset
};
#pragma pack (pop)
Trampoline* m_pTrampoline;
};
#elif defined(_M_X64)
/*
Callback thunk that replaces the nth parameter of the original callback with this pointer
Note that the return type of the callback must be returnable in rax register
For callback R __stdcall (Param0, Param1, ..., ParamN-1, ParamN, ParamN+1, ...), the user callback is R __stdcall (Param0, Param1, ..., ParamN-1, Class*, ParamN+1, ...)
*/
template <typename, typename, std::size_t>
class ReplacementCallbackThunkImpl;
template <typename C, typename F, std::size_t I>
requires (I >= 0 && I < 4)
class ReplacementCallbackThunkImpl<C, F, I>
{
private:
static consteval std::uint16_t GenerateMovRegMem()
{
switch (I)
{
case 0:
return 0xb948; // mov rcx, mem
break;
case 1:
return 0xba48; // mov rdx, mem
break;
case 2:
return 0xb849; // mov r8, mem
break;
case 3:
return 0xb949; // mov r9, mem
break;
default:
break;
}
}
protected:
#pragma pack (push, 2)
struct Trampoline : public Detail::ExecutableNewDeleteAllocator
{
std::uint16_t mov_reg = GenerateMovRegMem();
std::uint64_t pThis = 0; // mov reg, pThis
std::uint16_t mov_rax = 0xb848;
std::uint64_t pCallbackProc = 0; // mov rax, pCallbackProc
std::uint32_t rexw_jmp_rax_nop = 0x90e0ff48; // rex.w jmp rax; nop
};
#pragma pack (pop)
};
template <typename C, typename F, std::size_t I>
requires (I >= 4 && I < 15)
class ReplacementCallbackThunkImpl<C, F, I>
{
protected:
#pragma pack (push, 1)
struct Trampoline : public Detail::ExecutableNewDeleteAllocator
{
std::uint16_t mov_rax1 = 0xb848;
std::uint64_t pThis = 0; // mov rax, pThis
std::uint32_t mov_rsp_plus_imm_rax = 0x24448948;
std::uint8_t imm = 40 + (I - 4) * 8; // mov [rsp+(40+(I-4)*8)], rax
std::uint16_t mov_rax2 = 0xb848;
std::uint64_t pCallbackProc = 0; // mov rax, pCallbackProc
std::uint32_t rexw_jmp_rax_nop = 0x90e0ff48; // rex.w jmp rax; nop
};
#pragma pack (pop)
};
template <typename C, typename F, std::size_t I>
requires (I >= 15)
class ReplacementCallbackThunkImpl<C, F, I>
{
protected:
static_assert(stdext::always_false_v<C, F, decltype(I)>, "Too many parameters in the callback function.");
struct Trampoline : public Detail::ExecutableNewDeleteAllocator
{
std::uint64_t pThis = 0;
std::uint64_t pCallbackProc = 0;
};
};
template <typename C, typename F, std::size_t I>
requires std::is_class_v<C> && stdext::is_function_pointer_v<F> && stdext::is_x64call_v<std::remove_pointer_t<F>> && (stdext::arity_v<std::remove_pointer_t<F>> > 0) && (I < stdext::arity_v<std::remove_pointer_t<F>>)
class ReplacementCallbackThunk : private ReplacementCallbackThunkImpl<C, F, I>
{
public:
ReplacementCallbackThunk(C* pThis, stdext::replace_parameter_t<std::remove_pointer_t<F>, C*, I>* pCallbackProc) :
m_pTrampoline(new ReplacementCallbackThunkImpl<C, F, I>::Trampoline{ .pThis = reinterpret_cast<std::uint64_t>(pThis), .pCallbackProc = reinterpret_cast<std::uint64_t>(pCallbackProc) })
{
FlushInstructionCache(GetCurrentProcess(), m_pTrampoline, sizeof(*m_pTrampoline));
}
~ReplacementCallbackThunk()
{
delete m_pTrampoline;
}
F GetAddress() const noexcept
{
return reinterpret_cast<F>(m_pTrampoline);
}
private:
ReplacementCallbackThunkImpl<C, F, I>::Trampoline* m_pTrampoline;
};
/*
Callback thunk that inserts this pointer before the first parameter of the original callback
Note that the return type of the callback must be returnable in rax register
For callback R __stdcall (Param0, Param1, ...), the user callback is R(__thiscall Class::*)(Param0, Param1, ...)
*/
template <typename, typename, bool>
class InsertionCallbackThunkImpl;
template <typename C, typename F, bool b>
requires (stdext::arity_v<std::remove_pointer_t<F>> == 0)
class InsertionCallbackThunkImpl<C, F, b>
{
protected:
#pragma pack (push, 2)
struct Trampoline : public Detail::ExecutableNewDeleteAllocator
{
std::uint16_t mov_rcx = 0xb948;
std::uint64_t pThis = 0; // mov rcx, pThis
std::uint16_t mov_rax = 0xb848;
std::uint64_t pCallbackProc = 0; // mov rax, pCallbackProc
std::uint32_t rexw_jmp_rax_nop = 0x90e0ff48; // rex.w jmp rax; nop
};
#pragma pack (pop)
};
template <typename C, typename F, bool b>
requires (stdext::arity_v<std::remove_pointer_t<F>> > 0 && stdext::arity_v<std::remove_pointer_t<F>> < 4)
class InsertionCallbackThunkImpl<C, F, b>
{
private:
static consteval auto GenerateThunkProlog()
{
std::string ThunkProlog;
if constexpr (stdext::arity_v<std::remove_pointer_t<F>> == 1)
{
if (std::is_floating_point_v<stdext::parameter_type_t<std::remove_pointer_t<F>, 0>>)
{
ThunkProlog += "\x0f\x28\xc8"; // movaps xmm1, xmm0
}
else
{
ThunkProlog += "\x48\x89\xca"; // mov rdx, rcx
}
}
else if constexpr (stdext::arity_v<std::remove_pointer_t<F>> == 2)
{
if (std::is_floating_point_v<stdext::parameter_type_t<std::remove_pointer_t<F>, 1>>)
{
ThunkProlog += "\x0f\x28\xd1"; // movaps xmm2, xmm1
}
else
{
ThunkProlog += "\x49\x89\xd0"; // mov r8, rdx
}
if (std::is_floating_point_v<stdext::parameter_type_t<std::remove_pointer_t<F>, 0>>)
{
ThunkProlog += "\x0f\x28\xc8"; // movaps xmm1, xmm0
}
else
{
ThunkProlog += "\x48\x89\xca"; // mov rdx, rcx
}
}
else if constexpr (stdext::arity_v<std::remove_pointer_t<F>> == 3)
{
if (std::is_floating_point_v<stdext::parameter_type_t<std::remove_pointer_t<F>, 2>>)
{
ThunkProlog += "\x0f\x28\xda"; // movaps xmm3, xmm2
}
else
{
ThunkProlog += "\x4d\x89\xc1"; // mov r9, r8
}
if (std::is_floating_point_v<stdext::parameter_type_t<std::remove_pointer_t<F>, 1>>)
{
ThunkProlog += "\x0f\x28\xd1"; // movaps xmm2, xmm1
}
else
{
ThunkProlog += "\x49\x89\xd0"; // mov r8, rdx
}
if (std::is_floating_point_v<stdext::parameter_type_t<std::remove_pointer_t<F>, 0>>)
{
ThunkProlog += "\x0f\x28\xc8"; // movaps xmm1, xmm0
}
else
{
ThunkProlog += "\x48\x89\xca"; // mov rdx, rcx
}
}
return ThunkProlog;
}
static consteval std::size_t ThunkPrologSize()
{
return GenerateThunkProlog().size();
}
static consteval auto ThunkPrologData()
{
auto StringToArray = []<std::size_t ...Is>(const std::string& str, std::index_sequence<Is...>) { return std::array{ str[Is]... }; };
return StringToArray(GenerateThunkProlog(), std::make_index_sequence<ThunkPrologSize()>{});
}
protected:
#pragma pack (push, 1)
struct Trampoline : public Detail::ExecutableNewDeleteAllocator
{
std::array<char, ThunkPrologSize()> ThunkProlog = ThunkPrologData();
std::uint16_t mov_rcx = 0xb948;
std::uint64_t pThis = 0; // mov rcx, pThis
std::uint16_t mov_rax = 0xb848;
std::uint64_t pCallbackProc = 0; // mov rax, pCallbackProc
std::uint32_t rexw_jmp_rax_nop = 0x90e0ff48; // rex.w jmp rax; nop
};
#pragma pack (pop)
};
template <typename C, typename F>
requires (stdext::arity_v<std::remove_pointer_t<F>> >= 4 && stdext::arity_v<std::remove_pointer_t<F>> < 15)
class InsertionCallbackThunkImpl<C, F, false>
{
private:
static consteval auto GenerateThunkProlog()
{
std::string ThunkProlog;
std::size_t OriginalStackParameterCount = stdext::arity_v<std::remove_pointer_t<F>> - 4;
if (OriginalStackParameterCount > 0)
{
ThunkProlog += "\x48\x89\xe0"; // mov rax, rsp
}
if (OriginalStackParameterCount % 2 != 0)
{
ThunkProlog += "\x48\x83\xec\x08"; // sub rsp, 8
}
for (size_t i = OriginalStackParameterCount; i > 0; i--)
{
std::int8_t imm = static_cast<std::int8_t>(32 + i * 8);
ThunkProlog += "\xff\x70";
ThunkProlog += static_cast<char>(imm); // push qword ptr [rax+imm]
}
if (std::is_floating_point_v<stdext::parameter_type_t<std::remove_pointer_t<F>, 3>>)
{
ThunkProlog += "\x48\x83\xec\x08\x66\x0f\x13\x1c\x24"; // sub rsp, 8; movlpd qword ptr [rsp], xmm3
}
else
{
ThunkProlog += "\x41\x51"; // push r9
}
ThunkProlog += "\x48\x83\xec\x20"; // sub rsp, 32
if (std::is_floating_point_v<stdext::parameter_type_t<std::remove_pointer_t<F>, 2>>)
{
ThunkProlog += "\x0f\x28\xda"; // movaps xmm3, xmm2
}
else
{
ThunkProlog += "\x4d\x89\xc1"; // mov r9, r8
}
if (std::is_floating_point_v<stdext::parameter_type_t<std::remove_pointer_t<F>, 1>>)
{
ThunkProlog += "\x0f\x28\xd1"; // movaps xmm2, xmm1
}
else
{
ThunkProlog += "\x49\x89\xd0"; // mov r8, rdx
}
if (std::is_floating_point_v<stdext::parameter_type_t<std::remove_pointer_t<F>, 0>>)
{
ThunkProlog += "\x0f\x28\xc8"; // movaps xmm1, xmm0
}
else
{
ThunkProlog += "\x48\x89\xca"; // mov rdx, rcx
}
return ThunkProlog;
}
static consteval std::size_t ThunkPrologSize()
{
return GenerateThunkProlog().size();
}
static consteval auto ThunkPrologData()
{
auto StringToArray = []<std::size_t ...Is>(const std::string& str, std::index_sequence<Is...>) { return std::array{ str[Is]... }; };
return StringToArray(GenerateThunkProlog(), std::make_index_sequence<ThunkPrologSize()>{});
}
static consteval auto GenerateThunkEpilog()
{
std::string ThunkEpilog;
std::size_t OriginalStackParameterCount = stdext::arity_v<std::remove_pointer_t<F>> - 4;
ThunkEpilog += "\xff\xd0"; // call rax
std::int8_t imm = static_cast<std::int8_t>(40 + OriginalStackParameterCount * 8);
if (OriginalStackParameterCount % 2 != 0)
{
imm += 8;
}
ThunkEpilog += "\x48\x83\xc4";
ThunkEpilog += static_cast<char>(imm); // add rsp, imm
ThunkEpilog += "\xc3"; // ret
return ThunkEpilog;
}
static consteval std::size_t ThunkEpilogSize()
{
return GenerateThunkEpilog().size();
}
static consteval auto ThunkEpilogData()
{
auto StringToArray = []<std::size_t ...Is>(const std::string& str, std::index_sequence<Is...>) { return std::array{ str[Is]... }; };
return StringToArray(GenerateThunkEpilog(), std::make_index_sequence<ThunkEpilogSize()>{});
}
protected:
#pragma pack (push, 1)
struct Trampoline : public Detail::ExecutableNewDeleteAllocator
{
std::array<char, ThunkPrologSize()> ThunkProlog = ThunkPrologData();
std::uint16_t mov_rcx = 0xb948;
std::uint64_t pThis = 0; // mov rcx, pThis
std::uint16_t mov_rax = 0xb848;
std::uint64_t pCallbackProc = 0; // mov rax, pCallbackProc
std::array<char, ThunkEpilogSize()> ThunkEpilog = ThunkEpilogData();
};
#pragma pack (pop)
};
template <typename C, typename F>
requires (stdext::arity_v<std::remove_pointer_t<F>> >= 4 && stdext::arity_v<std::remove_pointer_t<F>> < 15)
class InsertionCallbackThunkImpl<C, F, true>
{
private:
static consteval auto GenerateThunkProlog()
{
std::string ThunkProlog;
std::size_t OriginalStackParameterCount = stdext::arity_v<std::remove_pointer_t<F>> - 4;
if (OriginalStackParameterCount > 0)
{
ThunkProlog += "\x48\x89\xe0"; // mov rax, rsp
}
if (OriginalStackParameterCount % 2 != 0)
{
ThunkProlog += "\x48\x83\xec\x08"; // sub rsp, 8
}
for (size_t i = OriginalStackParameterCount; i > 0; i--)
{
std::int8_t imm = static_cast<std::int8_t>(32 + i * 8);
ThunkProlog += "\xff\x70";
ThunkProlog += static_cast<char>(imm); // push qword ptr [rax+imm]
}
if (std::is_floating_point_v<stdext::parameter_type_t<std::remove_pointer_t<F>, 3>>)
{
ThunkProlog += "\x48\x83\xec\x08\x66\x0f\x13\x1c\x24"; // sub rsp, 8; movlpd qword ptr [rsp], xmm3
}
else
{
ThunkProlog += "\x41\x51"; // push r9
}
ThunkProlog += "\x48\x83\xec\x20"; // sub rsp, 32
if (std::is_floating_point_v<stdext::parameter_type_t<std::remove_pointer_t<F>, 2>>)
{
ThunkProlog += "\x0f\x28\xda"; // movaps xmm3, xmm2
}
else
{
ThunkProlog += "\x4d\x89\xc1"; // mov r9, r8
}
if (std::is_floating_point_v<stdext::parameter_type_t<std::remove_pointer_t<F>, 1>>)
{
ThunkProlog += "\x0f\x28\xd1"; // movaps xmm2, xmm1
}
else
{
ThunkProlog += "\x49\x89\xd0"; // mov r8, rdx
}
if (std::is_floating_point_v<stdext::parameter_type_t<std::remove_pointer_t<F>, 0>>)
{
ThunkProlog += "\x0f\x28\xc8"; // movaps xmm1, xmm0
}
else
{
ThunkProlog += "\x48\x89\xca"; // mov rdx, rcx
}
return ThunkProlog;
}
static consteval std::size_t ThunkPrologSize()
{
return GenerateThunkProlog().size();
}
static consteval auto ThunkPrologData()
{
auto StringToArray = []<std::size_t ...Is>(const std::string& str, std::index_sequence<Is...>) { return std::array{ str[Is]... }; };
return StringToArray(GenerateThunkProlog(), std::make_index_sequence<ThunkPrologSize()>{});
}
static consteval auto GenerateUnwindCodes()
{
std::vector<UNWIND_CODE> UnwindCodes;
std::uint8_t OffsetInProlog = 0;
std::size_t OriginalStackParameterCount = stdext::arity_v<std::remove_pointer_t<F>> - 4;
if (OriginalStackParameterCount > 0)
{
OffsetInProlog += 3; // mov rax, rsp
}
if (OriginalStackParameterCount % 2 != 0)
{
OffsetInProlog += 4;
UnwindCodes.push_back({ OffsetInProlog, 2, 0 }); // sub rsp, 8 (UWOP_ALLOC_SMALL, 8)
}
for (size_t i = OriginalStackParameterCount; i > 0; i--)
{
OffsetInProlog += 3;
UnwindCodes.push_back({ OffsetInProlog, 2, 0 }); // push qword ptr [rax+imm] (UWOP_ALLOC_SMALL, 8)
}
if (std::is_floating_point_v<stdext::parameter_type_t<std::remove_pointer_t<F>, 3>>)
{
OffsetInProlog += 4;
UnwindCodes.push_back({ OffsetInProlog, 2, 0 }); // sub rsp, 8; movlpd qword ptr [rsp], xmm3 (UWOP_ALLOC_SMALL, 8)
OffsetInProlog += 5;
}
else
{
OffsetInProlog += 2;
UnwindCodes.push_back({ OffsetInProlog, 2, 0 }); // push r9 (UWOP_ALLOC_SMALL, 8)
}
OffsetInProlog += 4;
UnwindCodes.push_back({ OffsetInProlog, 2, 3 }); // sub rsp, 32 (UWOP_ALLOC_SMALL, 32)
// movaps xmm3, xmm2 / mov r9, r8
// movaps xmm2, xmm1 / mov r8, rdx
// movaps xmm1, xmm0 / mov rdx, rcx
return UnwindCodes;
}
static consteval std::size_t UnwindInfoSizeOfProlog()
{
return GenerateUnwindCodes().rbegin()->OffsetInProlog;
}
static consteval std::size_t UnwindCodesSize()
{
return GenerateUnwindCodes().size();
}
static consteval std::size_t UnwindCodeArraySize()
{
std::size_t Size = UnwindCodesSize();
return Size % 2 ? Size + 1 : Size;
}
static consteval auto UnwindCodesData()
{
auto VectorToArray = []<std::size_t ...Is>(const std::vector<UNWIND_CODE>& vec, std::index_sequence<Is...>) { return std::array<UNWIND_CODE, UnwindCodeArraySize()>{ vec[sizeof...(Is) - Is - 1]... }; };
return VectorToArray(GenerateUnwindCodes(), std::make_index_sequence<UnwindCodesSize()>{});
}
static consteval auto GenerateThunkEpilog()
{
std::string ThunkEpilog;
std::size_t OriginalStackParameterCount = stdext::arity_v<std::remove_pointer_t<F>> - 4;
ThunkEpilog += "\xff\xd0"; // call rax
std::int8_t imm = static_cast<std::int8_t>(40 + OriginalStackParameterCount * 8);
if (OriginalStackParameterCount % 2 != 0)
{
imm += 8;
}
ThunkEpilog += "\x48\x83\xc4";
ThunkEpilog += static_cast<char>(imm); // add rsp, imm2
ThunkEpilog += "\xc3"; // ret
return ThunkEpilog;
}
static consteval std::size_t ThunkEpilogSize()
{
return GenerateThunkEpilog().size();
}
static consteval auto ThunkEpilogData()
{
auto StringToArray = []<std::size_t ...Is>(const std::string& str, std::index_sequence<Is...>) { return std::array{ str[Is]... }; };
return StringToArray(GenerateThunkEpilog(), std::make_index_sequence<ThunkEpilogSize()>{});
}
protected:
struct UNWIND_CODE
{
std::uint8_t OffsetInProlog;
std::uint8_t UnwindOperationCode : 4;
std::uint8_t OperationInfo : 4;
};
#pragma pack (push, 1)
struct Trampoline : public Detail::ExecutableNewDeleteAllocator
{
std::array<char, ThunkPrologSize()> ThunkProlog = ThunkPrologData();
std::uint16_t mov_rcx = 0xb948;
std::uint64_t pThis = 0; // mov rcx, pThis
std::uint16_t mov_rax = 0xb848;
std::uint64_t pCallbackProc = 0; // mov rax, pCallbackProc
std::array<char, ThunkEpilogSize()> ThunkEpilog = ThunkEpilogData();
alignas(RUNTIME_FUNCTION) RUNTIME_FUNCTION FunctionTable{ 0, ThunkPrologSize() + 20 + ThunkEpilogSize(), offsetof(Trampoline, UnwindInfo)};
alignas(std::uint32_t) struct UNWIND_INFO
{
std::uint8_t Version : 3 = 1;
std::uint8_t Flags : 5 = 0;
std::uint8_t SizeOfProlog = UnwindInfoSizeOfProlog();
std::uint8_t CountOfUnwindCodes = UnwindCodesSize();
std::uint8_t FrameRegister : 4 = 0;
std::uint8_t FrameRegisterOffset : 4 = 0;
std::array<UNWIND_CODE, UnwindCodeArraySize()> UnwindCodes = UnwindCodesData();
} UnwindInfo;
};
#pragma pack (pop)
};
template <typename C, typename F, bool b>
requires (stdext::arity_v<std::remove_pointer_t<F>> >= 15)
class InsertionCallbackThunkImpl<C, F, b>
{
protected:
static_assert(stdext::always_false_v<C, F, decltype(b)>, "Too many parameters in the callback function.");
struct Trampoline : public Detail::ExecutableNewDeleteAllocator
{
std::uint64_t pThis = 0;
std::uint64_t pCallbackProc = 0;
};
};
template <typename C, typename F>
requires std::is_class_v<C> && stdext::is_function_pointer_v<F> && stdext::is_x64call_v<std::remove_pointer_t<F>>
class InsertionCallbackThunk : private InsertionCallbackThunkImpl<C, F, bGenerateFunctionTable>
{
public:
InsertionCallbackThunk(C* pThis, stdext::add_thiscall_t<std::remove_pointer_t<F> C::*> pCallbackProc) :
m_pTrampoline(new InsertionCallbackThunkImpl<C, F, bGenerateFunctionTable>::Trampoline{ .pThis = reinterpret_cast<std::uint64_t>(pThis), .pCallbackProc = *reinterpret_cast<std::uint64_t*>(&pCallbackProc) })
{
FlushInstructionCache(GetCurrentProcess(), m_pTrampoline, sizeof(*m_pTrampoline));
if constexpr (bGenerateFunctionTable && stdext::arity_v<std::remove_pointer_t<F>> >= 4 && stdext::arity_v<std::remove_pointer_t<F>> < 15)
{
RtlAddFunctionTable(&m_pTrampoline->FunctionTable, 1, reinterpret_cast<DWORD64>(m_pTrampoline));
}
}
~InsertionCallbackThunk()
{
if constexpr (bGenerateFunctionTable && stdext::arity_v<std::remove_pointer_t<F>> >= 4 && stdext::arity_v<std::remove_pointer_t<F>> < 15)
{
RtlDeleteFunctionTable(&m_pTrampoline->FunctionTable);
}
delete m_pTrampoline;
}
F GetAddress() const noexcept
{
return reinterpret_cast<F>(m_pTrampoline);
}
private:
InsertionCallbackThunkImpl<C, F, bGenerateFunctionTable>::Trampoline* m_pTrampoline;
};
#endif
// Extension to C++ standard library
#pragma once
#include <type_traits>
namespace stdext
{
/*
A dependent type that is always false_type to force static_assert to fail
*/
template <typename ...>
struct always_false : std::false_type {};
template <>
struct always_false<decltype([] {}) > : std::true_type {};
template <typename ...Ts>
inline constexpr bool always_false_v = always_false<Ts...>::value;
/*
An empty type to hold a parameter pack
*/
template <typename ...>
struct type_pack {};
/*
Get the type count in a type_pack
Example:
constexpr auto i = type_count_v<type_pack<int, float, chat>>; // i == 3
*/
template <typename>
struct type_count;
template <typename ...Args>
struct type_count<type_pack<Args...>>
{
static constexpr std::size_t value = sizeof...(Args);
};
template <typename T>
inline constexpr std::size_t type_count_v = type_count<T>::value;
/*
Get the Ith type in a type_pack
Example:
using T = get_t<type_pack<int, float, char>, 1>; // T is float
*/
template <typename, std::size_t>
struct get;
template <typename T, typename ...Ts, std::size_t I>
struct get<type_pack<T, Ts...>, I>
{
static_assert(I < sizeof...(Ts) + 1, "Index out of range.");
using type = get<type_pack<Ts...>, I - 1>::type;
};
template <typename T, typename ...Ts>
struct get<type_pack<T, Ts...>, 0>
{
using type = T;
};
template <typename T, std::size_t I>
using get_t = get<T, I>::type;
namespace detail
{
#if defined(_M_IX86) || defined(_M_X64)
/*
function_info related enumerations
*/
enum class calling_convention_category { cdecl_, stdcall, fastcall, vectorcall, thiscall, x64call };
enum class cv_qualifier_category { none, const_, volatile_, const_volatile_ };
enum class ref_qualifier_category { none, lvalue, rvalue };
/*
A helper class to hold information about a function or a pointer to member function
*/
template <calling_convention_category cc, cv_qualifier_category cv, ref_qualifier_category r, bool b1, bool b2, typename C, typename R, typename ...Args>
struct function_info
{
static constexpr calling_convention_category calling_convention = cc;
static constexpr cv_qualifier_category cv_qualifier = cv;
static constexpr ref_qualifier_category ref_qualifier = r;
static constexpr bool is_noexcept = b1;
static constexpr bool is_vararg = b2;
using class_type = C;
using return_type = R;
using parameter_types = type_pack<Args...>;
};
/*
Make function_info from type_pack
*/
template <calling_convention_category, cv_qualifier_category, ref_qualifier_category, bool, bool, typename, typename, typename>
struct make_function_info;
template <calling_convention_category cc, cv_qualifier_category cv, ref_qualifier_category r, bool b1, bool b2, typename C, typename R, typename ...Args>
struct make_function_info<cc, cv, r, b1, b2, C, R, type_pack<Args...>>
{
using type = function_info<cc, cv, r, b1, b2, C, R, Args...>;
};
template <calling_convention_category cc, cv_qualifier_category cv, ref_qualifier_category r, bool b1, bool b2, typename C, typename R, typename T>
using make_function_info_t = make_function_info<cc, cv, r, b1, b2, C, R, T>::type;
/*
Disassemble functions and pointer to member functions into function_info
*/
template <typename F>
struct disassemble_function;
#if defined(_M_IX86)
// cdecl functions
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...)>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::none, ref_qualifier_category::none, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) const>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_, ref_qualifier_category::none, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) volatile>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::volatile_, ref_qualifier_category::none, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) const volatile>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_volatile_, ref_qualifier_category::none, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...)&>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::none, ref_qualifier_category::lvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) const&>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_, ref_qualifier_category::lvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) volatile&>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::volatile_, ref_qualifier_category::lvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) const volatile&>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_volatile_, ref_qualifier_category::lvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...)&&>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::none, ref_qualifier_category::rvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) const&&>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_, ref_qualifier_category::rvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) volatile&&>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::volatile_, ref_qualifier_category::rvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) const volatile&&>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_volatile_, ref_qualifier_category::rvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::none, ref_qualifier_category::none, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) const noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_, ref_qualifier_category::none, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) volatile noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::volatile_, ref_qualifier_category::none, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) const volatile noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_volatile_, ref_qualifier_category::none, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) & noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::none, ref_qualifier_category::lvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) const& noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_, ref_qualifier_category::lvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) volatile& noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::volatile_, ref_qualifier_category::lvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) const volatile& noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_volatile_, ref_qualifier_category::lvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) && noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::none, ref_qualifier_category::rvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) const&& noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_, ref_qualifier_category::rvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) volatile&& noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::volatile_, ref_qualifier_category::rvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) const volatile&& noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_volatile_, ref_qualifier_category::rvalue, true, false, void, R, Args...>;
};
// cdecl pointer to member functions
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...)>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::none, ref_qualifier_category::none, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) const>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_, ref_qualifier_category::none, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) volatile>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::volatile_, ref_qualifier_category::none, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) const volatile>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_volatile_, ref_qualifier_category::none, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...)&>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::none, ref_qualifier_category::lvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) const&>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_, ref_qualifier_category::lvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) volatile&>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::volatile_, ref_qualifier_category::lvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) const volatile&>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_volatile_, ref_qualifier_category::lvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...)&&>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::none, ref_qualifier_category::rvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) const&&>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_, ref_qualifier_category::rvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) volatile&&>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::volatile_, ref_qualifier_category::rvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) const volatile&&>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_volatile_, ref_qualifier_category::rvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::none, ref_qualifier_category::none, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) const noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_, ref_qualifier_category::none, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) volatile noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::volatile_, ref_qualifier_category::none, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) const volatile noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_volatile_, ref_qualifier_category::none, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) & noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::none, ref_qualifier_category::lvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) const& noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_, ref_qualifier_category::lvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) volatile& noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::volatile_, ref_qualifier_category::lvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) const volatile& noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_volatile_, ref_qualifier_category::lvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) && noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::none, ref_qualifier_category::rvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) const&& noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_, ref_qualifier_category::rvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) volatile&& noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::volatile_, ref_qualifier_category::rvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) const volatile&& noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_volatile_, ref_qualifier_category::rvalue, true, false, C, R, Args...>;
};
// cdecl variadic functions
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......)>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::none, ref_qualifier_category::none, false, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) const>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_, ref_qualifier_category::none, false, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) volatile>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::volatile_, ref_qualifier_category::none, false, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) const volatile>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_volatile_, ref_qualifier_category::none, false, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......)&>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::none, ref_qualifier_category::lvalue, false, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) const&>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_, ref_qualifier_category::lvalue, false, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) volatile&>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::volatile_, ref_qualifier_category::lvalue, false, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) const volatile&>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_volatile_, ref_qualifier_category::lvalue, false, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......)&&>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::none, ref_qualifier_category::rvalue, false, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) const&&>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_, ref_qualifier_category::rvalue, false, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) volatile&&>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::volatile_, ref_qualifier_category::rvalue, false, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) const volatile&&>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_volatile_, ref_qualifier_category::rvalue, false, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::none, ref_qualifier_category::none, true, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) const noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_, ref_qualifier_category::none, true, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) volatile noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::volatile_, ref_qualifier_category::none, true, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) const volatile noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_volatile_, ref_qualifier_category::none, true, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) & noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::none, ref_qualifier_category::lvalue, true, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) const& noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_, ref_qualifier_category::lvalue, true, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) volatile& noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::volatile_, ref_qualifier_category::lvalue, true, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) const volatile& noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_volatile_, ref_qualifier_category::lvalue, true, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) && noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::none, ref_qualifier_category::rvalue, true, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) const&& noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_, ref_qualifier_category::rvalue, true, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) volatile&& noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::volatile_, ref_qualifier_category::rvalue, true, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) const volatile&& noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_volatile_, ref_qualifier_category::rvalue, true, true, void, R, Args...>;
};
// cdecl pointer to variadic member functions
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......)>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::none, ref_qualifier_category::none, false, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) const>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_, ref_qualifier_category::none, false, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) volatile>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::volatile_, ref_qualifier_category::none, false, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) const volatile>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_volatile_, ref_qualifier_category::none, false, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......)&>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::none, ref_qualifier_category::lvalue, false, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) const&>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_, ref_qualifier_category::lvalue, false, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) volatile&>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::volatile_, ref_qualifier_category::lvalue, false, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) const volatile&>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_volatile_, ref_qualifier_category::lvalue, false, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......)&&>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::none, ref_qualifier_category::rvalue, false, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) const&&>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_, ref_qualifier_category::rvalue, false, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) volatile&&>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::volatile_, ref_qualifier_category::rvalue, false, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) const volatile&&>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_volatile_, ref_qualifier_category::rvalue, false, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::none, ref_qualifier_category::none, true, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) const noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_, ref_qualifier_category::none, true, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) volatile noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::volatile_, ref_qualifier_category::none, true, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) const volatile noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_volatile_, ref_qualifier_category::none, true, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) & noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::none, ref_qualifier_category::lvalue, true, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) const& noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_, ref_qualifier_category::lvalue, true, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) volatile& noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::volatile_, ref_qualifier_category::lvalue, true, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) const volatile& noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_volatile_, ref_qualifier_category::lvalue, true, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) && noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::none, ref_qualifier_category::rvalue, true, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) const&& noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_, ref_qualifier_category::rvalue, true, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) volatile&& noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::volatile_, ref_qualifier_category::rvalue, true, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) const volatile&& noexcept>
{
using type = function_info<calling_convention_category::cdecl_, cv_qualifier_category::const_volatile_, ref_qualifier_category::rvalue, true, true, C, R, Args...>;
};
// stdcall functions
template <typename R, typename ...Args>
struct disassemble_function<R __stdcall (Args...)>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::none, ref_qualifier_category::none, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __stdcall (Args...) const>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::const_, ref_qualifier_category::none, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __stdcall (Args...) volatile>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::volatile_, ref_qualifier_category::none, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __stdcall (Args...) const volatile>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::none, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __stdcall (Args...)&>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::none, ref_qualifier_category::lvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __stdcall (Args...) const&>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::const_, ref_qualifier_category::lvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __stdcall (Args...) volatile&>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::volatile_, ref_qualifier_category::lvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __stdcall (Args...) const volatile&>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::lvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __stdcall (Args...)&&>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::none, ref_qualifier_category::rvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __stdcall (Args...) const&&>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::const_, ref_qualifier_category::rvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __stdcall (Args...) volatile&&>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::volatile_, ref_qualifier_category::rvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __stdcall (Args...) const volatile&&>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::rvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __stdcall (Args...) noexcept>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::none, ref_qualifier_category::none, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __stdcall (Args...) const noexcept>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::const_, ref_qualifier_category::none, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __stdcall (Args...) volatile noexcept>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::volatile_, ref_qualifier_category::none, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __stdcall (Args...) const volatile noexcept>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::none, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __stdcall (Args...) & noexcept>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::none, ref_qualifier_category::lvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __stdcall (Args...) const& noexcept>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::const_, ref_qualifier_category::lvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __stdcall (Args...) volatile& noexcept>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::volatile_, ref_qualifier_category::lvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __stdcall (Args...) const volatile& noexcept>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::lvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __stdcall (Args...) && noexcept>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::none, ref_qualifier_category::rvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __stdcall (Args...) const&& noexcept>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::const_, ref_qualifier_category::rvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __stdcall (Args...) volatile&& noexcept>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::volatile_, ref_qualifier_category::rvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __stdcall (Args...) const volatile&& noexcept>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::rvalue, true, false, void, R, Args...>;
};
// stdcall pointer to member functions
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__stdcall C::*)(Args...)>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::none, ref_qualifier_category::none, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__stdcall C::*)(Args...) const>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::const_, ref_qualifier_category::none, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__stdcall C::*)(Args...) volatile>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::volatile_, ref_qualifier_category::none, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__stdcall C::*)(Args...) const volatile>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::none, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__stdcall C::*)(Args...)&>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::none, ref_qualifier_category::lvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__stdcall C::*)(Args...) const&>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::const_, ref_qualifier_category::lvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__stdcall C::*)(Args...) volatile&>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::volatile_, ref_qualifier_category::lvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__stdcall C::*)(Args...) const volatile&>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::lvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__stdcall C::*)(Args...)&&>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::none, ref_qualifier_category::rvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__stdcall C::*)(Args...) const&&>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::const_, ref_qualifier_category::rvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__stdcall C::*)(Args...) volatile&&>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::volatile_, ref_qualifier_category::rvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__stdcall C::*)(Args...) const volatile&&>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::rvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__stdcall C::*)(Args...) noexcept>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::none, ref_qualifier_category::none, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__stdcall C::*)(Args...) const noexcept>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::const_, ref_qualifier_category::none, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__stdcall C::*)(Args...) volatile noexcept>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::volatile_, ref_qualifier_category::none, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__stdcall C::*)(Args...) const volatile noexcept>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::none, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__stdcall C::*)(Args...) & noexcept>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::none, ref_qualifier_category::lvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__stdcall C::*)(Args...) const& noexcept>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::const_, ref_qualifier_category::lvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__stdcall C::*)(Args...) volatile& noexcept>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::volatile_, ref_qualifier_category::lvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__stdcall C::*)(Args...) const volatile& noexcept>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::lvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__stdcall C::*)(Args...) && noexcept>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::none, ref_qualifier_category::rvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__stdcall C::*)(Args...) const&& noexcept>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::const_, ref_qualifier_category::rvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__stdcall C::*)(Args...) volatile&& noexcept>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::volatile_, ref_qualifier_category::rvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__stdcall C::*)(Args...) const volatile&& noexcept>
{
using type = function_info<calling_convention_category::stdcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::rvalue, true, false, C, R, Args...>;
};
// fastcall functions
template <typename R, typename ...Args>
struct disassemble_function<R __fastcall (Args...)>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::none, ref_qualifier_category::none, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __fastcall (Args...) const>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::const_, ref_qualifier_category::none, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __fastcall (Args...) volatile>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::volatile_, ref_qualifier_category::none, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __fastcall (Args...) const volatile>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::none, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __fastcall (Args...)&>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::none, ref_qualifier_category::lvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __fastcall (Args...) const&>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::const_, ref_qualifier_category::lvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __fastcall (Args...) volatile&>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::volatile_, ref_qualifier_category::lvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __fastcall (Args...) const volatile&>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::lvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __fastcall (Args...)&&>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::none, ref_qualifier_category::rvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __fastcall (Args...) const&&>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::const_, ref_qualifier_category::rvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __fastcall (Args...) volatile&&>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::volatile_, ref_qualifier_category::rvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __fastcall (Args...) const volatile&&>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::rvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __fastcall (Args...) noexcept>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::none, ref_qualifier_category::none, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __fastcall (Args...) const noexcept>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::const_, ref_qualifier_category::none, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __fastcall (Args...) volatile noexcept>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::volatile_, ref_qualifier_category::none, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __fastcall (Args...) const volatile noexcept>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::none, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __fastcall (Args...) & noexcept>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::none, ref_qualifier_category::lvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __fastcall (Args...) const& noexcept>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::const_, ref_qualifier_category::lvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __fastcall (Args...) volatile& noexcept>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::volatile_, ref_qualifier_category::lvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __fastcall (Args...) const volatile& noexcept>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::lvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __fastcall (Args...) && noexcept>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::none, ref_qualifier_category::rvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __fastcall (Args...) const&& noexcept>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::const_, ref_qualifier_category::rvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __fastcall (Args...) volatile&& noexcept>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::volatile_, ref_qualifier_category::rvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __fastcall (Args...) const volatile&& noexcept>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::rvalue, true, false, void, R, Args...>;
};
// fastcall pointer to member functions
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__fastcall C::*)(Args...)>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::none, ref_qualifier_category::none, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__fastcall C::*)(Args...) const>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::const_, ref_qualifier_category::none, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__fastcall C::*)(Args...) volatile>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::volatile_, ref_qualifier_category::none, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__fastcall C::*)(Args...) const volatile>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::none, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__fastcall C::*)(Args...)&>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::none, ref_qualifier_category::lvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__fastcall C::*)(Args...) const&>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::const_, ref_qualifier_category::lvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__fastcall C::*)(Args...) volatile&>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::volatile_, ref_qualifier_category::lvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__fastcall C::*)(Args...) const volatile&>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::lvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__fastcall C::*)(Args...)&&>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::none, ref_qualifier_category::rvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__fastcall C::*)(Args...) const&&>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::const_, ref_qualifier_category::rvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__fastcall C::*)(Args...) volatile&&>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::volatile_, ref_qualifier_category::rvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__fastcall C::*)(Args...) const volatile&&>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::rvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__fastcall C::*)(Args...) noexcept>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::none, ref_qualifier_category::none, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__fastcall C::*)(Args...) const noexcept>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::const_, ref_qualifier_category::none, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__fastcall C::*)(Args...) volatile noexcept>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::volatile_, ref_qualifier_category::none, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__fastcall C::*)(Args...) const volatile noexcept>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::none, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__fastcall C::*)(Args...) & noexcept>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::none, ref_qualifier_category::lvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__fastcall C::*)(Args...) const& noexcept>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::const_, ref_qualifier_category::lvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__fastcall C::*)(Args...) volatile& noexcept>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::volatile_, ref_qualifier_category::lvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__fastcall C::*)(Args...) const volatile& noexcept>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::lvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__fastcall C::*)(Args...) && noexcept>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::none, ref_qualifier_category::rvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__fastcall C::*)(Args...) const&& noexcept>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::const_, ref_qualifier_category::rvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__fastcall C::*)(Args...) volatile&& noexcept>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::volatile_, ref_qualifier_category::rvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__fastcall C::*)(Args...) const volatile&& noexcept>
{
using type = function_info<calling_convention_category::fastcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::rvalue, true, false, C, R, Args...>;
};
// vectorcall functions
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...)>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::none, ref_qualifier_category::none, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) const>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_, ref_qualifier_category::none, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) volatile>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::volatile_, ref_qualifier_category::none, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) const volatile>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::none, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...)&>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::none, ref_qualifier_category::lvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) const&>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_, ref_qualifier_category::lvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) volatile&>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::volatile_, ref_qualifier_category::lvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) const volatile&>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::lvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...)&&>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::none, ref_qualifier_category::rvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) const&&>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_, ref_qualifier_category::rvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) volatile&&>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::volatile_, ref_qualifier_category::rvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) const volatile&&>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::rvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::none, ref_qualifier_category::none, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) const noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_, ref_qualifier_category::none, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) volatile noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::volatile_, ref_qualifier_category::none, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) const volatile noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::none, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) & noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::none, ref_qualifier_category::lvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) const& noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_, ref_qualifier_category::lvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) volatile& noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::volatile_, ref_qualifier_category::lvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) const volatile& noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::lvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) && noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::none, ref_qualifier_category::rvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) const&& noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_, ref_qualifier_category::rvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) volatile&& noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::volatile_, ref_qualifier_category::rvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) const volatile&& noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::rvalue, true, false, void, R, Args...>;
};
// vectorcall pointer to member functions
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...)>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::none, ref_qualifier_category::none, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) const>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_, ref_qualifier_category::none, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) volatile>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::volatile_, ref_qualifier_category::none, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) const volatile>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::none, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...)&>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::none, ref_qualifier_category::lvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) const&>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_, ref_qualifier_category::lvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) volatile&>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::volatile_, ref_qualifier_category::lvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) const volatile&>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::lvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...)&&>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::none, ref_qualifier_category::rvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) const&&>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_, ref_qualifier_category::rvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) volatile&&>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::volatile_, ref_qualifier_category::rvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) const volatile&&>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::rvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::none, ref_qualifier_category::none, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) const noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_, ref_qualifier_category::none, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) volatile noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::volatile_, ref_qualifier_category::none, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) const volatile noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::none, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) & noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::none, ref_qualifier_category::lvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) const& noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_, ref_qualifier_category::lvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) volatile& noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::volatile_, ref_qualifier_category::lvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) const volatile& noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::lvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) && noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::none, ref_qualifier_category::rvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) const&& noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_, ref_qualifier_category::rvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) volatile&& noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::volatile_, ref_qualifier_category::rvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) const volatile&& noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::rvalue, true, false, C, R, Args...>;
};
// thiscall pointer to member function
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__thiscall C::*)(Args...)>
{
using type = function_info<calling_convention_category::thiscall, cv_qualifier_category::none, ref_qualifier_category::none, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__thiscall C::*)(Args...) const>
{
using type = function_info<calling_convention_category::thiscall, cv_qualifier_category::const_, ref_qualifier_category::none, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__thiscall C::*)(Args...) volatile>
{
using type = function_info<calling_convention_category::thiscall, cv_qualifier_category::volatile_, ref_qualifier_category::none, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__thiscall C::*)(Args...) const volatile>
{
using type = function_info<calling_convention_category::thiscall, cv_qualifier_category::const_volatile_, ref_qualifier_category::none, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__thiscall C::*)(Args...)&>
{
using type = function_info<calling_convention_category::thiscall, cv_qualifier_category::none, ref_qualifier_category::lvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__thiscall C::*)(Args...) const&>
{
using type = function_info<calling_convention_category::thiscall, cv_qualifier_category::const_, ref_qualifier_category::lvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__thiscall C::*)(Args...) volatile&>
{
using type = function_info<calling_convention_category::thiscall, cv_qualifier_category::volatile_, ref_qualifier_category::lvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__thiscall C::*)(Args...) const volatile&>
{
using type = function_info<calling_convention_category::thiscall, cv_qualifier_category::const_volatile_, ref_qualifier_category::lvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__thiscall C::*)(Args...)&&>
{
using type = function_info<calling_convention_category::thiscall, cv_qualifier_category::none, ref_qualifier_category::rvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__thiscall C::*)(Args...) const&&>
{
using type = function_info<calling_convention_category::thiscall, cv_qualifier_category::const_, ref_qualifier_category::rvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__thiscall C::*)(Args...) volatile&&>
{
using type = function_info<calling_convention_category::thiscall, cv_qualifier_category::volatile_, ref_qualifier_category::rvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__thiscall C::*)(Args...) const volatile&&>
{
using type = function_info<calling_convention_category::thiscall, cv_qualifier_category::const_volatile_, ref_qualifier_category::rvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__thiscall C::*)(Args...) noexcept>
{
using type = function_info<calling_convention_category::thiscall, cv_qualifier_category::none, ref_qualifier_category::none, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__thiscall C::*)(Args...) const noexcept>
{
using type = function_info<calling_convention_category::thiscall, cv_qualifier_category::const_, ref_qualifier_category::none, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__thiscall C::*)(Args...) volatile noexcept>
{
using type = function_info<calling_convention_category::thiscall, cv_qualifier_category::volatile_, ref_qualifier_category::none, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__thiscall C::*)(Args...) const volatile noexcept>
{
using type = function_info<calling_convention_category::thiscall, cv_qualifier_category::const_volatile_, ref_qualifier_category::none, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__thiscall C::*)(Args...) & noexcept>
{
using type = function_info<calling_convention_category::thiscall, cv_qualifier_category::none, ref_qualifier_category::lvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__thiscall C::*)(Args...) const& noexcept>
{
using type = function_info<calling_convention_category::thiscall, cv_qualifier_category::const_, ref_qualifier_category::lvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__thiscall C::*)(Args...) volatile& noexcept>
{
using type = function_info<calling_convention_category::thiscall, cv_qualifier_category::volatile_, ref_qualifier_category::lvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__thiscall C::*)(Args...) const volatile& noexcept>
{
using type = function_info<calling_convention_category::thiscall, cv_qualifier_category::const_volatile_, ref_qualifier_category::lvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__thiscall C::*)(Args...) && noexcept>
{
using type = function_info<calling_convention_category::thiscall, cv_qualifier_category::none, ref_qualifier_category::rvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__thiscall C::*)(Args...) const&& noexcept>
{
using type = function_info<calling_convention_category::thiscall, cv_qualifier_category::const_, ref_qualifier_category::rvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__thiscall C::*)(Args...) volatile&& noexcept>
{
using type = function_info<calling_convention_category::thiscall, cv_qualifier_category::volatile_, ref_qualifier_category::rvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__thiscall C::*)(Args...) const volatile&& noexcept>
{
using type = function_info<calling_convention_category::thiscall, cv_qualifier_category::const_volatile_, ref_qualifier_category::rvalue, true, false, C, R, Args...>;
};
#elif defined(_M_X64)
// x64call functions
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...)>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::none, ref_qualifier_category::none, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) const>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_, ref_qualifier_category::none, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) volatile>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::volatile_, ref_qualifier_category::none, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) const volatile>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_volatile_, ref_qualifier_category::none, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...)&>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::none, ref_qualifier_category::lvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) const&>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_, ref_qualifier_category::lvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) volatile&>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::volatile_, ref_qualifier_category::lvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) const volatile&>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_volatile_, ref_qualifier_category::lvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...)&&>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::none, ref_qualifier_category::rvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) const&&>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_, ref_qualifier_category::rvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) volatile&&>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::volatile_, ref_qualifier_category::rvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) const volatile&&>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_volatile_, ref_qualifier_category::rvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::none, ref_qualifier_category::none, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) const noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_, ref_qualifier_category::none, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) volatile noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::volatile_, ref_qualifier_category::none, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) const volatile noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_volatile_, ref_qualifier_category::none, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) & noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::none, ref_qualifier_category::lvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) const& noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_, ref_qualifier_category::lvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) volatile& noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::volatile_, ref_qualifier_category::lvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) const volatile& noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_volatile_, ref_qualifier_category::lvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) && noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::none, ref_qualifier_category::rvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) const&& noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_, ref_qualifier_category::rvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) volatile&& noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::volatile_, ref_qualifier_category::rvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args...) const volatile&& noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_volatile_, ref_qualifier_category::rvalue, true, false, void, R, Args...>;
};
// x64call pointer to member functions
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...)>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::none, ref_qualifier_category::none, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) const>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_, ref_qualifier_category::none, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) volatile>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::volatile_, ref_qualifier_category::none, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) const volatile>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_volatile_, ref_qualifier_category::none, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...)&>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::none, ref_qualifier_category::lvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) const&>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_, ref_qualifier_category::lvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) volatile&>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::volatile_, ref_qualifier_category::lvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) const volatile&>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_volatile_, ref_qualifier_category::lvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...)&&>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::none, ref_qualifier_category::rvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) const&&>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_, ref_qualifier_category::rvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) volatile&&>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::volatile_, ref_qualifier_category::rvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) const volatile&&>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_volatile_, ref_qualifier_category::rvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::none, ref_qualifier_category::none, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) const noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_, ref_qualifier_category::none, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) volatile noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::volatile_, ref_qualifier_category::none, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) const volatile noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_volatile_, ref_qualifier_category::none, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) & noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::none, ref_qualifier_category::lvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) const& noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_, ref_qualifier_category::lvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) volatile& noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::volatile_, ref_qualifier_category::lvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) const volatile& noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_volatile_, ref_qualifier_category::lvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) && noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::none, ref_qualifier_category::rvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) const&& noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_, ref_qualifier_category::rvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) volatile&& noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::volatile_, ref_qualifier_category::rvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args...) const volatile&& noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_volatile_, ref_qualifier_category::rvalue, true, false, C, R, Args...>;
};
// x64call variadic functions
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......)>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::none, ref_qualifier_category::none, false, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) const>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_, ref_qualifier_category::none, false, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) volatile>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::volatile_, ref_qualifier_category::none, false, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) const volatile>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_volatile_, ref_qualifier_category::none, false, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......)&>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::none, ref_qualifier_category::lvalue, false, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) const&>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_, ref_qualifier_category::lvalue, false, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) volatile&>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::volatile_, ref_qualifier_category::lvalue, false, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) const volatile&>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_volatile_, ref_qualifier_category::lvalue, false, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......)&&>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::none, ref_qualifier_category::rvalue, false, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) const&&>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_, ref_qualifier_category::rvalue, false, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) volatile&&>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::volatile_, ref_qualifier_category::rvalue, false, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) const volatile&&>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_volatile_, ref_qualifier_category::rvalue, false, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::none, ref_qualifier_category::none, true, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) const noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_, ref_qualifier_category::none, true, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) volatile noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::volatile_, ref_qualifier_category::none, true, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) const volatile noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_volatile_, ref_qualifier_category::none, true, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) & noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::none, ref_qualifier_category::lvalue, true, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) const& noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_, ref_qualifier_category::lvalue, true, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) volatile& noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::volatile_, ref_qualifier_category::lvalue, true, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) const volatile& noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_volatile_, ref_qualifier_category::lvalue, true, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) && noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::none, ref_qualifier_category::rvalue, true, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) const&& noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_, ref_qualifier_category::rvalue, true, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) volatile&& noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::volatile_, ref_qualifier_category::rvalue, true, true, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __cdecl (Args......) const volatile&& noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_volatile_, ref_qualifier_category::rvalue, true, true, void, R, Args...>;
};
// x64call pointer to variadic member functions
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......)>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::none, ref_qualifier_category::none, false, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) const>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_, ref_qualifier_category::none, false, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) volatile>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::volatile_, ref_qualifier_category::none, false, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) const volatile>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_volatile_, ref_qualifier_category::none, false, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......)&>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::none, ref_qualifier_category::lvalue, false, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) const&>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_, ref_qualifier_category::lvalue, false, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) volatile&>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::volatile_, ref_qualifier_category::lvalue, false, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) const volatile&>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_volatile_, ref_qualifier_category::lvalue, false, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......)&&>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::none, ref_qualifier_category::rvalue, false, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) const&&>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_, ref_qualifier_category::rvalue, false, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) volatile&&>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::volatile_, ref_qualifier_category::rvalue, false, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) const volatile&&>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_volatile_, ref_qualifier_category::rvalue, false, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::none, ref_qualifier_category::none, true, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) const noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_, ref_qualifier_category::none, true, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) volatile noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::volatile_, ref_qualifier_category::none, true, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) const volatile noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_volatile_, ref_qualifier_category::none, true, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) & noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::none, ref_qualifier_category::lvalue, true, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) const& noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_, ref_qualifier_category::lvalue, true, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) volatile& noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::volatile_, ref_qualifier_category::lvalue, true, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) const volatile& noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_volatile_, ref_qualifier_category::lvalue, true, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) && noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::none, ref_qualifier_category::rvalue, true, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) const&& noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_, ref_qualifier_category::rvalue, true, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) volatile&& noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::volatile_, ref_qualifier_category::rvalue, true, true, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__cdecl C::*)(Args......) const volatile&& noexcept>
{
using type = function_info<calling_convention_category::x64call, cv_qualifier_category::const_volatile_, ref_qualifier_category::rvalue, true, true, C, R, Args...>;
};
// vectorcall functions
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...)>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::none, ref_qualifier_category::none, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) const>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_, ref_qualifier_category::none, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) volatile>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::volatile_, ref_qualifier_category::none, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) const volatile>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::none, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...)&>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::none, ref_qualifier_category::lvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) const&>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_, ref_qualifier_category::lvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) volatile&>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::volatile_, ref_qualifier_category::lvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) const volatile&>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::lvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...)&&>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::none, ref_qualifier_category::rvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) const&&>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_, ref_qualifier_category::rvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) volatile&&>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::volatile_, ref_qualifier_category::rvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) const volatile&&>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::rvalue, false, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::none, ref_qualifier_category::none, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) const noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_, ref_qualifier_category::none, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) volatile noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::volatile_, ref_qualifier_category::none, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) const volatile noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::none, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) & noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::none, ref_qualifier_category::lvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) const& noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_, ref_qualifier_category::lvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) volatile& noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::volatile_, ref_qualifier_category::lvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) const volatile& noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::lvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) && noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::none, ref_qualifier_category::rvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) const&& noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_, ref_qualifier_category::rvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) volatile&& noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::volatile_, ref_qualifier_category::rvalue, true, false, void, R, Args...>;
};
template <typename R, typename ...Args>
struct disassemble_function<R __vectorcall (Args...) const volatile&& noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::rvalue, true, false, void, R, Args...>;
};
// vectorcall pointer to member functions
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...)>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::none, ref_qualifier_category::none, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) const>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_, ref_qualifier_category::none, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) volatile>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::volatile_, ref_qualifier_category::none, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) const volatile>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::none, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...)&>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::none, ref_qualifier_category::lvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) const&>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_, ref_qualifier_category::lvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) volatile&>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::volatile_, ref_qualifier_category::lvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) const volatile&>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::lvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...)&&>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::none, ref_qualifier_category::rvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) const&&>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_, ref_qualifier_category::rvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) volatile&&>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::volatile_, ref_qualifier_category::rvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) const volatile&&>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::rvalue, false, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::none, ref_qualifier_category::none, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) const noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_, ref_qualifier_category::none, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) volatile noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::volatile_, ref_qualifier_category::none, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) const volatile noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::none, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) & noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::none, ref_qualifier_category::lvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) const& noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_, ref_qualifier_category::lvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) volatile& noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::volatile_, ref_qualifier_category::lvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) const volatile& noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::lvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) && noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::none, ref_qualifier_category::rvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) const&& noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_, ref_qualifier_category::rvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) volatile&& noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::volatile_, ref_qualifier_category::rvalue, true, false, C, R, Args...>;
};
template <typename R, typename C, typename ...Args>
struct disassemble_function<R(__vectorcall C::*)(Args...) const volatile&& noexcept>
{
using type = function_info<calling_convention_category::vectorcall, cv_qualifier_category::const_volatile_, ref_qualifier_category::rvalue, true, false, C, R, Args...>;
};
#endif
template <typename F>
using disassemble_function_t = disassemble_function<F>::type;
/*
Assemble functions and pointer to member functions from function_info
*/
template <typename T>
struct assemble_function
{
private:
// Assemble a function from return type and parameter list
template <bool, typename, typename>
struct make_function;
template <bool b, typename R, typename ...Args>
struct make_function<b, R, type_pack<Args...>>
{
using type = std::conditional_t<b, R(Args......), R(Args...)>;
};
// Add cv qualifiers to a function. Must be called immediately after make_function
template <typename, cv_qualifier_category>
struct add_cv;
template <typename R, typename ...Args, cv_qualifier_category cv>
struct add_cv<R(Args...), cv>
{
using type =
std::conditional_t<cv == cv_qualifier_category::const_, R(Args...) const,
std::conditional_t<cv == cv_qualifier_category::volatile_, R(Args...) volatile,
std::conditional_t<cv == cv_qualifier_category::const_volatile_, R(Args...) const volatile, R(Args...)>>>;
};
template <typename R, typename ...Args, cv_qualifier_category cv>
struct add_cv<R(Args......), cv>
{
using type =
std::conditional_t<cv == cv_qualifier_category::const_, R(Args......) const,
std::conditional_t<cv == cv_qualifier_category::volatile_, R(Args......) volatile,
std::conditional_t<cv == cv_qualifier_category::const_volatile_, R(Args......) const volatile, R(Args......)>>>;
};
// Add ref qualifiers to a function. Must be called immediately after add_cv
template <typename F, ref_qualifier_category r>
struct add_ref;
template <typename R, typename ...Args, ref_qualifier_category r>
struct add_ref<R(Args...), r>
{
using type =
std::conditional_t<r == ref_qualifier_category::lvalue, R(Args...)&,
std::conditional_t<r == ref_qualifier_category::rvalue, R(Args...)&&, R(Args...)>>;
};
template <typename R, typename ...Args, ref_qualifier_category r>
struct add_ref<R(Args...) const, r>
{
using type =
std::conditional_t<r == ref_qualifier_category::lvalue, R(Args...) const&,
std::conditional_t<r == ref_qualifier_category::rvalue, R(Args...) const&&, R(Args...) const>>;
};
template <typename R, typename ...Args, ref_qualifier_category r>
struct add_ref<R(Args...) volatile, r>
{
using type =
std::conditional_t<r == ref_qualifier_category::lvalue, R(Args...) volatile&,
std::conditional_t<r == ref_qualifier_category::rvalue, R(Args...) volatile&&, R(Args...) volatile>>;
};
template <typename R, typename ...Args, ref_qualifier_category r>
struct add_ref<R(Args...) const volatile, r>
{
using type =
std::conditional_t<r == ref_qualifier_category::lvalue, R(Args...) const volatile&,
std::conditional_t<r == ref_qualifier_category::rvalue, R(Args...) const volatile&&, R(Args...) const volatile>>;
};
template <typename R, typename ...Args, ref_qualifier_category r>
struct add_ref<R(Args......), r>
{
using type =
std::conditional_t<r == ref_qualifier_category::lvalue, R(Args......)&,
std::conditional_t<r == ref_qualifier_category::rvalue, R(Args......)&&, R(Args......)>>;
};
template <typename R, typename ...Args, ref_qualifier_category r>
struct add_ref<R(Args......) const, r>
{
using type =
std::conditional_t<r == ref_qualifier_category::lvalue, R(Args......) const&,
std::conditional_t<r == ref_qualifier_category::rvalue, R(Args......) const&&, R(Args......) const>>;
};
template <typename R, typename ...Args, ref_qualifier_category r>
struct add_ref<R(Args......) volatile, r>
{
using type =
std::conditional_t<r == ref_qualifier_category::lvalue, R(Args......) volatile&,
std::conditional_t<r == ref_qualifier_category::rvalue, R(Args......) volatile&&, R(Args......) volatile>>;
};
template <typename R, typename ...Args, ref_qualifier_category r>
struct add_ref<R(Args......) const volatile, r>
{
using type =
std::conditional_t<r == ref_qualifier_category::lvalue, R(Args......) const volatile&,
std::conditional_t<r == ref_qualifier_category::rvalue, R(Args......) const volatile&&, R(Args......) const volatile>>;
};
// Add noexcept to a function. Must be called immediately after add_ref
template <typename T, bool b>
struct add_noexcept;
template <typename R, typename ...Args, bool b>
struct add_noexcept<R(Args...), b>
{
using type = std::conditional_t<b, R(Args...) noexcept, R(Args...)>;
};
template <typename R, typename ...Args, bool b>
struct add_noexcept<R(Args...) const, b>
{
using type = std::conditional_t<b, R(Args...) const noexcept, R(Args...) const>;
};
template <typename R, typename ...Args, bool b>
struct add_noexcept<R(Args...) volatile, b>
{
using type = std::conditional_t<b, R(Args...) volatile noexcept, R(Args...) volatile>;
};
template <typename R, typename ...Args, bool b>
struct add_noexcept<R(Args...) const volatile, b>
{
using type = std::conditional_t<b, R(Args...) const volatile noexcept, R(Args...) const volatile>;
};
template <typename R, typename ...Args, bool b>
struct add_noexcept<R(Args...)&, b>
{
using type = std::conditional_t<b, R(Args...) & noexcept, R(Args...)&>;
};
template <typename R, typename ...Args, bool b>
struct add_noexcept<R(Args...) const&, b>
{
using type = std::conditional_t<b, R(Args...) const& noexcept, R(Args...) const&>;
};
template <typename R, typename ...Args, bool b>
struct add_noexcept<R(Args...) volatile&, b>
{
using type = std::conditional_t<b, R(Args...) volatile& noexcept, R(Args...) volatile&>;
};
template <typename R, typename ...Args, bool b>
struct add_noexcept<R(Args...) const volatile&, b>
{
using type = std::conditional_t<b, R(Args...) const volatile& noexcept, R(Args...) const volatile&>;
};
template <typename R, typename ...Args, bool b>
struct add_noexcept<R(Args...)&&, b>
{
using type = std::conditional_t<b, R(Args...) && noexcept, R(Args...)&&>;
};
template <typename R, typename ...Args, bool b>
struct add_noexcept<R(Args...) const&&, b>
{
using type = std::conditional_t<b, R(Args...) const&& noexcept, R(Args...) const&&>;
};
template <typename R, typename ...Args, bool b>
struct add_noexcept<R(Args...) volatile&&, b>
{
using type = std::conditional_t<b, R(Args...) volatile&& noexcept, R(Args...) volatile&&>;
};
template <typename R, typename ...Args, bool b>
struct add_noexcept<R(Args...) const volatile&&, b>
{
using type = std::conditional_t<b, R(Args...) const volatile&& noexcept, R(Args...) const volatile&&>;
};
template <typename R, typename ...Args, bool b>
struct add_noexcept<R(Args......), b>
{
using type = std::conditional_t<b, R(Args......) noexcept, R(Args......)>;
};
template <typename R, typename ...Args, bool b>
struct add_noexcept<R(Args......) const, b>
{
using type = std::conditional_t<b, R(Args......) const noexcept, R(Args......) const>;
};
template <typename R, typename ...Args, bool b>
struct add_noexcept<R(Args......) volatile, b>
{
using type = std::conditional_t<b, R(Args......) volatile noexcept, R(Args......) volatile>;
};
template <typename R, typename ...Args, bool b>
struct add_noexcept<R(Args......) const volatile, b>
{
using type = std::conditional_t<b, R(Args......) const volatile noexcept, R(Args......) const volatile>;
};
template <typename R, typename ...Args, bool b>
struct add_noexcept<R(Args......)&, b>
{
using type = std::conditional_t<b, R(Args......) & noexcept, R(Args......)&>;
};
template <typename R, typename ...Args, bool b>
struct add_noexcept<R(Args......) const&, b>
{
using type = std::conditional_t<b, R(Args......) const& noexcept, R(Args......) const&>;
};
template <typename R, typename ...Args, bool b>
struct add_noexcept<R(Args......) volatile&, b>
{
using type = std::conditional_t<b, R(Args......) volatile& noexcept, R(Args......) volatile&>;
};
template <typename R, typename ...Args, bool b>
struct add_noexcept<R(Args......) const volatile&, b>
{
using type = std::conditional_t<b, R(Args......) const volatile& noexcept, R(Args......) const volatile&>;
};
template <typename R, typename ...Args, bool b>
struct add_noexcept<R(Args......)&&, b>
{
using type = std::conditional_t<b, R(Args......) && noexcept, R(Args......)&&>;
};
template <typename R, typename ...Args, bool b>
struct add_noexcept<R(Args......) const&&, b>
{
using type = std::conditional_t<b, R(Args......) const&& noexcept, R(Args......) const&&>;
};
template <typename R, typename ...Args, bool b>
struct add_noexcept<R(Args......) volatile&&, b>
{
using type = std::conditional_t<b, R(Args......) volatile&& noexcept, R(Args......) volatile&&>;
};
template <typename R, typename ...Args, bool b>
struct add_noexcept<R(Args......) const volatile&&, b>
{
using type = std::conditional_t<b, R(Args......) const volatile&& noexcept, R(Args......) const volatile&&>;
};
// Add calling conventions to a function. Must be called immediately after add_noexcept
struct dummy {};
template <typename, calling_convention_category>
struct add_calling_convention;
#if defined (_M_IX86)
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...), cc>
{
using type =
std::conditional_t<cc == calling_convention_category::cdecl_, R __cdecl (Args...),
std::conditional_t<cc == calling_convention_category::stdcall, R __stdcall (Args...),
std::conditional_t<cc == calling_convention_category::fastcall, R __fastcall (Args...),
std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...), R(__thiscall dummy::*)(Args...)>>>>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) const, cc>
{
using type =
std::conditional_t<cc == calling_convention_category::cdecl_, R __cdecl (Args...) const,
std::conditional_t<cc == calling_convention_category::stdcall, R __stdcall (Args...) const,
std::conditional_t<cc == calling_convention_category::fastcall, R __fastcall (Args...) const,
std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) const, R(__thiscall dummy::*)(Args...) const>>>>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) volatile, cc>
{
using type =
std::conditional_t<cc == calling_convention_category::cdecl_, R __cdecl (Args...) volatile,
std::conditional_t<cc == calling_convention_category::stdcall, R __stdcall (Args...) volatile,
std::conditional_t<cc == calling_convention_category::fastcall, R __fastcall (Args...) volatile,
std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) volatile, R(__thiscall dummy::*)(Args...) volatile>>>>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) const volatile, cc>
{
using type =
std::conditional_t<cc == calling_convention_category::cdecl_, R __cdecl (Args...) const volatile,
std::conditional_t<cc == calling_convention_category::stdcall, R __stdcall (Args...) const volatile,
std::conditional_t<cc == calling_convention_category::fastcall, R __fastcall (Args...) const volatile,
std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) const volatile, R(__thiscall dummy::*)(Args...) const volatile>>>>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...)&, cc>
{
using type =
std::conditional_t<cc == calling_convention_category::cdecl_, R __cdecl (Args...)&,
std::conditional_t<cc == calling_convention_category::stdcall, R __stdcall (Args...)&,
std::conditional_t<cc == calling_convention_category::fastcall, R __fastcall (Args...)&,
std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...)&, R(__thiscall dummy::*)(Args...)&>>>>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) const&, cc>
{
using type =
std::conditional_t<cc == calling_convention_category::cdecl_, R __cdecl (Args...) const&,
std::conditional_t<cc == calling_convention_category::stdcall, R __stdcall (Args...) const&,
std::conditional_t<cc == calling_convention_category::fastcall, R __fastcall (Args...) const&,
std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) const&, R(__thiscall dummy::*)(Args...) const&>>>>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) volatile&, cc>
{
using type =
std::conditional_t<cc == calling_convention_category::cdecl_, R __cdecl (Args...) volatile&,
std::conditional_t<cc == calling_convention_category::stdcall, R __stdcall (Args...) volatile&,
std::conditional_t<cc == calling_convention_category::fastcall, R __fastcall (Args...) volatile&,
std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) volatile&, R(__thiscall dummy::*)(Args...) volatile&>>>>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) const volatile&, cc>
{
using type =
std::conditional_t<cc == calling_convention_category::cdecl_, R __cdecl (Args...) const volatile&,
std::conditional_t<cc == calling_convention_category::stdcall, R __stdcall (Args...) const volatile&,
std::conditional_t<cc == calling_convention_category::fastcall, R __fastcall (Args...) const volatile&,
std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) const volatile&, R(__thiscall dummy::*)(Args...) const volatile&>>>>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...)&&, cc>
{
using type =
std::conditional_t<cc == calling_convention_category::cdecl_, R __cdecl (Args...)&&,
std::conditional_t<cc == calling_convention_category::stdcall, R __stdcall (Args...)&&,
std::conditional_t<cc == calling_convention_category::fastcall, R __fastcall (Args...)&&,
std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...)&&, R(__thiscall dummy::*)(Args...)&&>>>>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) const&&, cc>
{
using type =
std::conditional_t<cc == calling_convention_category::cdecl_, R __cdecl (Args...) const&&,
std::conditional_t<cc == calling_convention_category::stdcall, R __stdcall (Args...) const&&,
std::conditional_t<cc == calling_convention_category::fastcall, R __fastcall (Args...) const&&,
std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) const&&, R(__thiscall dummy::*)(Args...) const&&>>>>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) volatile&&, cc>
{
using type =
std::conditional_t<cc == calling_convention_category::cdecl_, R __cdecl (Args...) volatile&&,
std::conditional_t<cc == calling_convention_category::stdcall, R __stdcall (Args...) volatile&&,
std::conditional_t<cc == calling_convention_category::fastcall, R __fastcall (Args...) volatile&&,
std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) volatile&&, R(__thiscall dummy::*)(Args...) volatile&&>>>>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) const volatile&&, cc>
{
using type =
std::conditional_t<cc == calling_convention_category::cdecl_, R __cdecl (Args...) const volatile&&,
std::conditional_t<cc == calling_convention_category::stdcall, R __stdcall (Args...) const volatile&&,
std::conditional_t<cc == calling_convention_category::fastcall, R __fastcall (Args...) const volatile&&,
std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) const volatile&&, R(__thiscall dummy::*)(Args...) const volatile&&>>>>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) noexcept, cc>
{
using type =
std::conditional_t<cc == calling_convention_category::cdecl_, R __cdecl (Args...) noexcept,
std::conditional_t<cc == calling_convention_category::stdcall, R __stdcall (Args...) noexcept,
std::conditional_t<cc == calling_convention_category::fastcall, R __fastcall (Args...) noexcept,
std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) noexcept, R(__thiscall dummy::*)(Args...) noexcept>>>>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) const noexcept, cc>
{
using type =
std::conditional_t<cc == calling_convention_category::cdecl_, R __cdecl (Args...) const noexcept,
std::conditional_t<cc == calling_convention_category::stdcall, R __stdcall (Args...) const noexcept,
std::conditional_t<cc == calling_convention_category::fastcall, R __fastcall (Args...) const noexcept,
std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) const noexcept, R(__thiscall dummy::*)(Args...) const noexcept>>>>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) volatile noexcept, cc>
{
using type =
std::conditional_t<cc == calling_convention_category::cdecl_, R __cdecl (Args...) volatile noexcept,
std::conditional_t<cc == calling_convention_category::stdcall, R __stdcall (Args...) volatile noexcept,
std::conditional_t<cc == calling_convention_category::fastcall, R __fastcall (Args...) volatile noexcept,
std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) volatile noexcept, R(__thiscall dummy::*)(Args...) volatile noexcept>>>>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) const volatile noexcept, cc>
{
using type =
std::conditional_t<cc == calling_convention_category::cdecl_, R __cdecl (Args...) const volatile noexcept,
std::conditional_t<cc == calling_convention_category::stdcall, R __stdcall (Args...) const volatile noexcept,
std::conditional_t<cc == calling_convention_category::fastcall, R __fastcall (Args...) const volatile noexcept,
std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) const volatile noexcept, R(__thiscall dummy::*)(Args...) const volatile noexcept>>>>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) & noexcept, cc>
{
using type =
std::conditional_t<cc == calling_convention_category::cdecl_, R __cdecl (Args...) & noexcept,
std::conditional_t<cc == calling_convention_category::stdcall, R __stdcall (Args...) & noexcept,
std::conditional_t<cc == calling_convention_category::fastcall, R __fastcall (Args...) & noexcept,
std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) & noexcept, R(__thiscall dummy::*)(Args...) & noexcept>>>>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) const& noexcept, cc>
{
using type =
std::conditional_t<cc == calling_convention_category::cdecl_, R __cdecl (Args...) const& noexcept,
std::conditional_t<cc == calling_convention_category::stdcall, R __stdcall (Args...) const& noexcept,
std::conditional_t<cc == calling_convention_category::fastcall, R __fastcall (Args...) const& noexcept,
std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) const& noexcept, R(__thiscall dummy::*)(Args...) const& noexcept>>>>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) volatile& noexcept, cc>
{
using type =
std::conditional_t<cc == calling_convention_category::cdecl_, R __cdecl (Args...) volatile& noexcept,
std::conditional_t<cc == calling_convention_category::stdcall, R __stdcall (Args...) volatile& noexcept,
std::conditional_t<cc == calling_convention_category::fastcall, R __fastcall (Args...) volatile& noexcept,
std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) volatile& noexcept, R(__thiscall dummy::*)(Args...) volatile& noexcept>>>>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) const volatile& noexcept, cc>
{
using type =
std::conditional_t<cc == calling_convention_category::cdecl_, R __cdecl (Args...) const volatile& noexcept,
std::conditional_t<cc == calling_convention_category::stdcall, R __stdcall (Args...) const volatile& noexcept,
std::conditional_t<cc == calling_convention_category::fastcall, R __fastcall (Args...) const volatile& noexcept,
std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) const volatile& noexcept, R(__thiscall dummy::*)(Args...) const volatile& noexcept>>>>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) && noexcept, cc>
{
using type =
std::conditional_t<cc == calling_convention_category::cdecl_, R __cdecl (Args...) && noexcept,
std::conditional_t<cc == calling_convention_category::stdcall, R __stdcall (Args...) && noexcept,
std::conditional_t<cc == calling_convention_category::fastcall, R __fastcall (Args...) && noexcept,
std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) && noexcept, R(__thiscall dummy::*)(Args...) && noexcept>>>>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) const&& noexcept, cc>
{
using type =
std::conditional_t<cc == calling_convention_category::cdecl_, R __cdecl (Args...) const&& noexcept,
std::conditional_t<cc == calling_convention_category::stdcall, R __stdcall (Args...) const&& noexcept,
std::conditional_t<cc == calling_convention_category::fastcall, R __fastcall (Args...) const&& noexcept,
std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) const&& noexcept, R(__thiscall dummy::*)(Args...) const&& noexcept>>>>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) volatile&& noexcept, cc>
{
using type =
std::conditional_t<cc == calling_convention_category::cdecl_, R __cdecl (Args...) volatile&& noexcept,
std::conditional_t<cc == calling_convention_category::stdcall, R __stdcall (Args...) volatile&& noexcept,
std::conditional_t<cc == calling_convention_category::fastcall, R __fastcall (Args...) volatile&& noexcept,
std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) volatile&& noexcept, R(__thiscall dummy::*)(Args...) volatile&& noexcept>>>>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) const volatile&& noexcept, cc>
{
using type =
std::conditional_t<cc == calling_convention_category::cdecl_, R __cdecl (Args...) const volatile&& noexcept,
std::conditional_t<cc == calling_convention_category::stdcall, R __stdcall (Args...) const volatile&& noexcept,
std::conditional_t<cc == calling_convention_category::fastcall, R __fastcall (Args...) const volatile&& noexcept,
std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) const volatile&& noexcept, R(__thiscall dummy::*)(Args...) const volatile&& noexcept>>>>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......), cc>
{
using type = R __cdecl (Args......);
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) const, cc>
{
using type = R __cdecl (Args......) const;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) volatile, cc>
{
using type = R __cdecl (Args......) volatile;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) const volatile, cc>
{
using type = R __cdecl (Args......) const volatile;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......)&, cc>
{
using type = R __cdecl (Args......)&;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) const&, cc>
{
using type = R __cdecl (Args......) const&;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) volatile&, cc>
{
using type = R __cdecl (Args......) volatile&;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) const volatile&, cc>
{
using type = R __cdecl (Args......) const volatile&;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......)&&, cc>
{
using type = R __cdecl (Args......)&&;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) const&&, cc>
{
using type = R __cdecl (Args......) const&&;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) volatile&&, cc>
{
using type = R __cdecl (Args......) volatile&&;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) const volatile&&, cc>
{
using type = R __cdecl (Args......) const volatile&&;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) noexcept, cc>
{
using type = R __cdecl (Args......) noexcept;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) const noexcept, cc>
{
using type = R __cdecl (Args......) const noexcept;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) volatile noexcept, cc>
{
using type = R __cdecl (Args......) volatile noexcept;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) const volatile noexcept, cc>
{
using type = R __cdecl (Args......) const volatile noexcept;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) & noexcept, cc>
{
using type = R __cdecl (Args......) & noexcept;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) const& noexcept, cc>
{
using type = R __cdecl (Args......) const& noexcept;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) volatile& noexcept, cc>
{
using type = R __cdecl (Args......) volatile& noexcept;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) const volatile& noexcept, cc>
{
using type = R __cdecl (Args......) const volatile& noexcept;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) && noexcept, cc>
{
using type = R __cdecl (Args......) && noexcept;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) const&& noexcept, cc>
{
using type = R __cdecl (Args......) const&& noexcept;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) volatile&& noexcept, cc>
{
using type = R __cdecl (Args......) volatile&& noexcept;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) const volatile&& noexcept, cc>
{
using type = R __cdecl (Args......) const volatile&& noexcept;
};
#elif defined(_M_X64)
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...), cc>
{
using type = std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...), R __cdecl (Args...)>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) const, cc>
{
using type = std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) const, R __cdecl (Args...) const>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) volatile, cc>
{
using type = std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) volatile, R __cdecl (Args...) volatile>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) const volatile, cc>
{
using type = std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) const volatile, R __cdecl (Args...) const volatile>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...)&, cc>
{
using type = std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...)&, R __cdecl (Args...)&>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) const&, cc>
{
using type = std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) const&, R __cdecl (Args...) const&>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) volatile&, cc>
{
using type = std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) volatile&, R __cdecl (Args...) volatile&>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) const volatile&, cc>
{
using type = std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) const volatile&, R __cdecl (Args...) const volatile&>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...)&&, cc>
{
using type = std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...)&&, R __cdecl (Args...)&&>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) const&&, cc>
{
using type = std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) const&&, R __cdecl (Args...) const&&>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) volatile&&, cc>
{
using type = std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) volatile&&, R __cdecl (Args...) volatile&&>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) const volatile&&, cc>
{
using type = std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) const volatile&&, R __cdecl (Args...) const volatile&&>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) noexcept, cc>
{
using type = std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) noexcept, R __cdecl (Args...) noexcept>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) const noexcept, cc>
{
using type = std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) const noexcept, R __cdecl (Args...) const noexcept>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) volatile noexcept, cc>
{
using type = std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) volatile noexcept, R __cdecl (Args...) volatile noexcept>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) const volatile noexcept, cc>
{
using type = std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) const volatile noexcept, R __cdecl (Args...) const volatile noexcept>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) & noexcept, cc>
{
using type = std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) & noexcept, R __cdecl (Args...) & noexcept>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) const& noexcept, cc>
{
using type = std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) const& noexcept, R __cdecl (Args...) const& noexcept>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) volatile& noexcept, cc>
{
using type = std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) volatile& noexcept, R __cdecl (Args...) volatile& noexcept>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) const volatile& noexcept, cc>
{
using type = std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) const volatile& noexcept, R __cdecl (Args...) const volatile& noexcept>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) && noexcept, cc>
{
using type = std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) && noexcept, R __cdecl (Args...) && noexcept>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) const&& noexcept, cc>
{
using type = std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) const&& noexcept, R __cdecl (Args...) const&& noexcept>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) volatile&& noexcept, cc>
{
using type = std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) volatile&& noexcept, R __cdecl (Args...) volatile&& noexcept>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args...) const volatile&& noexcept, cc>
{
using type = std::conditional_t<cc == calling_convention_category::vectorcall, R __vectorcall (Args...) const volatile&& noexcept, R __cdecl (Args...) const volatile&& noexcept>;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......), cc>
{
using type = R __cdecl (Args......);
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) const, cc>
{
using type = R __cdecl (Args......) const;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) volatile, cc>
{
using type = R __cdecl (Args......) volatile;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) const volatile, cc>
{
using type = R __cdecl (Args......) const volatile;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......)&, cc>
{
using type = R __cdecl (Args......)&;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) const&, cc>
{
using type = R __cdecl (Args......) const&;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) volatile&, cc>
{
using type = R __cdecl (Args......) volatile&;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) const volatile&, cc>
{
using type = R __cdecl (Args......) const volatile&;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......)&&, cc>
{
using type = R __cdecl (Args......)&&;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) const&&, cc>
{
using type = R __cdecl (Args......) const&&;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) volatile&&, cc>
{
using type = R __cdecl (Args......) volatile&&;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) const volatile&&, cc>
{
using type = R __cdecl (Args......) const volatile&&;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) noexcept, cc>
{
using type = R __cdecl (Args......) noexcept;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) const noexcept, cc>
{
using type = R __cdecl (Args......) const noexcept;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) volatile noexcept, cc>
{
using type = R __cdecl (Args......) volatile noexcept;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) const volatile noexcept, cc>
{
using type = R __cdecl (Args......) const volatile noexcept;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) & noexcept, cc>
{
using type = R __cdecl (Args......) & noexcept;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) const& noexcept, cc>
{
using type = R __cdecl (Args......) const& noexcept;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) volatile& noexcept, cc>
{
using type = R __cdecl (Args......) volatile& noexcept;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) const volatile& noexcept, cc>
{
using type = R __cdecl (Args......) const volatile& noexcept;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) && noexcept, cc>
{
using type = R __cdecl (Args......) && noexcept;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) const&& noexcept, cc>
{
using type = R __cdecl (Args......) const&& noexcept;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) volatile&& noexcept, cc>
{
using type = R __cdecl (Args......) volatile&& noexcept;
};
template <typename R, typename ...Args, calling_convention_category cc>
struct add_calling_convention<R(Args......) const volatile&& noexcept, cc>
{
using type = R __cdecl (Args......) const volatile&& noexcept;
};
#endif
// Add class to a function. Must be called immediately after add_calling_convention
template <typename F, typename C>
struct make_member_function_pointer
{
using type = F C::*;
};
template <typename F, typename C>
struct add_class
{
using type = std::conditional_t<std::is_void_v<C>, std::type_identity<F>, make_member_function_pointer<F, C>>::type;
};
template <typename F, typename C>
struct add_class<F dummy::*, C>
{
using type = F C::*;
};
using F1 = make_function<T::is_vararg, typename T::return_type, typename T::parameter_types>::type;
using F2 = add_cv<F1, T::cv_qualifier>::type;
using F3 = add_ref<F2, T::ref_qualifier>::type;
using F4 = add_noexcept<F3, T::is_noexcept>::type;
using F5 = add_calling_convention<F4, T::calling_convention>::type;
using F6 = add_class<F5, typename T::class_type>::type;
public:
using type = F6;
};
template <typename T>
using assemble_function_t = assemble_function<T>::type;
}
/*
Check if T is a function pointer and is not a pointer to member function
Example:
constexpr bool b1 = is_function_pointer<int(*)(char, float)>; // b1 == true
constexpr bool b2 = is_function_pointer<int (A::*)(char, float)> // b2 == false;
*/
template <typename F>
struct is_function_pointer : std::conjunction<std::is_pointer<F>, std::is_function<std::remove_pointer_t<F>>> {};
template <typename F>
inline constexpr bool is_function_pointer_v = is_function_pointer<F>::value;
/*
Check if T is a variadic function or a pointer to variadic member function
Example:
constexpr bool b1 = is_variadic_function_v<int(float, char, ...)>; // b1 == true
constexpr bool b2 = is_variadic_function_v<int(A::*)(float, char)>; // b2 == false
*/
template <typename F>
struct is_variadic_function : std::bool_constant<detail::disassemble_function_t<F>::is_vararg> {};
template <typename F>
inline constexpr bool is_variadic_function_v = is_variadic_function<F>::value;
/*
Get the parameter count of a function or a pointer to member function
Example:
constexpr auto i = arity_v<void(int, float, char)>; // i == 3
constexpr autp j = arity_v<void(A::*)(int, float, char) const&>; // j == 3
constexpr auto k = arity_v<void(int, float, char, ...)>; // k == 3
*/
template <typename F>
struct arity : std::integral_constant<std::size_t, type_count_v<typename detail::disassemble_function_t<F>::parameter_types>> {};
template <typename F>
inline static constexpr std::size_t arity_v = arity<F>::value;
/*
Get the return type of a function or a pointer to member function
Example:
using T = return_type_t<int(float, char)>; // T is int
using U = return_type_t<int(A::*)(float, char)>; // U is int
*/
template <typename F>
struct return_type
{
using type = detail::disassemble_function_t<F>::return_type;
};
template <typename F>
using return_type_t = return_type<F>::type;
/*
Get the Ith parameter of a function or a pointer to member function
Example:
using T = parameter_type_t<void(int, float, char) const&, 1>; // T is float
using U = parameter_type_t<void(A::*)(int, float, char) const&, 1>; // U is float
using V = parameter_type_t<void(int, float, char...) const&, 1>; // V is float
*/
template <typename F, std::size_t I>
struct parameter_type
{
using type = get_t<typename detail::disassemble_function_t<F>::parameter_types, I>;
};
template <typename F, std::size_t I>
using parameter_type_t = parameter_type<F, I>::type;
/*
Remove the class from a pointer to member function
Example:
using T = strip_class_t<int (A::*)(int, float, char) const&>; // T is int(int, float, char) const&
*/
template <typename>
struct strip_class;
template <typename F, typename C>
struct strip_class<F C::*>
{
using type = F;
};
template <typename F>
using strip_class_t = strip_class<F>::type;
/*
Remove the function from a pointer to member function
Example:
using T = strip_function_t<int (A::*)(int, float, char) const&>; // T is A
*/
template <typename>
struct strip_function;
template <typename F, typename C>
struct strip_function<F C::*>
{
using type = C;
};
template <typename F>
using strip_function_t = strip_function<F>::type;
/*
Test if a function is stdcall
Example:
constexpr bool b1 = is_stdcall_v<int __stdcall (float, char))>; // b1 == true
constexpr bool b2 = is_stdcall_v<int(__stdcall A::*)(float, char)>; // b2 == true
constexpr bool b3 = is_stdcall_v<int(A::*)(float, char)>; // b3 == false;
*/
#if defined(_M_IX86)
template <typename F>
struct is_stdcall : std::bool_constant<detail::disassemble_function_t<F>::calling_convention == detail::calling_convention_category::stdcall> {};
#elif defined(_M_X64)
template <typename>
struct is_stdcall : std::false_type {};
#endif
template <typename F>
inline constexpr bool is_stdcall_v = is_stdcall<F>::value;
/*
Add stdcall to a function or a pointer to member function
Example:
using T = add_stdcall_t<void __fastcall (int, char)>; // T is int __stdcall (int, char)
using U = add_stdcall_t<void(__thiscall A::*)(int, char)>; // T is int(__stdcall A::*)(int, char)
*/
#if defined(_M_IX86)
template <typename F>
struct add_stdcall
{
private:
using T = detail::disassemble_function_t<F>;
public:
using type = detail::assemble_function_t<detail::make_function_info_t<detail::calling_convention_category::stdcall, T::cv_qualifier, T::ref_qualifier, T::is_noexcept, T::is_vararg, typename T::class_type, typename T::return_type, typename T::parameter_types>>;
};
#elif defined(_M_X64)
template <typename F>
struct add_stdcall
{
using type = F;
};
#endif
template <typename F>
using add_stdcall_t = add_stdcall<F>::type;
/*
Test if a pointer to member function is thiscall
Example:
constexpr bool b1 = is_thiscall_v<int(__thiscall A::*)(float, char)>; // b1 == true
constexpr bool b2 = is_thiscall_v<int(__stdcall A::*)(float, char)>; // b1 == false
*/
#if defined (_M_IX86)
template <typename F>
struct is_thiscall : std::bool_constant<std::is_member_function_pointer_v<F> && detail::disassemble_function_t<F>::calling_convention == detail::calling_convention_category::thiscall> {};
#elif defined (_M_X64)
template <typename>
struct is_thiscall : std::false_type {};
#endif
template <typename F>
inline constexpr bool is_thiscall_v = is_thiscall<F>::value;
/*
Add thiscall to a pointer to member function
Example:
using T = add_thiscall_v<int(__stdcall A::*)(float, char)>; // T is int(__thiscall A::*)(float, char)
*/
#if defined(_M_IX86)
template <typename F, bool>
struct add_thiscall_impl;
template <typename F>
struct add_thiscall_impl<F, true>
{
private:
using T = detail::disassemble_function_t<F>;
public:
using type = detail::assemble_function_t<detail::make_function_info_t<detail::calling_convention_category::thiscall, T::cv_qualifier, T::ref_qualifier, T::is_noexcept, T::is_vararg, typename T::class_type, typename T::return_type, typename T::parameter_types>>;
};
template <typename F>
struct add_thiscall_impl<F, false>
{
using type = F;
};
#elif defined(_M_X64)
template <typename F, bool>
struct add_thiscall_impl
{
using type = F;
};
#endif
template <typename F>
struct add_thiscall : add_thiscall_impl<F, std::is_member_function_pointer_v<F>> {};
template <typename F>
using add_thiscall_t = add_thiscall<F>::type;
/*
Test if a function is default x64 calling convention
Example:
constexpr bool b1 = is_x64call_v<int(float, char)>; // b1 == true
constexpr bool b2 = is_x64call_v<int(A::*)(float, char)>; // b2 == true
constexpr bool b3 = is_x64call_v<int __vectorcall (float, char)>; // b3 == false
*/
#if defined(_M_IX86)
template <typename>
struct is_x64call : std::false_type {};
#elif defined(_M_X64)
template <typename F>
struct is_x64call : std::bool_constant<detail::disassemble_function_t<F>::calling_convention == detail::calling_convention_category::x64call> {};
#endif
template <typename F>
inline constexpr bool is_x64call_v = is_x64call<F>::value;
/*
Add x64 default calling convention to a function or a pointer to member function
Example:
using T = add_x64call_t<void __vectorcall (int, char)>; // T is int(int, char)
using U = add_x64call_t<void(__vectorcall A::*)(int, char)>; // T is int(A::*)(int, char)
*/
#if defined(_M_IX86)
template <typename F>
struct add_x64call
{
using type = F;
};
#elif defined(_M_X64)
template <typename F>
struct add_x64call
{
private:
using T = detail::disassemble_function_t<F>;
public:
using type = detail::assemble_function_t<detail::make_function_info_t<detail::calling_convention_category::x64call, T::cv_qualifier, T::ref_qualifier, T::is_noexcept, T::is_vararg, typename T::class_type, typename T::return_type, typename T::parameter_types>>;
};
#endif
template <typename F>
using add_x64call_t = add_x64call<F>::type;
/*
Relace the Ith parameter of a function or a pointer to member function
Example:
using T = replace_parameter_t<void(A::*)(float, char, double, short), long long, 2>; // T is void(A::*)(float, char, long long, short)
*/
template <typename F, typename T, std::size_t I>
struct replace_parameter
{
private:
template <typename, typename, std::size_t, typename>
struct replace_type;
template <typename ...Ts2, typename T2, std::size_t I2, std::size_t ...Is2>
struct replace_type<type_pack<Ts2...>, T2, I2, std::index_sequence<Is2...>>
{
using type = type_pack<std::conditional_t<I2 != Is2, Ts2, T2>...>;
};
using FI = detail::disassemble_function_t<F>;
static_assert(I < type_count_v<typename FI::parameter_types>, "Index out of range.");
using Ts = replace_type<typename FI::parameter_types, T, I, std::make_index_sequence<type_count_v<typename FI::parameter_types>>>::type;
using F2 = detail::assemble_function_t<detail::make_function_info_t<FI::calling_convention, FI::cv_qualifier, FI::ref_qualifier, FI::is_noexcept, FI::is_vararg, typename FI::class_type, typename FI::return_type, Ts>>;
public:
using type = F2;
};
template <typename F, typename T, std::size_t I>
using replace_parameter_t = replace_parameter<F, T, I>::type;
#endif
}
// Example
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#pragma comment(linker, "\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#ifdef _M_X64
constexpr bool bGenerateFunctionTable = false;
#endif // _M_X64
#include <exception>
#include <utility>
#include <Windows.h>
#include <windowsx.h>
#include "CallbackThunk.hpp"
/*
Store exceptions in WndProc for further handling
*/
thread_local std::exception_ptr WindowProcExceptionPointer = nullptr;
class Window
{
public:
Window(WNDCLASSEX* lpWndClass, LPCTSTR lpWindowName, DWORD dwStyle, DWORD dwExStyle = 0, int X = CW_USEDEFAULT, int Y = CW_USEDEFAULT, int nWidth = CW_USEDEFAULT, int nHeight = CW_USEDEFAULT, HWND hWndParent = NULL, HMENU hMenu = NULL) :
m_WindowProcThunk(this, WindowProc),
m_lpClassName(MakeClass(lpWndClass)),
m_hWnd(CreateWindowEx(dwExStyle, m_lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, GetModuleHandle(NULL), NULL)) {}
Window(const Window&) = delete;
Window& operator=(const Window&) = delete;
HWND GetHWnd() const noexcept
{
return m_hWnd;
}
protected:
LRESULT HandleLButtonDoubleClick(WPARAM vKeyDown, int x, int y)
{
// Deliberately throw an exception
if (vKeyDown & MK_CONTROL)
{
throw std::exception();
}
else
{
return 0;
}
}
LRESULT HandleDestroy()
{
PostQuitMessage(0);
return 0;
}
private:
// Temporarily store this pointer for WindowProcStub
inline static thread_local Window* s_pThis;
LPCTSTR MakeClass(WNDCLASSEX* lpWndClass)
{
s_pThis = this;
lpWndClass->lpfnWndProc = WindowProcStub;
return MAKEINTATOM(RegisterClassEx(lpWndClass));
}
// Stub WndProc to get HWND as early as possible
static LRESULT CALLBACK WindowProcStub(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
s_pThis->m_hWnd = hWnd;
WNDPROC WindowProcNew = s_pThis->m_WindowProcThunk.GetAddress();
SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(WindowProcNew));
return std::invoke(WindowProcNew, hWnd, uMsg, wParam, lParam);
}
static LRESULT CALLBACK WindowProc(Window* pThis, UINT uMsg, WPARAM wParam, LPARAM lParam) try
{
switch (uMsg)
{
case WM_LBUTTONDBLCLK:
{
return pThis->HandleLButtonDoubleClick(wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
}
break;
case WM_DESTROY:
{
return pThis->HandleDestroy();
}
break;
default:
{
return DefWindowProc(pThis->GetHWnd(), uMsg, wParam, lParam);
}
}
}
catch (...)
{
WindowProcExceptionPointer = std::current_exception();
return DefWindowProc(pThis->GetHWnd(), uMsg, wParam, lParam);
}
ReplacementCallbackThunk<Window, WNDPROC, 0> m_WindowProcThunk;
LPCTSTR m_lpClassName;
HWND m_hWnd;
};
LPCWSTR lpszWindowClassName = L"MyWindowClass";
LPCWSTR lpszWindowName = L"MyApplication";
WNDCLASSEX wcex{ sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS, nullptr, 0, 0, GetModuleHandle(NULL), NULL, LoadCursor(NULL, IDC_ARROW), GetSysColorBrush(COLOR_WINDOW), NULL, lpszWindowClassName, NULL };
class MyApplication final
{
public:
MyApplication(int nCmdShow) :
m_nCmdShow(nCmdShow),
m_CallWindowReturnProcThunk(this, &MyApplication::CallWindowReturnProc),
m_hHook(SetWindowsHookEx(WH_CALLWNDPROCRET, m_CallWindowReturnProcThunk.GetAddress(), NULL, GetCurrentThreadId())),
m_Window(&wcex, lpszWindowName, WS_OVERLAPPEDWINDOW),
m_uExitCode() {}
MyApplication(const MyApplication&) = delete;
MyApplication& operator=(const MyApplication&) = delete;
~MyApplication()
{
UnhookWindowsHookEx(m_hHook);
}
void Run()
{
ShowWindow(m_Window.GetHWnd(), m_nCmdShow);
UpdateWindow(m_Window.GetHWnd());
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
m_uExitCode = static_cast<UINT>(msg.wParam);
}
UINT GetExitCode() const noexcept
{
return m_uExitCode;
}
private:
// Message hook to rethrow stored exception in WindowProcExceptionPointer
LRESULT CallWindowReturnProc(int code, WPARAM wParam, LPARAM lParam) try
{
if (WindowProcExceptionPointer)
{
std::rethrow_exception(std::exchange(WindowProcExceptionPointer, nullptr));
}
return CallNextHookEx(m_hHook, code, wParam, lParam);
}
catch (std::exception&)
{
MessageBox(reinterpret_cast<LPCWPRETSTRUCT>(lParam)->hwnd, L"Error!", L"Error", MB_ICONERROR | MB_OK);
PostQuitMessage(-1);
return CallNextHookEx(m_hHook, code, wParam, lParam);
}
int m_nCmdShow;
InsertionCallbackThunk<MyApplication, HOOKPROC> m_CallWindowReturnProcThunk;
HHOOK m_hHook;
Window m_Window;
UINT m_uExitCode;
};
int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ PWSTR pCmdLine, _In_ int nCmdShow)
{
MyApplication app(nCmdShow);
app.Run();
return app.GetExitCode();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment