在类模板中存储可变参数

时间:2017-04-17 15:51:43

标签: c++ c++11 templates variadic-templates template-meta-programming

我试图让一些经理在一些超时或某个时间之后处理任务等。对于这位经理我正在开发任务类,我可以保存在这个经理中并稍后执行。到目前为止,我已经有了这些类,但编译时出错了。因为我是模板中的新手,所以我无法弄清楚问题出在哪里。一切都很好,除了从类对象创建任务。但是如果那些对象中的方法没有参数,一切都会好的。我还使用了来自here的代码。所以,我的代码是:

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:在编译过程中,我遇到了以下错误:

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)'

1 个答案:

答案 0 :(得分:3)

我建议你做一些改正

(1)在public class Score : MonoBehaviour { public static int score; // The player's score. Text text; // Reference to the Text component. void Start() { // Set up the reference. text = GetComponent<Text>(); // Reset the score. score = 0; } void Update() { // Set the displayed text to the score value. text.text = "Score: " + score; } } 中,MemberTask类型的定义应该包括方法的参数;所以,而不是

Method

你应该写

typedef ReturnType(Class::*Method)();

(2)在typedef ReturnType(Class::*Method)(Types...); 中,而不是

CreateSimpleTask()

您应该在return new SimpleTask< std::result_of<decltype(func)(Arguments...)>::type, Arguments...>(std::forward<Function>(func), std::forward<Arguments>(args)...); 之前添加typename,所以

std::result_of

(3)在return new SimpleTask< typename std::result_of<decltype(func)(Arguments...)>::type, Arguments...>(std::forward<Function>(func), std::forward<Arguments>(args)...); 中你忘记了CreateMemberTask()和方法的论点;所以,而不是

typename

你应该写

return new MemberTask<
   std::result_of<decltype(method)(Class)>::type,
   Class, Arguments...>(std::forward<Class*>(obj), std::forward<Method>(method), 
                        std::forward<Arguments>(args)...);