2012-07-05 49 views
8

我有下面的代碼片段,雖然完全無關緊要,但它說明了我試圖在更一般的代碼中使用的模式。用lambda和std :: function的C++ 11類型推理

template<typename InT, typename ResT> 
ResT unary_apply(InT val, std::function<ResT(InT)> fn) 
{ 
    return fn(val); 
} 

我希望能夠與函數指針,仿函數,lambda表達式等unary_apply撥打:因此使用的std::function抽象一切都拋棄。

當我嘗試使用上述以下列方式,C++(G ++ 4.7)無法執行相關類型推斷:

double blah = unary_apply(2, [](int v) { return 3.0 * v; }); 

src/fun.cpp:147:75: error: no matching function for call to ‘unary_apply(int, test()::<lambda(int)>)’ 
src/fun.cpp:147:75: note: candidate is: 
src/fun.cpp:137:6: note: template<class InT, class ResT> ResT unary_apply(InT, std::function<ResT(InT)>) 
src/fun.cpp:137:6: note: template argument deduction/substitution failed: 
src/fun.cpp:147:75: note: ‘test()::<lambda(int)>’ is not derived from ‘std::function<ResT(double)>’ 

失敗,我發現,我必須明確指定模板參數(實際上我相信它只是返回類型是無法推斷的):

double blah = unary_apply<int, double>(2, [](int v) { return 3.0 * v; }); 

我對C++ 11中的類型推斷規則並不熟悉,但上面的行爲似乎是合理的(我可以看到,通過std::function的內部機制推斷可能是一個很大的問題)。我的問題是:是否有可能重寫上面的函數以保持相同的靈活性(就可以作爲第二個參數傳遞的函數/函子等類型而言),同時還提供了更多類型推斷的線索所以我不必在調用點明確提供模板參數?

回答

9

去有點鴨鍵入y應該工作:

template <typename T, typename F> 
auto unary_apply(T&& val, F&& func) -> decltype(func(val)) { 
    return func(std::forward<T>(val)); 
} 
+0

提出的解決方案是正確的,第一句話是沒有的。類型推斷不能在問題中應用的原因與它是lambda的事實無關(您可以通過任何其他函子/函數,但仍然無法推斷該類型) – 2012-07-05 12:24:12

+0

@DavidRodríguez-dribeas:再次閱讀。 Lambda不是*函數*類型。這是一個帶有'operator()'的無名類類型。但是,是的,用'std :: function '這個推論可能不會起作用。 – 2012-07-05 12:25:02

+0

我錯過了那部分,糾正了註釋:問題不是它是lambda,而是'std :: function'的模板參數處於不可誘導的上下文中,嘗試傳遞一個常規函數(而不是'std :: function < >' - 或者你的意思是* lambda不是一個'std :: function'實例化?) – 2012-07-05 12:27:29

相關問題