2017-10-05 119 views
3

我有這個非常漂亮的包裝,但我想它接受任何數量的T,S,R,Q,...的如何將std :: function包裝器轉換爲可變參數函數?

template<typename U, typename T, typename S> 
boost::variant<U, std::string> RunSafeFn2(const std::function<U(const T&,const S&)>& f, const std::string& errMsg, const T& a1, const S& a2) 
{ 
    try 
    { 
     return f(a1,a2); 
    } 
    catch (...) 
    { 
     return errMsg; 
    } 
} 

我嘗試了以下,並已對谷歌搜索,而人錯誤信息是神祕的 - 我試圖做甚麼可能?

template<typename U, class ... Ts> 
boost::variant<U, std::string> RunSafeFnN(const std::function<U(Ts)>& f, const std::string& errMsg, Ts ... ts) 
{ 
    try 
    { 
     return bind(f, ts...); 
    } 
    catch (...) 
    { 
     return errMsg; 
    } 
} 
+1

從Clang開始,我得到'error:聲明類型包含在函數'中的'Ts'下面帶有波形的未擴展參數包'Ts''。如果我要判斷,我會說這很清楚。 – chris

+0

當然,但是它告訴我要做什麼? – Carbon

回答

7

你可以做你想做的,因爲這個簡單的程序顯示:

template <class ... Ts> 
void foo(std::function<void(Ts...)> f, Ts && ... ts) { 
    f(std::forward<Ts>(ts)...); 
} 

int main() 
{ 
    std::function<void(int)> f = [] (int i) { std::cerr << "hello " << i; }; 
    foo(f, 5); 
    return 0; 
} 

的事情是,一旦RunSafeFn2是一個模板,你不妨也模板仿函數本身。當您已經是模板時,鍵入刪除可調用函數幾乎沒有什麼好處。因此,在實踐中,它只是更有意義的事:

template <class F, class ... Ts> 
void foo(F f, Ts && ... ts) { 
    f(std::forward<Ts>(ts)...); 
} 

仍允許使用上面,但也允許這樣做的:

foo([] (int i) { std::cerr << "hello " << i; }, 5); 

這也將是更有效,因爲你完全避免創建std::function對象。爲了處理返回類型,因爲你只限於C++ 11,你可以這樣做:

template <class F, class ... Ts> 
auto foo(F f, Ts && ... ts) -> boost::variant<decltype(f(std::forward<Ts>(ts)...)), std::string> { 
    try { 
     return f(std::forward<Ts>(ts)...); 
    } 
    ... 
} 

編輯:讓我補充一個最後的思考:在C++ 11和上,其中可調用都是那麼容易創造,這是一個簡單得多的替代方案實際上是採取了調用和沒有參數:

template <class F> 
auto foo(F f) -> boost::variant<decltype(f()), std::string> { 
    try { 
     return f(); 
    } 
    ... 
} 

這是因爲它是很容易捕捉身邊,你需要的參數。例如,如果我寫了我原來的例子那樣,我可以做的使用它:

int i = 5; 
foo([&]() { std::cerr << "hello " << i; }); 

與移動只有類型時,這有利弊尤其是可能的,但如果你希望儘量減少維修負擔,你的用例很簡單,這是一個合理的選擇。

+0

所以魔法是使用std :: forward而不是綁定? – Carbon

+1

好吧,綁定是一個全紅鯡魚。它被用來創建一個從另一個可調用。但是你不想創建一個可調用的對象,你只需要調用它。對於像這樣調用可調用函數,std :: forward並不是絕對必要的,但它是出於各種原因最正確的方法。 –

+0

你能在C++ 14中做什麼更好的返回類型嗎?我們正在使用MSVC 2015.2 – Carbon

相關問題