2012-03-28 23 views
4

很久以前,我注意到在Visual C++ 10 ADL失敗時,至少有一個參數是lambda。有lambda參數時ADL失敗?

std::vector<float> vec; 
for_each(begin(vec), end(vec), [](float) {}); 

以上不能在VC++ 10和11(beta)上進行編譯(開始和結束都是通過ADL發現的)。當我將lambda函數轉換爲常規的自由函數時,事情就像預期的那樣工作。

我在Herb Sutters博客上曾經問過一次,也看過msdn connect上的一些帖子,通常的答案是:這是一個錯誤,我們還沒有實現lambda的最新標準,但當時 - 相當可以理解的。事情還沒有完成。在MS連接也出現了令人不安的評論認爲,這不會對下一個版本,即VC 11.

我的問題是,這段代碼預期 C++的11個標準下工作來解決?我不能完全弄清楚。當我使用lambda表達式時,是否真的必須將我的for_each和其他算法加上std ::前綴? 我懷疑這種行爲在vC++ 11發佈後不會改變。

+1

什麼免費功能做你用? – 2012-03-28 05:46:24

+0

像void一樣簡單f(float){}甚至可以工作。或者在函數調用之外聲明lambda:auto f = [](float){}; – 2012-03-28 13:59:34

回答

1

這是完全有效的代碼。任何無bug的編譯器都可以編譯它。但是由於MSVC有bug,所以無法通過ADL搜索函數,那麼也許你不應該依賴ADL,而是用std::來幫助編譯器找到函數。

+0

這證實了我一直在想什麼。我也不明白爲什麼lambda參數和非lambda參數的組合應禁用ADL。不知道我是否喜歡官方的微軟響應(在其他地方實例化lambda或使用std::);) – 2012-03-28 14:02:31

+0

@Martin:不,'vector :: iterator'被允許爲'T *'(我懷疑這是正是這個問題)。儘管@ refp的答案有點長,並不能證實您的懷疑,但這是正確的。雖然,我無法解釋爲什麼它可以在未通過'std'類型參數化的自由函數中工作。 – Potatoswatter 2012-03-29 06:59:10

+1

@Martin請將綠色複選標記移至refp的答案。 – 2012-08-27 16:55:58

15

該標準並不能保證你想要什麼到..

隨着下方一點,我們可以很容易地認識到,沒有什麼低保ADL會在類似於提供的示例情況下工作在你的文章中。

template <class C> auto begin(C& c) -> decltype(c.begin()); 
template <class C> auto end(C& c) -> decltype(c.end()); 

雖然Container<...>::iterator(這是返回型c.begin())是:


  • std::begin (c)/std::end (c)

    的功能是在標準作爲以下引號中描述一個實現定義的類型。

    更多關於物質可以在24.5.6範圍訪問,和23.3.6.1/2類模板矢量(或任何其他模板STL容器)中讀取後。

  • [](){} - Lambda表達式

    一個lambda是實現定義型,沒有什麼標準,說明所得到的物體將是一個類型,其是下空間std的。

    只要它符合標準設置的其他規則,它就可以存在於任何想要的地方。



過長;沒看過

其中std::begin/std::end/a lambda-expression產量不能保證下空間std的類型,因此ADL是保證在踢。

+3

@David:不,問題正是關於'for_each'。它甚至說'begin'和'end'沒有問題。我認爲大多數人沒有正確地閱讀這個問題。對於refp:+1,這是正確的答案。 – Xeo 2012-03-28 02:13:23

+0

@Xeo:我以爲ADL無法解析'begin'和'end'。無論如何,假設標準中沒有保證迭代器將處於'std'的狀態,那麼在lambda情況下未能找到'for_each'仍然存在一個錯誤(假設'std :: vector <> :: iterator'恰好在'std'中定義)或在ADL中找到'for_each',如果lambda被函數調用替代(如果'std :: vector <> :: iterator'沒有在'std ')。 – 2012-03-28 02:26:17

+0

澄清:開始和結束通過ADL在vC++ 10和11 beta中正確解析。我的問題是針對爲什麼forLeach(或任何其他std算法)的ADL失敗時,有來自命名空間std *和*一個或多個lambda的類型的組合。我認爲當有lambda參數時,vC++會禁用ADL。請注意,如果您傳遞for_each在for_each函數之外聲明的lambda表達式,則ADL可以正常工作(目前這是Microsoft的官方解決方案)。 – 2012-03-28 13:58:41