2016-12-05 68 views
0

我有一系列我想鏈接在一起的任務對象,這樣一個任務的輸出就是下一個任務的輸入。在模板對象向量中的每個元素上調用模板方法

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>類型的基類。我該如何寫這樣的ITaskTaskList類?在引入類型的地方有很多方法來進行混洗(例如,Task構造函數,run方法),但是我還沒有找到推廣到TaskList的方法。

這種方法是完全錯誤的嗎?或者是我想要做不好的設計?

+3

你有問題。如果使用通用容器,則每個階段的輸入/輸出類型在編譯時都是未知的。這意味着您需要將每個階段的結果存儲在「變體」或「任意」中,然後下一階段必須將變體強制轉換爲正確的類型(或將其轉換或扔出) –

+0

@RichardHodges或者如果任務I/O類型在編譯時是已知的,'tuple'' – AndyG

+0

啊,我希望避免走這條路,但是,輸入/輸出類型在編譯時是未知的。我也可以爲我的所有輸入/輸出類型設置一個基類,但這很糟糕,因爲我可能無法控制所有類型。 – danielsuo

回答

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 
} 
+0

我認爲它會起作用。但是,與通常使用遞歸和模板專業化不同,通常不會耗盡實施限制,我認爲OP可能會尋求一些限制鏈條運行時間的限制。 –

+0

感謝這個有趣的解決方案!但是,除了@ YanZhou的評論之外,我似乎還需要在編譯時指定任務鏈。我的應用程序也許能夠擺脫這種情況,但我需要考慮更多。關於'std :: vector',我的錯在原文中沒有提及;我可能想要隨機訪問單個任務來修改或交換它們。 – danielsuo

+0

@danielsuo - 您需要在**運行**時間指定任務鏈?哇!如果是這樣,這是完全不同的情況。你應該在你的問題中指定這個,並顯示你想寫的代碼的例子。你有編輯特權給你的問題?如果沒有,你應該打開另一個問題,或者,如果你能更好地解釋,我可以編輯本爲你解答。 – max66