Проверка во время компиляции, если аргумент шаблона недействителен

Я пытаюсь обернуть функции 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;
}

Используя это, я могу получить следующий код

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
}

Это прекрасно работает. Однако есть одна возможная проблема. Возьмем функцию

void WINAPI someFunc();

При подстановке этого в функцию шаблона это выглядит следующим образом:

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
}

Чтобы обойти это, я попытался создать версию шаблона, в которой я заменил 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
}

Однако typeidявляется сравнением во время выполнения, поэтому код по-прежнему не компилируется из-за попытки объявить переменную void, даже если этого никогда не произойдет.

Затем я попытался использовать std::is_same ::valueвместо typeid, но обнаружил, что это также сравнение во время выполнения.

На данный момент я не знаю, что делать дальше.Есть ли возможность заставить компилятор поверить, что я знаю, что то, что я делаю, будет работать нормально? Я не возражаю против присоединения дополнительного аргумента к Wrap, но и из этого я ничего не смог получить.

Я использую Code::Blocks с GNU G++ 4.6.1 и Windows XP, а также Windows 7. Спасибо за любую помощь, даже если мне говорят, что в конечном итоге мне придется просто не использовать Wrapдля функций, возвращающих void.

12
задан Nathan Kleyn 13 April 2013 в 20:52
поделиться