将成员函数指针作为模板参数传递

Mik*_*yke 3 c++ templates c++11

我想创建一个包装类,它可以在模板的帮助下调用包装类的成员函数(任何类型).这是我到目前为止:

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;
}
Run Code Online (Sandbox Code Playgroud)

正如您在main函数的注释中所看到的,我想调用包装函数而不显式指定包装成员函数的返回类型.(如何)可以在C++ 11中完成?

pet*_*ohn 8

template<typename F>
void call_func(F func) {
  (wrapped.*func)();
}
Run Code Online (Sandbox Code Playgroud)

然后像这样打电话:

wr.call_func(&some_class::some_func);
Run Code Online (Sandbox Code Playgroud)

如果你也想使用返回值,你需要这样:

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

如果您有C++ 14,则可以省略该-> decltype(...)部分并将其decltype(auto)用作返回值.

如果您还想传递函数,可以使用可变参数模板并进行转发.

template<typename F, typename... Args>
decltype(auto) call_func(F func, Args&&... args) {
  return (wrapped.*func)(std::forward<Args>(args)...);
}
Run Code Online (Sandbox Code Playgroud)

  • 如果您有C++ 14并且省略了`decltype`,那么您应该将返回类型替换为`decltype(auto)`以保留模板的相同语义. (3认同)