我查找了this和this SO的答案,但没有一个能解决我的问题。
简短描述:模板函数应该能够 Package 任何其他函数,也包括类的函数成员,其中应该发生比这个例子更多的事情。
最小工作示例:
#include <iostream>
template <typename T, typename ...ArgsT>
T wrapper(T(*func)(ArgsT...), ArgsT... args)
{
return func(args...);
}
class TestClass
{
public:
int mult_by_2_member(int a)
{
return a * 2;
}
static int mult_by_2_static(int a)
{
return a * 2;
}
void wrap_funcs()
{
// std::cout << "Wrapped member = "
// << wrapper(&mult_by_2_member, 2) // Prob: cannot convert `int(TestClass::*)(int) to int(*)(int)`
// << std::endl;
std::cout << "Wrapped static = " << wrapper(mult_by_2_static, 2) << std::endl;
}
};
int main()
{
TestClass test_instance;
test_instance.wrap_funcs();
// skipping wrapping of a global function... that works correctly
}
上面的代码片段中发布的错误消息是显而易见的。但我还没有弄清楚如何解决它,甚至整个开始的逻辑或意图是否有效。
任何解决方案建议或信息来源?
编辑
一种可能的解决办法是:
/* as above */
static int mult_by_2_static(TestClass* p, int a)
{
return p->mult_by_2_member(2);
}
void wrap_funcs()
{
// std::cout << "Wrapped member = " << wrapper(&mult_by_2_member, 2) << " = " << std::endl;
std::cout << "Wrapped static = " << wrapper(mult_by_2_static, this, 2) << std::endl;
}
但是这样我就必须将所有目标成员函数“预 Package ”成静态成员函数,这是一个很大的样板。
2条答案
按热度按时间3duebb1j1#
[...]模板函数应该能够 Package 任何其他函数,也包括类的函数成员,其中应该发生比这个例子更多的事情。
从你的要求,我只能建议有使用
std::invoke
(自c++17或最新).它将完成区分自由函数/非成员函数指针和成员函数指针的艰巨工作。现在你可以用成员函数调用它,如下所示:
这也将涵盖
wrapper(mult_by_2_static, 2)
的情况。j91ykkif2#
这里的问题是 * 成员函数 * 与 * 静态成员函数 * 有不同的签名(包括调用约定)-从编译器的Angular 来看,后者只是与类作用域绑定的普通函数,可能有访问限制。
你的模板函数能够接受 * 普通 * 或静态成员函数,但不能接受非静态成员函数,正如你已经注意到的那样-成员函数还有一个进一步的问题:你需要一个类型的额外示例来调用成员函数,所以你需要这样的东西:
这使得您需要两个不同的模板,一个是您已经拥有的,一个是用于成员函数指针的。is的正确语法:
请注意,
.*
运算符(以及它的指针模拟->*
运算符)的优先级低于函数调用运算符,因此不能省略括号。现在需要两个实现相同的模板,除了(成员)函数调用可能不是你想要的。
我的解决方案是将原始模板转换为更通用的形式(从这里依赖于C++11):
通过这种方式,您可以使用任意可调用对象调用模板,这些对象可以是函数或可调用对象(functors)。
现在你可以像以前一样用静态函数调用它。使用lambda执行成员函数调用,如:
如果你想避免编写lambda的不便,你仍然可以编写上面的模板重载并将lambda隐藏在里面:
所有代码完全未经测试,如果你发现一个错误,请修复自己。
旁注:您可能希望为您的 Package 器函数实现完美的转发...