Enigmatic
Enigmatic

Reputation: 388

Template function to wrap any function passed to it in C++

I am trying to use libgit2, and thought it would be nice to wrap the calls with something that will throw an exception for me instead. My philosophy was that I would then be able to invoke functions that have a common return typ. I figured I would be able to do it with a templated function but I am running into some issues:

template<typename F, typename... Args>
inline void invoke(Args&&... args) {
    git_error_code errCode = F(std::forward<Args>(args)...);
    if (errCode != GIT_OK) {
        throw GitErrorException(errCode);
    }
}

This generated some compiler warnings that I was not using a valid type so I figured that I could also use an alias instead:

template<typename ... Args>
using F = int (*)(Args&&... args);

template<F f, typename... Args>
inline void invoke(Args&&... args) {
    git_error_code errCode = f(std::forward<Args>(args)...);
    if (errCode != GIT_OK) {
        throw GitErrorException(errCode);
    }
}

But that also did not work when using the code as follows:

Git::invoke<git_branch_name>(&name, _ref);

Should I really have to rely on a macro instead here?

Upvotes: 2

Views: 135

Answers (1)

Jarod42
Jarod42

Reputation: 217085

To have following syntax

Git::invoke<git_branch_name>(&name, _ref);

You need (C++17)

template<auto F, typename... Args>
void invoke(Args&&... args) {
    git_error_code errCode = F(std::forward<Args>(args)...);
    if (errCode != GIT_OK) {
        throw GitErrorException(errCode);
    }
}

For c++14, you might do instead

template<typename F, typename... Args>
void invoke(F f, Args&&... args) {
    git_error_code errCode = f(std::forward<Args>(args)...);
    if (errCode != GIT_OK) {
        throw GitErrorException(errCode);
    }
}

with usage

Git::invoke(&git_branch_name, &name, _ref);

Upvotes: 5

Related Questions