메타 프로그래밍 방법. 첫째, 호출 규칙 정보를 유지하려고하는 포인터 특성입니다.
template<class...>types {using type=types;};
enum class calling_convention {
cdecl,
clrcall,
stdcall,
fastcall,
thiscall,
vectorcall,
};
template<class Sig>
struct signature_properties;
template<class R, class...Args>
struct signature_properties {
using return_type = R;
using argument_types = types<Args...>;
};
template<class FuncPtr>
struct function_properties;
#define CAT_(A,B) A##B
#define CAT(A,B) CAT_(A,B)
#define CALLING_CONVENTION_SUPPORT(CONVENTION) \
template<class R, class... Args> \
struct function_properties< R(CAT(__, CONVENTION) *)(Args...) >: \
signature_properties<R(Args...)> \
{ \
using type = R(CAT(__, CONVENTION) *)(Args...) \
static const calling_convention convention = calling_convention::CONVENTION; \
static type from_pvoid(void const* pvoid) { \
return static_cast<type>(pvoid); \
} \
}
CALLING_CONVENTION_SUPPORT(cdecl);
CALLING_CONVENTION_SUPPORT(clrcall);
CALLING_CONVENTION_SUPPORT(stdcall);
CALLING_CONVENTION_SUPPORT(fastcall);
CALLING_CONVENTION_SUPPORT(thiscall);
CALLING_CONVENTION_SUPPORT(vectorcall);
#undef CAT
#undef CAT_
#undef CALLING_CONVENTION_SUPPORT
Icky 매크로. 그리고 심각한 과잉. 그리고 안된다고. 그러나 당신은 아이디어를 얻습니다.
다음 작업을 할 수있는 도우미 : 도우미의
template<class FuncPtrType, class R, class Args>
struct helper;
template<class FuncPtrType, class R, class... Args>
struct helper<FuncPtrType, R, types<Args...>> {
FuncPtrType ptr;
R operator()(Args...args)const {
return ptr(std::forward<Args>(args)...);
}
helper(FuncPtrType p):ptr(p) {};
helper(helper const&)=default;
helper& operator=(helper const&)=default;
};
완벽한 전달도 유혹 할 것이다.
마지막으로, 우리는 helper
에 Entry
에서 작업을 반송 위의 특성 클래스를 사용
template<class FuncPtrType>
struct Entry:helper<
FuncPtrType,
typename signature_properties<FuncPtrType>::return_type,
typename signature_properties<FuncPtrTpye>::arguments
> {
using parent = helper<
FuncPtrType,
typename signature_properties<FuncPtrType>::return_type,
typename signature_properties<FuncPtrTpye>::arguments
>;
Entry(void const* pvoid):parent(static_cast<FuncPtrType>(pvoid)) {}
};
우리가 void const*
을 가지고 helper
에 입력 된 포인터를 전달하는 Entry
의 생성자를 포함 제외.
한 가지 변경 사항은 에서 우리가 호출 한 시점이 아닌 함수 유형이라는 것을 알고있는 가장 빠른 시점에 함수 유형으로 변환한다는 것입니다.
'void *'에 함수 포인터를 저장하는 데 기술적 인 문제가 있다고 생각했습니다. 확실히 어떤 플랫폼 VS2013 타겟이 아니더라도, 나는 인정할 것이다. – Yakk
@ Yakk, 함수 포인터 (정상 포인터보다 훨씬 큽니다)의 크기 때문일 수 있습니다. 그러나 나는'& function'을하지 않습니다. 나는 수출 테이블에서 주소를 가져 와서 캐스팅합니다. 어떤 해를 끼치 지 않아야합니다. – rev