2011-11-14 82 views
7

遍歷一個矢量作品:的std :: for_each的過度的std ::集,C++ 11

std::vector<int> collection = {2, 3, 4, 5435345, 2}; 
std::for_each(collection.begin(), collection.end(), [](int& i){cout << i << endl;}); 

但不超過一套(編譯錯誤):

std::set<int> collection = {2, 3, 4, 5435345, 2}; 
std::for_each(collection.begin(), collection.end(), [](int& i){cout << i << endl;}); 

爲什麼能」 t我使用std::for_each迭代了std::set

獎金的問題: 另外,我想在拉姆達的參數來改變int&auto&,爲什麼不能這樣自動推斷?

回答

19

std::set<T>::value_typeT const而不是T;因此,您的lambda參數必須是值類型(即複製)或int const&(技術上或int const volatile&),而不是int&。即,這個工程:

std::set<int> collection{2, 3, 4, 5435345, 2}; 
std::for_each(
    collection.begin(), 
    collection.end(), 
    [](int const& i) { std::cout << i << std::endl; } 
); 

獎金的問題:另外,我想在拉姆達的參數來改變int&auto&,爲什麼不能這樣自動推斷?

因爲標準說不能;歷史上,我認爲這是由於lambdas和概念之間的相互作用過於複雜(在概念從草案中刪除之前)。 然而,我聽到有傳言說新的(C++ 11)標準的第一個缺陷報告將完全解決這個問題,因此您可能會在接下來的一兩年內爲您的編譯器添加支持。 編輯:哦,看,C++ 14現在有多態lambda表達式...

+0

你從哪裏聽到的?在Herb sutter的博客中,他提到他們不會添加多態lambda表達式,直到概念問題得到解決,因爲他們仍然希望將來可以使用類似概念的功能。 –

+0

哈哈什麼是政治家。 :)所以把它拿出來回答,你會嗎? – wilhelmtell

0

你應該能夠遍歷一個集合。但是,請注意,由於集合中的元素也是其關鍵字,因此無法修改。將代碼更改爲採用const引用,並使用cbegin/cend來代替,無論是否爲集合或不打算修改元素時。

1

取消引用set<int>迭代器是const int&。所以你不能將它作爲參數int&而不是const來傳遞。嘗試使用普通的(int i)(const int& i)

這真的不是您允許使用的地方之一auto。我認爲auto只適用於具有初始化程序的聲明或作爲尾隨返回類型的佔位符。

3

關於獎金問題:「自動」功能參數不是特定於lambda表達式的。你可能會問爲什麼我們不允許所有的函數被聲明爲f(auto x, auto y)。但這只是意味着你基本上想要用函數模板替換所有的函數。這被認爲不適用於現有的C++語言和特別的類型系統。如果你想要一個函數模板,那就已經有了一個現有的語法和機制,並且聲明「auto」參數不是要走的路。