【发布时间】:2020-12-08 01:00:13
【问题描述】:
我有以下代码:
class A{
public:
A() {}
void foo(const B& b) {
int a = b.a();
}
};
template<class T, typename ... ARGS>
std::function<void()> * invoke(T *t, void(T::* fn)(ARGS...), ARGS... args) {
//Create a new std::function on the heap to be executed later
std::function<void()> *f = new std::function<void()>([=]() { (t->*fn)( args... ); });
return f;
}
int main(void) {
A myA;
B myB(5, 6, 7);
std::function<void()> *fn = invoke(&myA, &A::foo, myB);
}
其目的是能够从堆上的成员函数指针(和对象指针)创建通用std::function,以供以后执行。
我的问题是,编译器似乎无法弄清楚如何正确扩展调用模板,我收到以下错误:
template argument deduction/substitution failed:
inconsistent parameter pack deduction with 'const B&' and 'B'
我希望我的 invoke() 函数的语义保持不变(即对象 *、成员函数 *、参数...)。
有没有办法在保持这些语义的同时仍然允许编译器找出正确的模板推导?
谢谢!
编辑
如果我执行以下操作,我可以让它工作:
template<class T, typename F, typename ... ARGS>
std::function<void()> * invoke(T *t, F const &fn, ARGS... args) {
std::function<void()> *f = new std::function<void()>([=]() { (t->*fn)( args... ); });
return f;
}
但是,这并不能完全满足我的需要,因为参数是两份而不是一份。当我创建在堆上分配的新 std::function 时,我希望只发生一个副本。参数仍应通过引用数学成员函数的签名来传递。
【问题讨论】:
-
你为什么需要
invoke()?尤其是在使用fn之前,您冒着myA超出范围的风险?为什么不让调用者直接创建一个 lambda,然后根据需要传递它呢?A myA; B myB(5, 6, 7); auto fn = [=](){ myA.foo(myB); }; // use fn as needed...
标签: c++ class pointers templates