- 我可以制作方法(=成员函数)指针的模板参数包吗?
- 如果是,是否可以创建一个(模板)函数来执行其模板参数包中的所有方法?
简化:
- 指定方法的执行顺序无关紧要。
- 所有方法指针具有相同的签名(例如 return
bool
,具有相同的基类,不带参数)
简化:
bool
,具有相同的基类,不带参数)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,
。
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 的贡献)