C++中lambda與function的推導問題?

(非常抱歉問題描述不清楚,當時在上課用的手機編輯的。已修改問題描述)

平台 :linux

編譯器 :g++

版本 6.1.1

附加命令:-std=c++0x

我在看SICP的時候對於第一章描述的過程抽象問題時,說到sum函數的抽象,於是我就想去用C++通過模板去實現函數類似下面

template&
auto sum_iter(T *begin , T *end , function& term , function&next)-&> T;

其中term是對求和過程中數據的操作,比如求平方和,立方和之類的,next是對於指針移動的操作。

然後在調用這個函數時,可以選擇通過傳函數指針或者lambda函數給term和next。例如這個

int a[4];
sum_iter(a, a + 4 , [](int i){ return i; } , [](int **p){ (*p)++; });

但是在編譯的時候,報錯誤說沒有匹配的函數。

目前我用的辦法是通過一個輔助的模板類

template&
struct type_deduce
{
using type = T;
}
template&
auto sum_iter(T *begin , T *end , const typename type_deduce&&>::type term , const typename type_deduce&&>::type next);

這樣子就可以推導出來了,其中的原理在c++ primer 和 effctive 系列中看到過,可還是不太懂。編譯器在面對模板推導時是怎樣思考的,以及對於模板編程這樣子的設計,肯定有支撐它的思想與理由在其中,希望有大神能站在編譯器的角度幫忙解釋下個中原理。

(PS:剛入門,提問的地方或有不妥,我不知道自己問的這個問題範圍大不大,如果範圍很大,那麼有什麼推薦的書去閱讀或者通過什麼辦法可以提高自己這方面的能力)

利益相關:二本學校軟體工程大二,學校課程很亂。自己自學c++大概接近一年,看了c++ primer,課後習題中等偏下的都寫了,難一點的是看github上面的習題答案,理解然後自己照著敲了一遍。effctive c++看完了,正在看more effctive,書中部分內容看了深有體會,也有部分內容可能沒經歷過,所以看得一知半解。目前大二下學期自己跟著公開課視頻看CSAPP以及SICP,現在就是想迫切用c++把學過的知識穿起來,深知自己看了許多書,但是沒有實踐下來所以記憶與體會不深刻。目前用c++也就刷刷POJ的題目,然後模仿著寫一寫簡陋的東西,比如c++ primer上引導著寫的簡單版vector,感覺自己陷入了困境,這個問題下面也想尋求下幫助,謝謝。


你應該把錯誤信息、完整代碼和你使用的什麼平台等詳細信息都發上來,而不是讓回答者們猜你可能哪裡有錯

反正我這裡一點問題都沒有

至於你問匹配是如何發生的,std::function會有一個模板構造函數,模板SFINAE檢查通過的話,你寫的lambda會被用來調用那個構造函數,然後function把這個函數裝進自己內部。

匹配失敗的話,多半是SFINAE檢查沒有通過,而既然你寫的是對的,我懷疑是是編譯器對SFINAE支持不好

更新了啊

template&
auto sum_iter(T *begin, T *end, function& term, function&next)-&>T
{
return 0;
}

int main()
{
int a[4]{};
sum_iter(a, a + 4, [](int i) { return i; }, [](int **p) { (*p)++; });
}

簡單說一下,就是lambda到function的轉換隻能是正向的,也就是說,function的類型已經確定的情況下,可以有一個合適的lambda轉換到這個function。

然而在你這個情況下,參數2是function&,這個T是個模板參數,是需要編譯時推導來確定的,而編譯器沒法通過lambda來確定function&的T究竟是什麼,所以就報了個錯(這個問題在C++17有了模板參數推導之後應該會有所解決)

你上面寫的那個解決方案,實際上是通過又套了一層模板,讓編譯器不去嘗試用lambda推導T,而是用前兩個參數,a和a+4來推導T,這樣就會成功了

當然更簡單的方法,是顯式把T寫出來,不用編譯器去推導

sum_iter&(a, a + 4, [](int i) { return i; }, [](int **p) { (*p)++; });


VS2015表示沒有問題


可能你寫錯了。

引用孫明琦的回答。

實際上是通過又套了一層模板,讓編譯器不去嘗試用lambda推導T,而是用前兩個參數,a和a+4來推導T,這樣就會成功了。


推薦閱讀:

人人都可以製作的三種基礎外掛教程(附GitHub源碼)
計算機發展史——史前計算機
Linux學習——文件和目錄操作命令【1】
右鍵菜單 添加新的 文件對象關聯菜單
調試程序時,設置斷點的原理是什麼?

TAG:計算機 | C | 模板C |