Reputation: 161
I have two variadic class member functions.
When the first one Init(...)
is called I want to create a std::function to the second class member function and then bind the arguments of Init(...)
to the function pointer.
So then later on I can just call mf_()
without having to pass all arguments to Reset(...)
again
I'd like to avoid making it template class and store the arguments in a tuple.
I'm trying to make the following example work :
#include <iostream>
#include <string>
#include <functional>
using namespace std;
class Foo
{
public:
template<typename... T>
void Init(T&... args)
{
cout << __func__ << endl;
Print(args...);
// bind args.. to Reset ..
mf_ = std::bind(&Reset, args...);
// mf_ = std::bind(&Foo::Reset, this, args...); ???
}
template<typename... T>
void Reset(T&... args)
{
cout << __func__ << endl;
}
// std::function to Reset(...)
std::function<void()> mf_;
private:
template<typename First>
void Print(First& arg)
{
cout << arg << endl;
}
template<typename First, typename... Rest>
void Print(First& arg, Rest&... args)
{
cout << arg << " ";
Print(args...);
}
};
int main()
{
int arg1 = 1;
int arg2 = 2;
string arg3 { "test" };
double arg4 = 1.10;
Foo foo;
foo.Init(arg1, arg2, arg3, arg4);
//foo.mf_();
return 0;
}
Link to live example : http://cpp.sh/4ylm
When I compile I get an error that states
template argument deduction/substitution failed: 17:37:
note: couldn't deduce template parameter '_Result'
Upvotes: 2
Views: 1236
Reputation: 171263
The problem is that &Reset
is not a valid pointer-to-member expression.
You need to say &Foo::Reset
to form a pointer-to-member function, and you also need to supply the this
pointer, so you're almost correct with:
// mf_ = std::bind(&Foo::Reset, this, args...); ???
But it's still not valid because Reset
is a function template and so you need to say which specialization of the template you mean.
You can tell the compiler which specialization you want by providing an explicit template argument list:
mf_ = std::bind(&Foo::Reset<T&...>, this, args...);
Or by creating a variable of the right type, initialized from &Foo::Reset
, which allows the compiler to deduce which specialization you mean:
void (Foo::*f)(T&...) = &Foo::Reset;
mf_ = std::bind(f, this, args...);
Or by creating a typedef for the right type, and casting &Foo::Reset
to that type:
using pmf_type = void (Foo::*)(T&...);
mf_ = std::bind((pmf_type)&Foo::Reset, this, args...);
Upvotes: 2