Я обертываю Windows API и хочу сделать проверку ошибок простой и полезной.В настоящее время у меня есть объект глобальной ошибки с функцией set
для обработки новой ошибки.Функция set
принимает четыре аргумента: bool Error::set (const int code, const char * file, const char * const function, const int line);
Функция использует аргументы file, function и 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;
}
Респондент отметил, что вариационные шаблоны были бы необходимостьюсделать это достаточно общим.Это начало, но я потерян и благодарен за любую помощь в этом вопросе.