I have some code (courtesy of progschj on GitHub) which I have adapted to exemplify my question. MakeTask moves any function and its arguments into MakeTask which makes a packaged_task. The created task is executed whereupon its future is returned to the caller. This is very slick, but I would like to be able to do this with a member function as well. But if I put Func into a struct, F&& in MakeTask fails with the errors noted in the code.
#include <future>
#include <memory>
#include <string>
#include <functional>
template<class F, class... Args>
auto MakeTask( F&& f, Args&&... args )-> std::future< typename std::result_of< F( Args... ) >::type >
{
typedef typename std::result_of< F( Args... ) >::type return_type;
auto task = std::make_shared< std::packaged_task< return_type() > >(
std::bind( std::forward< F >( f ), std::forward< Args >( args )... )
);
std::future< return_type > resultFuture = task->get_future();
( *task )( );
return resultFuture;
}
struct A
{
int Func( int nn, std::string str )
{
return str.length();
}
};
int main()
{
// error C2893: Failed to specialize function template 'std::future<std::result_of<_Fty(_Args...)>::type> MakeTask(F &&,Args &&...)'
// note: 'F=int (__thiscall A::* )(int,std::string)'
// note: 'Args={int, const char (&)[4]}'
auto resultFuture = MakeTask( &A::Func, 33, "bbb" ); // does not compile
int nn = resultFuture.get();
return 0;
}
I can make it work if I turn Func into a static, but that will break other parts of my app code.
Edit1: I figured out the syntax for std::function and modified the sample with the new error messages. MakeTask’s F&& move argument doesn’t accept my aFunc as a callable object.
Edit2: Because of Barry's answer, I change the sample code back to the original posting so his answer makes sense to future viewers.
&A::Func
is a non-static member function, which means that it needs an instance of A
to operate in. The convention that all the function objects/adapters use is that the 1st argument provided will be that instance.
MakeTask()
requires that the first argument (F
) be invoke-able with all the other arguments (Args...
). &A::Func
requires three arguments: an object of type A
(or pointer to A
or reference_wrapper<A>
), an int
, and a string
. You're simply missing the first one:
auto resultFuture = MakeTask( &A::Func, A{}, 33, "bbb" );
^^^^^