我正在包装 Windows API,我希望使错误检查易于使用且有用。目前,我有一个全局错误对象,具有set
处理新错误的函数。该set
函数接受四个参数:bool Error::set (const int code, const char * file, const char * const function, const int line);
该函数使用文件、函数和行参数以格式良好的消息显示它们。
为了简化错误的设置,有一个宏#define setError() error.set (GetLastError(), __FILE__, __FUNCTION__, __LINE__);
这样我可以setError()
在任何时候通过在调用 API 函数后添加它来响应 API 函数设置的错误。
不幸的是,这会导致代码看起来像这样:
SomeAPIFunction();
setError();
AnotherAPIFunction();
setError();
构造函数也存在问题:
MyClass:MyClass()
: a (SomeAPIFunction), b (AnotherAPIFunction)
{
setError(); //what if both functions set an error?
}
如您所见,通过使用成员初始化器语法,我实际上是在限制自己。
解决此问题的一种方法是包装每个 API 函数:
int someAPIFunction()
{
int ret = SomeAPIFunction();
setError();
return ret;
}
错误消息的function
部分会告诉我是哪个函数导致了错误。当然,这必须是处理这个问题的最糟糕的方法。
解决方案似乎是使用可变参数模板。问题是,我不知道我应该怎么做才能让他们为此工作。我想最终的代码看起来像以下之一:
wrap<int, SomeAPIFunction (5)>();
wrap<int, SomeAPIFunction, 5>();
wrap<int, SomeAPIFunction> (5);
我已经阅读了有关开始可变参数模板的内容,但它们都让我对如何设置这样的东西一无所知。谁能指出我正确的方向?
我在类似的问题上发现了以下内容:
#include <iostream>
template<void f(void)>
struct Wrap {
void operator()() const {
std::cout << "Pre call hook" << std::endl;
f();
}
};
namespace {
void test_func() {
std::cout << "Real function" << std::endl;
}
}
const Wrap<&test_func> wrapped_test_func = {};
int main() {
wrapped_test_func();
return 0;
}
受访者指出,可变参数模板将是使其足够通用的必要条件。这是一个开始,但我对此事的任何帮助感到迷茫和感激。