3
votes

I have an interface where I have to pass on member function pointer which are static cast'ed to a base pointer and behind our backs stored as a void pointer and invocation type ( message tables).

I have created a wrapper that does some exception handling (very simpel try/catch to catch std::runtime_error) since this is tedious and error prone to maintain in every single user callback.

So far, the following wrapper is actually working out fairly well (The idea is to grab the member function pointer directly as a value template parameter - in essence giving a member function wrapper for each and every callback function.):

class MyClass : public CWnd/*example*/{
public:
      template<void (MyClass::*f)(CCmdUI*)>
      void Dispatch(CCmdUI* pCmdUI) {
        try {
          (this->*f)(pCmdUI);
        }
        catch (std::runtime_error& e) {
          //handle error
        }
      }
};

But in order to avoid having an explicit overload for each type of call - would it be possible to parametize the argument list ?

Illustration (note this doesn't work):

      template<void (MyClass::*f)(Args...)>
      void Dispatch(Args... args) {
1
Please provide a minimal reproducible example, you are much more likely to get a response if people can paste your code into a compiler and fiddle with it.Alan Birtles

1 Answers

5
votes

Since you're using C++17, you can use auto on template parameters:

template<auto f, typename... Args>
      void Dispatch(Args... args) {
      //...

And invoke them normally by passing a pointer to member function as template argument #1. Live Example.

If you need to check whether f is a pointer to member function of that class, you can use some static_assert statements before invoking (this->*f)(args...).

And a small thing: if you're using rvalue semantics, it's also a good idea to receive Args&&and use std::forward.