Reputation: 7819
I'm trying to create sort of a closure callback class and run into some problems with template parameter deduction and matching
(The class works as follows: Upon construction, it will take a member or non-member function as well as a variable (CAPARGS
) number of arguments into a closure. The closure can then be called with a variable number of arguments (CALLARGS
), and it will call its callback function with CAPARGS
and CALLARGS
.)
ERROR 1:
candidate template ignored: could not match 'function' against 'void (*)(int)'
ERROR 2:
note: candidate template ignored: failed template argument deduction
Class code:
template <class... CALLARGS>
class Closure{
public:
// Constructor intended for use at ERROR 1
template <class OBJ, class... CAPARGS>
Closure(OBJ* obj, void (OBJ::*fct)(CAPARGS..., CALLARGS...), CAPARGS... capArgs){
callback =
[=] (CALLARGS... callArgs) -> void{
(obj->*fct)(capArgs..., callArgs...);
};
}
// Constructor intended for use at ERROR 1
template <class... CAPARGS>
Closure(std::function<void(CAPARGS..., CALLARGS...)>, CAPARGS... capArgs){
callback =
[=] (CALLARGS... callArgs) -> void{
fct(capArgs..., callArgs...);
};
}
void operator () (CALLARGS... callArgs){
callback(callArgs...);
}
private:
std::function<void(CALLARGS...)> callback;
};
Test code:
class A{
public:
virtual void fct(int a){
...
}
};
void plusF(int a){
...
}
int main(void) {
A a;
Closure<int> callF(plusF); // **ERROR 1 from here**
Closure<int> callA(&a, &A::fct); // **ERROR 2 from here**
callF(1);
callA(2);
}
I'm aware that maybe I'm doing stuff which exceeds my skills. But can I somehow fix this?
(Btw, side question: Is it reasonable to call this class Closure, or does such a construct have a different name?)
Upvotes: 0
Views: 181
Reputation: 217810
Some of your variadic template are non deductible (or create conflict), you may do instead:
template <class... CALLARGS>
class Closure{
public:
template <class OBJ, typename M, class... CAPARGS>
Closure(OBJ* obj, M (OBJ::*fct), CAPARGS... capArgs){
callback =
[=] (CALLARGS... callArgs) -> void{
(obj->*fct)(capArgs..., callArgs...);
};
}
template <typename F, class... CAPARGS>
Closure(F fct, CAPARGS... capArgs){
callback =
[=] (CALLARGS... callArgs) -> void{
fct(capArgs..., callArgs...);
};
}
void operator () (CALLARGS... callArgs){
callback(callArgs...);
}
private:
std::function<void(CALLARGS...)> callback;
};
std::bind
may be a simpler alternative:
using namespace std::placeholders;
A a;
auto callF = std::bind(plusF, _1);
auto callA = std::bind(&A::fct, &a, _1);
callF(1);
callA(2);
Upvotes: 1