使用任意参数调用数据成员函数的成员函数模板
Member function template to call a funcion on a data member with arbitrary arguments
我正在研究 C++11 代码库,想知道如何调用传递任意参数的成员类型上的任何函数。 请注意,因为我使用的是 C++11,所以我不能使用 std::invoke
.
之类的东西
我开始在 Outer
class 中创建函数模板,但我最初的尝试出现编译错误。
#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
不变。
关于更改签名,您没有太多选择,因为至少需要一个额外的模板。
正确的语法有点复杂:
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
进行模板化,而且它的 return 类型 Ret
。然后,您还需要第二组可变参数模板参数,用于转发参数的转发引用(可能不一定与 FuncArgs
相同,因此需要单独的一组可变参数模板类型)。
因为 f
是一个指针,所以在调用它之前需要先取消引用它的成员函数:
(b->*f)(std::forward<Args>(args)...);
我正在研究 C++11 代码库,想知道如何调用传递任意参数的成员类型上的任何函数。 请注意,因为我使用的是 C++11,所以我不能使用 std::invoke
.
我开始在 Outer
class 中创建函数模板,但我最初的尝试出现编译错误。
#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
不变。
关于更改签名,您没有太多选择,因为至少需要一个额外的模板。
正确的语法有点复杂:
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
进行模板化,而且它的 return 类型 Ret
。然后,您还需要第二组可变参数模板参数,用于转发参数的转发引用(可能不一定与 FuncArgs
相同,因此需要单独的一组可变参数模板类型)。
因为 f
是一个指针,所以在调用它之前需要先取消引用它的成员函数:
(b->*f)(std::forward<Args>(args)...);