chr*_*ris 12 c++ typechecking compile-time variadic-templates c++11
我正在尝试包装Windows API函数以在我选择时检查错误.正如我在之前的SO问题中发现的那样,我可以使用模板函数来调用API函数,然后调用GetLastError()以检索它可能设置的任何错误.然后,我可以将此错误传递给我的Error班级让我知道.
这是模板函数的代码:
template<typename TRet, typename... TArgs>
TRet Wrap(TRet(WINAPI *api)(TArgs...), TArgs... args)
{
TRet ret = api(args...);
//check for errors
return ret;
}
Run Code Online (Sandbox Code Playgroud)
使用这个我可以有如下代码
int WINAPI someFunc (int param1, BOOL param2); //body not accessible
int main()
{
int ret = someFunc (5, true); //works normally
int ret2 = Wrap (someFunc, 5, true); //same as above, but I'll get a message if there's an error
}
Run Code Online (Sandbox Code Playgroud)
这非常有效.但是,有一个可能的问题.采取这个功能
void WINAPI someFunc();
Run Code Online (Sandbox Code Playgroud)
将其转换为模板函数时,它看起来如下:
void Wrap(void(WINAPI *api)())
{
void ret = api(); //<-- ahem! Can't declare a variable of type void...
//check for errors
return ret; //<-- Can't return a value for void either
}
Run Code Online (Sandbox Code Playgroud)
为了解决这个问题,我试图创建一个版本,我替换的模板的TRet使用void.不幸的是,这实际上只会导致使用哪一个模糊.
除此之外,我尝试过使用
if (strcmp (typeid (TRet).name(), "v") != 0) //typeid(void).name() == "v"
{
//do stuff with variable to return
}
else
{
//do stuff without returning anything
}
Run Code Online (Sandbox Code Playgroud)
但是,typeid是运行时比较,因此代码仍然无法编译,因为尝试声明一个void变量,即使它永远不会.
接下来,我尝试使用std::is_same <TRet, void>::value而不是typeid,但发现它也是一个运行时比较.
此时,我不知道下一步该尝试什么.有没有可能让编译器相信我知道我在做什么会运行正常?我不介意附加一个额外的论点Wrap,但我也无法从中得到任何结论.
我使用Code :: Blocks与GNU G ++ 4.6.1,Windows XP以及Windows 7.感谢您提供任何帮助,即使它告诉我,我必须最终只是不使用Wrap返回void的函数.
您可以使用辅助类来微调特化:
template <typename F>
struct wrapper
{};
template <typename Res, typename... Args>
struct wrapper<Res(Args...)>
{
static Res wrap(Res (WINAPI *f)(Args...), Args&& args...)
{
Res r = f(std::forward<Args>(args)...);
// Blah blah
return r;
}
};
template <typename... Args>
struct wrapper<void(Args...)>
{
static void wrap(void (WINAPI *f)(Args...), Args&& args...)
{
f(std::forward<Args>(args)...);
// Blah blah
}
};
Run Code Online (Sandbox Code Playgroud)
现在,您可以编写包装器:
template <typename Res, typename... Args>
Res Wrap(Res (WINAPI *f)(Args...), Args&& args...)
{
return wrapper<Res(Args...)>::wrap(f, std::forward<Args>(args)...);
}
Run Code Online (Sandbox Code Playgroud)
请注意它即使在什么时候Res也能工作void.你被允许在return一个返回void的函数中返回void的表达式.
推导出正确的类型Wrap(someFunc, 5, true),即使对于返回void的函数也是如此.