2011-04-09 59 views
9

我很驚訝,當我發現下面的代碼實際工作:爲什麼std :: tr1 :: function與Ob​​jective-C塊一起工作?

std::vector<int> list /*= ...*/; 
std::tr1::function<void(int)> func = ^(int i) { 
    return i + 1; 
}; 

std::for_each(list.begin(), list.end(), func); 

好像std::tr1::function能夠從一個Objective-C座正在建造的,但我不知道怎麼挺,自(去年我檢查),它的實現並不特別處理塊。它以某種方式隱含地吸出基礎函數指針?此外,這種行爲未定,可能會改變?

+1

從C++的角度來看,你的std :: function包含一個指向任何看起來像'void f(int)'的指針。如果這是塊看起來像,它會起作用(否則)。 – 2011-04-10 10:53:02

+0

@Bavarious感謝您的標籤編輯! – 2011-09-17 03:52:11

回答

5

更新:我錯了,這裏就是爲什麼它確實有效

std::tr1::function的模板參數簡單地定義簽名生成的函數對象的,不是類型,它實際上包裝。因此,包裹對象只需要提供具有匹配簽名的operator()。塊引用,比如函數指針,隱式地有這樣一個operator()(顯然,所以你可以稱它們爲)。

老,不正確的答案(這樣的評論意義)

我強烈懷疑它的工作原理,因爲該塊不從周邊範圍捕獲任何變量。在這種情況下,不需要維護狀態,所以塊引用可以表示爲裸函數指針。如果我們的代碼更改爲

std::vector<int> list /*= ...*/; 
int counter = 0; 
std::tr1::function<void(int)> func = ^(int i) { 
    counter++; 
    return i + counter; 
}; 

std::for_each(list.begin(), list.end(), func); 

應該編譯失敗,因爲塊必須用它隨身攜帶的counter捕獲值。 (當然,除非的std::tr1::function的實施已專門更新,以支持塊)

+4

只要簽名有效,'std(:: tr1):: function'完全不關心它應該調用什麼。你應該從Objective-C塊中獲得一個函子,而std(:: tr1):: function'可以很好地調用一個函數。我認爲Objective-C塊的工作類似於C++ 0x lambdas,而'std(:: tr1):: function's可以在lambdas上運行,因爲它們基本上都是函子。 :) – Xeo 2011-04-17 09:50:33

+0

你當然是對的。答覆修正。 D'哦。 – pmdj 2011-04-17 11:41:04

+0

這真的很有趣,謝謝! – 2011-04-17 14:40:01

0

雖然你可以把塊作爲Objective-C對象和Objective-C有很多的塊支持,塊不限於Objective-C的。您也可以在C和C++中使用塊。有關更多信息,請參見this article