目前我正在为不同的调用约定(__stdcall,__ cdecl,__ fastcall等)构建仿函数(可调用类型).使用包装器,我将能够做到这样的事情:
void __stdcall foo(int arg) { std::printf("arg: %i\n", arg); } int main(int, char**) { Functionv{foo}; v(1337); return EXIT_SUCCESS; }
目前,我为__stdcall调用约定构建了一个包装器,只要指定了正确的参数并传入了正确的参数,就可以调用任何__stdcall函数.该类如下所示:
templateclass Function { // NOTE: This version of my callable types // only supports the __stdcall calling // convention. I need support for __cdecl, // __fastcall and also __thiscall. using return_t = ReturnT; using callable_t = return_t(__stdcall*)(Args...); private: callable_t mCallable; public: template Function(FuncT const &func) : mCallable(func) { ; } void operator()(Args&&... args) { mCallable(std::forward (args)...); } };
有了这个,我决定构建其他包装器,但我认为键入相同的代码片段并更改callable_t的using声明中的调用约定比需要更多的工作.所以我想找到一种方法来构建大约4种可调用类型的变体(对于每个调用约定),但是找不到一种方法.
到目前为止,我已经尝试使用枚举作为非类型模板参数,如下所示:
templateclass Function { // ... };
但我不知道如何迭代Call对象的类型并建立所需的类型(我尝试使用std :: is_same/std :: enable_if但这是一个死胡同).我还尝试使用这样的代码模板专业化:
struct StdcallT { ; }; struct CdeclT { ; }; struct FastcallT { ; }; templatestruct BaseT { }; template <> struct BaseT { using CallableT = void(__stdcall*)(); }; template <> struct BaseT { using CallableT = void(__cdecl*)(); }; template <> struct BaseT { using CallableT = void(__fastcall*)(); }; template class Function { using CallableT = typename BaseT ::CallableT; };
但我没有考虑其余的参数(返回类型+参数),所以这也不行.
那么无论如何都有什么想法我能做什么?我正在考虑的一种方法是切换非类型参数并调用正确的参数,如下所示:
templateclass Function { void operator()(ArgsT&&... args) { switch(Call) { case CallingConvention::Cdecl: // Call a __cdecl version break; case CallingConvention::Stdcall: // Call an __stdcall version break; // And so on... } } };
尽管这看起来像一个工作的解决方案,我想知道是否有一些我没想到的好的替代方案.
有任何想法吗?