【发布时间】:2014-05-22 20:06:48
【问题描述】:
如何创建一个可变参数模板函数,将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 基类也不是一种选择,因为循环对性能至关重要,而且我不能在每次循环迭代中调用抽象函数。
【问题讨论】:
-
这只是一个 MWE,在实际代码中,
run方法包含一个并行循环,并在每个循环迭代中调用fun。 -
您的问题似乎是编译器在尝试将成员函数指针与
std::function映射时不知道Args...是什么,因为尚未推断出Args...(它在更右边)。 -
不要这样使用
std::function。它不起作用,即使它起作用,你也不会得到什么。 -
此外,所提供的参数不太可能与
function参数的参数完全匹配。您可能会有额外的限定词和转换等等。 -
@MooingDuck 但即使你修复了它,例如使用
std::decay_t<T>或一些unqualified_t<T>trait,你仍然会遇到麻烦。
标签: c++ c++11 variadic-templates std-function