2
  1. 我可以制作方法(=成员函数)指针的模板参数包吗?
  2. 如果是,是否可以创建一个(模板)函数来执行其模板参数包中的所有方法?

简化:

  • 指定方法的执行顺序无关紧要。
  • 所有方法指针具有相同的签名(例如 return bool,具有相同的基类,不带参数)
4

2 回答 2

2
template<class T, class...Ms>
void run_all(T* t, Ms&&... ms) {
  using discard=int[];
  (void)discard{0,(void(
    (t->*ms)()
  ),0)...};
}

利用:

struct foo {
  bool t1() { return true; }
  bool t2() const { return false; }
};
int main() {
  foo f;
  run_all(&f, &foo::t1, &foo::t2);
}

run_all是迟钝的,但那是因为我们没有 C++17。

template<class T, class...Ms>
void run_all(T* t, Ms&&... ms) {
  ((void)((t->*ms)()),...);
}

这有点简单,甚至:

template<class T, class...Ms>
void run_all(T* t, Ms&&... ms) {
  ((t->*ms)(),...);
}

它依赖于t->*ms返回一个理智的类型。

我们还可以依靠ms返回 bool 的事实并做:

template<class T, class...Ms>
void run_all(T* t, Ms&&... ms) {
  (void)std::initializer_list<bool>{(t->*ms)()...};
}

或者

template<class T, class...Ms>
void run_all(T* t, Ms&&... ms) {
  using discard=bool[];
  (void)discard{false,(t->*ms)()...};
}

请注意,所有这些都按顺序执行它们的方法,并支持传递 0 个方法。

上面的一些void强制转换是为了阻止未使用值的警告。

其他人可以处理调用返回重载类型的可能性operator,

于 2017-07-20T18:22:04.900 回答
1
class MyClass {

  /* The methods to be executed: */

  bool func_1() const { /* ... */ }
  bool func_2() const { /* ... */ }
  // ...


  /* The parameter pack expansion: */

  typedef bool (MyClass::*FuncPtr)() const;

  template<class T = void>
  void Expand() const {}  // Termination version.

  template<FuncPtr ptr, FuncPtr ... Args>
  void Expand() const {
    (this->*ptr)();
    Expand<Args...>();
  }


  /* The function that calls them all: */

  void RunAll() const {
    Expand< 
      &MyClass::func_1, // <-- input to parameter pack
      &MyClass::func_2
    >();
  }

};

没有递归的替代版本:

class MyClass {

  /* The methods to be executed: */

  bool func_1() const { /* ... */ }
  bool func_2() const { /* ... */ }
  // ...


  /* The parameter pack expansion: */

  typedef bool (MyClass::*FuncPtr)() const;

  template<typename ... T> void ignore(T && ...) {}

  template<FuncPtr ... Args> 
  void Expand() const {
    ignore( ((this->*Args)(),0) ... );
  }

  /* The function that calls them all: */

  void RunAll() const {
    Expand< 
      &MyClass::func_1, // <-- input to parameter pack
      &MyClass::func_2
    >();
  }

};

(来自@Yakk 的贡献)

于 2017-07-21T07:45:36.400 回答