Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing member function pointer as template parameter

I want to create a wrapper class which is able to call member functions (of any type) of the wrapped class with help of templates. This is what I have so far:

template <typename T>
class wrapper {
  public:    
    template<typename R, R (T::*func)()>
    void call_func() {
      (wrapped.*func)();
    }

  private:
    T wrapped;  
};

class some_class {
  private:
    int i = 2;
  public:
    void some_func() {
      std::cout << i << std::endl;
    }
};

int main() {
    wrapper<some_class> wr;
    // How I need to call at the moment:
    wr.call_func<void, &some_class::some_func>();
    // How I want call:
    wr.call_func<&some_class::some_func>();
    return 0;
}

As you can see in the comments of the main function, I want to call the wrapper-function without explicitly specifying the return type of the wrapped member function. (How) Can this be done in C++11?

like image 642
Mike van Dyke Avatar asked Feb 23 '18 13:02

Mike van Dyke


1 Answers

template<typename F>
void call_func(F func) {
  (wrapped.*func)();
}

then call like this:

wr.call_func(&some_class::some_func);

If you want to use the return value too, you'll need this:

template<typename F>
auto call_func(F func) -> decltype((std::declval<T>().*func)()) {
  return (wrapped.*func)();
}

If you have C++14, you can omit the -> decltype(...) part and use decltype(auto) as the return value.

If you also want to pass functions, you can use variadic templates and forwarding for that.

template<typename F, typename... Args>
decltype(auto) call_func(F func, Args&&... args) {
  return (wrapped.*func)(std::forward<Args>(args)...);
}
like image 54
petersohn Avatar answered Sep 28 '22 03:09

petersohn