Reputation: 686
I'm trying to make some manager that will work with tasks after some timeout or at some time etc. For this manager I'm developing task classes that I can save in this manager and execute later on. So far I've got these classes, but there is an error during compilation. Because I'm newbie in templates, I can't figure out where is the problem. Everything is just fine, except creating task from class object. But if the method in those object will not have parameters, everything will be fine. I used also code from here. So, my code is:
class TaskInterface
{
public:
virtual void Execute() = 0;
};
//************************************************************
namespace TaskHelper
{
template <std::size_t... Types>
struct index {};
template <std::size_t N, std::size_t... Types>
struct gen_seq : gen_seq<N - 1, N - 1, Types...> {};
template <std::size_t... Types>
struct gen_seq<0, Types...> : index<Types...>{};
}
//************************************************************
template <typename ReturnType, typename... Types>
class SimpleTask : public TaskInterface
{
public:
template <typename Function>
SimpleTask(Function&& func, Types&&... args)
: m_function(std::forward<Function>(func)),
m_args(std::make_tuple(std::forward<Types>(args)...)) {
}
void Execute() override final
{
func(m_args);
}
private:
std::function<ReturnType(Types...)> m_function;
std::tuple<Types...> m_args;
template <typename... Args, std::size_t... Is>
void func(std::tuple<Args...>& tup, TaskHelper::index<Is...>)
{
m_function(std::get<Is>(tup)...);
}
template <typename... Args>
void func(std::tuple<Args...>& tup)
{
func(tup, TaskHelper::gen_seq<sizeof...(Args)>{});
}
};
//************************************************************
template < typename ReturnType, class Class, typename... Types>
class MemberTask : public TaskInterface
{
public:
typedef ReturnType(Class::*Method)();
MemberTask(Class* object, Method method, Types&&... args) :
m_object(object), m_method(method), m_args(std::make_tuple(std::forward<Types>(args)...)) {
};
void Execute() override final
{
func(m_args);
};
private:
Class* m_object;
Method m_method;
std::tuple<Types...> m_args;
template <typename... Args, std::size_t... Is>
void func(std::tuple<Args...>& tup, TaskHelper::index<Is...>)
{
(m_object->*m_method)(std::get<Is>(tup)...);
}
template <typename... Args>
void func(std::tuple<Args...>& tup)
{
func(tup, TaskHelper::gen_seq<sizeof...(Args)>{});
}
};
//************************************************************
template <typename Function, typename... Arguments>
TaskInterface* CreateSimpleTask(Function&& func, Arguments&&... args)
{
return new SimpleTask<std::result_of<decltype(func)(Arguments...)>::type, Arguments...>(std::forward<Function>(func), std::forward<Arguments>(args)...);
}
template <class Class, typename Method, typename... Arguments>
TaskInterface* CreateMemberTask(Class* obj, Method method, Arguments&&... args)
{
return new MemberTask<std::result_of<decltype(method)(Class)>::type, Class, Arguments...>(std::forward<Class*>(obj), std::forward<Method>(method), std::forward<Arguments>(args)...);
}
//************************************************************
class Test {
public:
Test() { id = ++m_id; }
bool doIt(int n) {
std::cout << "doIt of " << n * id;
return true;
};
private:
static int m_id;
int id;
};
int Test::m_id = 0;
double test1(int xs)
{
xs *= 555;
return 66.02l;
}
int main()
{
TaskInterface* st = CreateSimpleTask(test1, 5);
st->Execute();
Test t;
TaskInterface* mt = CreateMemberTask(&t, &Test::doIt, 66);
mt->Execute();
return 0;
}
UPD1: During compilation I've got following error:
error C2664: 'MemberTask<bool,Class,int>::MemberTask(const MemberTask<bool,Class,int> &)' : cannot convert argument 2 from 'bool (__thiscall Test::* )(int)' to 'bool (__thiscall Test::* )(void)'
Upvotes: 0
Views: 712
Reputation: 66230
I suggest you some corrections
(1) in MemberTask
, the definition of the Method
type should include the arguments of the method; so, instead of
typedef ReturnType(Class::*Method)();
you should write
typedef ReturnType(Class::*Method)(Types...);
(2) in CreateSimpleTask()
, instead of
return new SimpleTask<
std::result_of<decltype(func)(Arguments...)>::type,
Arguments...>(std::forward<Function>(func), std::forward<Arguments>(args)...);
you should add a typename
before std::result_of
, so
return new SimpleTask<
typename std::result_of<decltype(func)(Arguments...)>::type,
Arguments...>(std::forward<Function>(func), std::forward<Arguments>(args)...);
(3) in CreateMemberTask()
you have forgotten the typename
and the arguments of the method; so, instead of
return new MemberTask<
std::result_of<decltype(method)(Class)>::type,
Class, Arguments...>(std::forward<Class*>(obj), std::forward<Method>(method),
std::forward<Arguments>(args)...);
you should write
return new MemberTask<
typename std::result_of<decltype(method)(Class, Arguments...)>::type,
Class, Arguments...>(std::forward<Class*>(obj), std::forward<Method>(method),
std::forward<Arguments>(args)...);
Upvotes: 3