jeudi 13 décembre 2018

Is there a way to automatically resolve an overloaded method via a template parameter?

I was trying to write a general purpose method locking wrapper for operations around a list. What I currently have is:

template <typename OP, typename... ARGS>
auto locked_call (OP op, ARGS... args) const
-> decltype(op(args...)) {
    std::lock_guard<std::mutex> g(lock_);
    return op(args...);
}

And, I can use it like this:

auto push_back = [this](decltype(p) p) {
    return list_.push_back(p); };
locked_call(push_back, p);

But, I would rather be able to pass the method to be called directly into locked_call and it dispatch directly against list_.

template <typename METHOD, typename... ARGS>
auto locked_call (METHOD op, ARGS... args) const
-> decltype((list_.*op)(args...)) {
    std::lock_guard<std::mutex> g(lock_);
    return (list_.*op)(args...);
}

I realized quickly this is tricky because of method overloading, and research seems to indicate explicitly resolving the overload is required. Is there any clever use of templates or decltype I can use to allow the code to simply pass the method name into locked_call?


As a hack, I can use a macro to achieve the simplified syntax by autogenerating a lambda:

#define LOCKED_CALL(METHOD, ...) \
    locked_call([this,##__VA_ARGS__](){ \
        return list_.METHOD(__VA_ARGS__); })

But I was hoping there was a template equivalent.

Aucun commentaire:

Enregistrer un commentaire