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
возвращает логическое значение и сделать:
template<class T, class...Ms>
void run_all(T* t, Ms&&... ms) {
(void)std::initializer_list<bool>{(t->*ms)()...};
}
or
template<class T, class...Ms>
void run_all(T* t, Ms&&... ms) {
using discard=bool[];
(void)discard{false,(t->*ms)()...};
}
Обратите внимание, что все они выполняют свои методы по порядку и поддерживают передачу 0 методов.
Некоторые из вышеприведенных приведений void
предназначены для блокировки предупреждений о неиспользуемых значениях.
Другие предназначены для обработки возможности того, что вызов возвращает тип, который перегружает operator,
.
person
Yakk - Adam Nevraumont
schedule
20.07.2017