2014-06-18 45 views
1

(這裏是C++ 11的新手) 與C++ 11個lambda表達式嘗試一些想法組成:C++ 11組成具有的std ::功能失效

#include <iostream> 
#include <functional> 

struct A { }; 
struct B { }; 
struct C { }; 

B b4a (A a) { B b; return b; } 
C c4b (B b) { C c; return c; } 

我現在打印出來的類型如下(的type_name定義是有點偏離主題,但是我有source of everything in this question building and working online here):

cout << "b4a : " << type_name<decltype(b4a)>() << endl; 
cout << "c4b : " << type_name<decltype(c4b)>() << endl; 
auto c4a = [=] (A a) { return c4b (b4a (a)); }; 
cout << "c4a : " << type_name<decltype(c4a)>() << endl; 

產生以下合理外觀輸出:

b4a : B (A) 
c4b : C (B) 
c4a : main::{lambda(A)#1} 

我現在嘗試抽象成分本身如下:

template <typename R, typename S, typename T> 
std::function<R (T)> compose 
( std::function <R (S)> r4s 
, std::function <S (T)> s4t ) 
{ return [=] (T t) { r4s (s4t (t)); }; } 

,我得到了以下錯誤

main.cpp: In function 'int main()': 
main.cpp:44:33: error: no matching function for call to 'compose(C (&)(B), B (&)(A))' 
    auto c4a = compose (c4b, b4a); 
           ^
main.cpp:44:33: note: candidate is: 
main.cpp:34:17: note: template<class R, class S, class T> std::function<R(T)> compose(std::function<R(S)>, std::function<S(T)>) 
function<R (T)> compose 
       ^
main.cpp:34:17: note: template argument deduction/substitution failed: 
main.cpp:44:33: note: mismatched types 'std::function<R(S)>' and 'C (*)(B)' 
    auto c4a = compose (c4b, b4a); 

這暗示有一個「指針到功能型」的問題;但我認爲std::function<...>應該抽象出來呢?

在顯式類型參數

auto c4a = compose<C, B, A> (c4b, b4a); 

改變了錯誤,但不利於把:

main.cpp: In instantiation of 'std::function<R(T)> compose(std::function<R(S)>, std::function<S(T)>) [with R = C; S = B; T = A]': 

main.cpp:44:42: required from here 
main.cpp:37:42: error: could not convert '<lambda closure object>compose(std::function<R(S)>, std::function<S(T)>) [with R = C; S = B; T = A]::<lambda(A)>{std::function<C(B)>((*(const std::function<C(B)>*)(& r4s))), std::function<B(A)>((*(const std::function<B(A)>*)(& s4t)))}' from 'compose(std::function<R(S)>, std::function<S(T)>) [with R = C; S = B; T = A]::<lambda(A)>' to 'std::function<C(A)>' 
{ return [=] (T t) { r4s (s4t (t)); }; } 

在顯式轉換

auto c4a = compose (std::function<C(B)>(c4b), std::function<B(A)>(b4a)); 

auto c4a = compose<C, B, A> (std::function<C(B)>(c4b), std::function<B(A)>(b4a)); 

產生與上述相同的錯誤。線索?

+0

我忘了在上面了'return'。請參閱http://coliru.stacked-crooked.com/a/8cb674b2bddeb2c0 –

回答

1

C++ 11 std::function當需要模板類型扣除時,不會隱式接受「相同類型」的lambda表達式。在這種情況下,您必須明確地將您的lambda轉換爲std::function對象,或者將其存儲在std::function對象中,然後才能在您的功能組合中使用它。看起來,目前的C++標準不能同時處理隱式類型轉換和模板類型的推導,可能是因爲可能性的組合太多以及相關的模糊性問題。

請在這裏看到我的相關問題:why do lambda functions in c++11 not have function<> types?如果你有興趣。

基本上,每個lambda就像一個對象,它自己的調用操作符()。所以,即使你有兩個lambda都採用A並返回B,它們有兩種截然不同的類型。

我有一個包裝make_function做類型轉換爲明確的情況下here

下可能的工作:

auto c4a = compose<C, B, A> (make_function(c4b), make_function(b4a)); 
+1

嚴格地說,我不認爲這是正確的。據我可以告訴語句'[](int i,int j){return i + j; }'產生一個可以隱式轉換爲'std :: function '的lambda。我認爲這個問題出現在我們試圖用unbound模板參數隱式地將lambda轉換成std :: function的時候。 –

+0

現在,我非常想知道如何在沒有'function'轉換的情況下聲明'compose'(我已經開始工作了)。那些(失敗的)嘗試我可能應該打開另一個問題。 –

+0

我已經能夠得到,這是最小的下面'模板 功能組成 (R(R 45)(S) ,S(S4T)(T)) {return [=](T t){return r4s(s4t(t)); }; }' –