我正在使用C ++ 11代码库,想知道如何在传递任意参数的成员类型上调用任何函数。 请注意,由于我正在使用C ++ 11,因此无法使用类似std::invoke
的语言。
[我开始在Outer
类中创建功能模板,但最初的尝试给了我一个编译错误。
#include <iostream>
#include <utility>
#include <type_traits>
struct Inner {
void bar(int x) {
std::cout << "Called: x=" << x << std::endl;
}
};
struct Outer {
explicit Outer(Inner *i) : b{i} {}
void foo(int) {}
Inner* b;
template <typename Func, typename ... Args>
void CallInner(Func&& f, Args&& ... args) {
b->f(std::forward<Args>(args)...);
}
};
int main() {
Inner inner{};
Outer outer(&inner);
outer.CallInner(&Inner::bar, 5);
}
同样,我想使函数CallInner
的签名与上面的示例代码保持不变。
由于f
是一个成员函数的指针,因此在被调用之前需要先解除引用:
(b->*f)(std::forward<Args>(args)...);
关于更改签名,您没有太多选择,因为至少需要一个附加模板。
正确的语法稍微复杂一些:
struct Outer {
explicit Outer(Inner *i) : b{i} {}
void foo(int) {}
Inner* b;
template <typename Ret, typename ...FuncArgs, typename ... Args>
void CallInner(Ret (Inner::*f)(FuncArgs...), Args&& ... args) {
(b->*f)(std::forward<Args>(args)...);
}
};
CallInner
的第一个参数必须是方法指针,并且在模板上下文中,不仅需要使用一组可变参数模板参数FuncArgs
对其进行模板化,还需要使用其返回类型Ret
。然后,您还需要第二组可变参数模板参数来转发要转发的参数(它们不一定与FuncArgs
相同,因此需要单独的可变参数模板类型集)。