Check at Compile-Time if Template Argument is void

You can use a helper class to fine tune specializations:

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
    }
};

Now, you can write the wrapper:

template <typename Res, typename... Args>
Res Wrap(Res (WINAPI *f)(Args...), Args&& args...)
{
    return wrapper<Res(Args...)>::wrap(f, std::forward<Args>(args)...);
}

Note that it works even when Res is void. You’re allowed to return an expression returning void in a function returning void.

The correct type is deduced, as in Wrap(someFunc, 5, true), even for functions returning void.

Leave a Comment