Проблема
Я хочу сделать функцию, которая принимает произвольное число объектов-функторов или, в общем, просто вызываемые объекты (разных типов) и применяет их к внутренней структуре данных. Функция будет использоваться с различным числом функторов в разных точках моего кода.
Вместо того, чтобы делать другую версию, чтобы принять 1,2,3... и т.д. и дублировать код, я думал об использовании вариативных шаблонов.
Я нашел решение, которое я опубликую ниже в качестве ответа, поскольку я не мог найти что-либо в Google об этом конкретно, и другие могут найти его полезным. Но, пожалуйста, если у кого-то есть лучшие идеи, опубликуйте их. У меня есть чувство, что должен быть стандартный способ сделать это?
Наивная попытка
Я вроде знал, что это не сработает, но моя первая попытка была
#include <iostream>
using namespace std;
struct FunctorA {
void operator() () {
cout << "FunctorA" << endl;
}
};
struct FunctorB {
void operator() () {
cout << "FunctorB" << endl;
}
};
template<typename... Fs>
void apply_functors(Fs... fs) {
fs()...; // will not work - can only expand packs in certain situations (e.g. as funciton
}
int main(void) {
apply_functors(FunctorA(),FunctorB());
apply_functors(FunctorA());
apply_functors([]()->void{ cout << "Lambda" << endl; });
return 0;
}
Однако это не сработает, потому что нам разрешено расширять пакеты параметров в определенных ситуациях, и бесплатный, как это не один.
Попытка 2
Моя следующая идея заключалась в том, чтобы создать фиктивную функцию, которая ничего не делала, но в которую я мог бы передавать функторы в качестве параметров, а затем расширять их. Причиной этого является то, что параметры функции являются одной из ситуаций, когда мы можем расширять пакеты параметров.
template<typename... Fs>
void _dummyF_impl(Fs... fs){}
template<typename... Fs>
void apply_functors(Fs... fs) {
_dummyF_impl( fs()... ); // only works if all functors return a value (else we get "invalid use of 'void'")
}
Однако это не сработает, потому что функторы возвращают void из их operator()
, и мы не можем передавать void в качестве параметров для функций.