我有一系列任务对象,我想将它们链接在一起,这样一个任务的输出就是下一个任务的输入。
template <typename Input, typename Output> class Task {
public:
std::function<Output(Input)> func;
Task(std::function<Output(Input)> func) : func(func){};
Output run(const Input& input) { return func(input); }
};
太好了,现在我可以将一些任务联系在一起了。
#include <iostream>
#include "Task.h"
int main() {
auto func1 = [](int i) {
return i + 1;
};
auto func2 = [](std::string i) {
return stoi(i);
};
Task<int, int> task1(func1);
Task<std::string, int> task2(func2);
std::cout << task1.run(task2.run("1"));
return 0;
}
但是现在,我想将任务放在TaskList
容器中,这样我就不需要对这些任务链进行硬编码。 API可能如下所示:
class TaskList {
public:
std::vector<ITask> tasks;
void append(ITask task) { tasks.push_back(task); }
void run() { // Run all tasks }
};
其中ITask
是各种Task<Input, Output>
类型的基类。我怎么写这样的ITask
和TaskList
类?有很多方法可以改变引入类型的方法(例如,Task
构造函数,run
方法),但我还没有找到一种方法可以推广到TaskList
。
这种做法完全错了吗?或者我正在尝试做糟糕的设计?
答案 0 :(得分:0)
如何使用递归和模板特化而不是std::vector
?
以下应该是一个工作示例
#include <functional>
#include <iostream>
template <typename, typename ...>
class TaskList;
template <typename First>
class TaskList<First>
{
public:
TaskList ()
{ }
First run (First const & firstVal) const
{ return firstVal; }
};
template <typename Output, typename Input, typename ... Prevs>
class TaskList<Output, Input, Prevs...>
{
private:
std::function<Output(Input)> const head;
TaskList<Input, Prevs...> const tail;
public:
template <typename ... Funcs>
TaskList (std::function<Output(Input)> const & f0,
Funcs const & ... funcsPre)
: head {f0}, tail {funcsPre...}
{ }
template <typename T>
Output run (T const & firstArg) const
{ return head(tail.run(firstArg)); }
};
int main ()
{
auto func0 = [](int i) { return long(i << 1); };
auto func1 = [](int i) { return i + 1; };
auto func2 = [](std::string i) { return stoi(i); };
TaskList<long, int, int, std::string> taskL012(func0, func1, func2);
std::cout << taskL012.run("1") << std::endl; // print 4
}