c++ - 无法通过 "variables"将参数传递给基于可变参数的模板

标签 c++ c++11 templates variadic-templates variadic-functions

我已经编写了用于存储一些任务及其参数的代码,以便稍后执行。代码:

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)(Types...);

    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<typename 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<typename 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;
}

但问题是我只能通过这种方式创建这些任务:

TaskInterface* st = CreateSimpleTask(test1, 5);

Test t;
TaskInterface* mt = CreateMemberTask(&t, &Test::doIt, 66);

并且不能以这些方式:

// error C2664: 'double (int)' : cannot convert argument 1 from 'int *' to 'int'
int xxxx;
TaskBase* st = CreateSimpleTask(test1, &xxxx);

或对于 MemberTask:

// cannot convert argument 2 from 'bool (__thiscall Test::* )(std::string)' to 'bool (__thiscall Test::* )(std::string &)'
std::string ss = "sdfsdf";
TaskBase* mt = CreateMemberTask(&t, &Test::doIt, ss);

如何修改我的类以便不仅通过“值”而且通过“变量”传递参数?还是我所有的“架构”都完全错误?

最佳答案

比存储具有特定签名及其参数的函数更简单的方法是简单地存储不带参数的函数及其上下文(有时称为 thunk)。

std::function<void()> st = [] { test1(5); };
std::function<void()> mt = [&] { t.doIt(ss); };

与您的代码不同,这要简单得多,例如不会泄漏内存。您可以按值、按引用或组合来捕获上下文。 Lambda 很酷! http://en.cppreference.com/w/cpp/language/lambda .

关于c++ - 无法通过 "variables"将参数传递给基于可变参数的模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43742914/

相关文章:

c++ - 设计嵌套模板类

javascript - Angular 部分 : templateUrl Routing Local . HTML 文件

c++ - 如何记录 C++ 非类型模板参数?

c++ - 预先估计输出的 dll/exe 的大小?

c++ - 从属名称解析和命名空间标准/标准库

c++ - 从整数数组构造 bitset

c++ - 失败时 dynamic_cast 的返回类型

c++如何显示字符串搜索关键字及其确切的行号?

c++ - 更改不在 Qt 主线程上的监听端口

c++ - 遍历字符串集时没有可行的转换