Как создать переменную функцию шаблона с std::function
как параметр функции, который принимает переменное количество аргументов? Я попытался уменьшить проблему до MWE:
#include <functional>
template <class T> void run(std::function<void(T *)> fun, T *obj) { fun(obj); }
template <class T, class... Args>
void run_variadic(std::function<void(T *, Args...)> fun, T *obj, Args... args) {
fun(obj, args...);
}
struct Foo {
void bar() {}
};
int main() {
Foo foo;
std::function<void(Foo *)> fun = &Foo::bar;
run(fun, &foo); // works
run<Foo>(&Foo::bar, &foo); // works
run_variadic(fun, &foo); // works
run_variadic<Foo>(&Foo::bar, &foo); // does not compile
}
Похоже, что простое наличие параметра вариационного шаблона в run_variadic
делает невозможным прямое обращение к нему с помощью указателя на функцию-член. clang
сообщение об ошибке выглядит следующим образом:
main.cpp:21:3: error: no matching function for call to 'run_variadic'
run_variadic<Foo>(&Foo::bar, &foo); // does not compile
^~~~~~~~~~~~~~~~~
main.cpp:6:6: note: candidate template ignored: could not match 'function<void (Foo *, type-parameter-0-1...)>' against 'void (Foo::*)()'
void run_variadic(std::function<void(T *, Args...)> fun, T *obj, Args&&... args) {
^
1 error generated.
Любые предложения о том, как я могу исправить run_variadic
, чтобы мне не пришлось проходить через дополнительный объект std::function
?
Фон
У меня есть иерархия классов как
template <class T> class Abstract { ... };
class UnrelatedStuff { ... };
class Derived : public Abstract<UnrelatedStuff> { ... };
Существует несколько классов Derived
, которые должны реализовать один или несколько методов для циклического перемещения по ряду элементов. Цикл выглядит примерно так:
#pragma omp parallel for
for (ZFSId i = begin; i != end; ++i) {
callMemFun(i, and, other, args);
}
Все циклы должны быть с OpenMP-ускорением. Я хочу, чтобы материал ускорителя учитывался и не повторялся в каждом методе Derived
, который использует цикл, так что мне нужно изменить только одно место, например, OpenMP переключится на OpenACC.
Таким образом, я ищу способ поместить цикл (и его украшение) в свою собственную функцию. Перемещение его в базовый класс Abstract
также не является вариантом, поскольку циклы критичны для производительности, и я не могу иметь абстрактный вызов функции в каждой итерации цикла.