2010-07-01 74 views
8

在C++ 0x中,我想知道什麼類型是lambda函數。具體來說:什麼是lambda函數的類型?

#include<iostream> 

type1 foo(int x){ 
return [x](int y)->int{return x * y;}; 
} 

int main(){ 

std::cout<<foo(3)(4);//would output 12 

type2 bar = foo(5); 
std::cout<<bar(6);//would output 30 
return 0; 
} 

我需要用type1/type2替換以獲得上述功能嗎?希望你能看到我想要完成的事情,所以即使這不可能通過直接替換type1和type2來實現,也許你可以引導我朝着正確的方向前進。

換句話說:

  • 我怎樣才能得到一個函數返回一個匿名函數?
  • 如何爲一個變量分配一個匿名函數?

謝謝!

編輯:我與Visual Studio 2010

回答

14

你永遠無法知道lambda函數的類型,因爲什麼邏輯上出現的情況是編譯器生成與功能的(本地)類調用操作符被重載,並且一個詞法閉包由該(本地)類的數據成員表示。這是一個lambda函數在邏輯上發生,如:

auto foo = [](int x, int y) { return x + y; }; 

編譯器在邏輯上做到這一點:

struct CompilerGeneratedName { void operator()(int x, int y) const { return x + y; } }; 
CompilerGeneratedName foo; 

由於編譯器生成(局部)類,它生成一個名稱,因此,您可以從不明確寫入類型,只能從模板函數參數的任一類型推導或使用auto/decltype中推斷出類型。

另外C++ 0x閉包是靜態分配的,所以無論如何您都無法安全地返回原始C++ 0x閉包。

仍然有幾種方法可以實現這一點,第一種方法更靈活,並支持捕獲詞法範圍的lambda函數。使用std :: function,如果你有一個lambda函數不能從外部範圍捕獲任何東西,那麼你可以使用函數指針,但是這種轉換更適合於使用遺留代碼而不是任何東西。

所以基本上你想要的是這樣的:

std::function< int (int) > foo(int x) 
{ 
    return [x](int y)->int{return x * y;}; 
} 

爲什麼我一直說在邏輯上的原因,是因爲這是如何提高::拉姆達樣的作品最初(儘管C++ 03不允許本地類在模板函數參數中使用)以及添加lambda函數的想法來自哪裏,但由於這是一種語言功能,現在編譯器供應商可以以不同的和更高效的方式實現它,例如通過引用編譯器捕獲所有環境可以傳遞一個指向調用堆棧的指針而不是邏輯方式,同時仍然保持邏輯視圖。

+0

謝謝,+1。你的意思是「如果你的lambda函數沒有捕獲任何來自外部範圍的東西,那麼你可以使用函數指針。」?它不是捕獲x? – Cam 2010-07-01 20:29:23

+0

@incrediman是你的例子捕獲,所以你不能使用函數指針,只有無狀態的lambda函數可以轉換爲函數指針。 – 2010-07-01 20:32:27

+0

@snk_kid:哦。我實際上只是誤讀了你寫的東西,它的方式非常有意義:) – Cam 2010-07-01 20:34:32

6

編譯自Wikipedia

拉姆達功能的實現依賴型的函數對象;此類型的名稱僅適用於編譯器。如果用戶希望將lambda函數作爲參數,則該類型必須是模板類型,或者必須創建一個std::function來捕獲lambda值。

VC10編譯此

//Beware, brain-compiled code ahead! 
#include<iostream> 
#include<functional> 

std::function<int(int)> foo(int x) 
{ 
    return [x](int y)->int{return x * y;}; 
} 

int main(){ 

    std::cout<<foo(3)(4) << '\n'; 

    auto bar = foo(5); 
    std::cout<<bar(6) << '\n'; 

    return 0; 
} 

,並打印

 
12 
30 
+0

這工作完美,謝謝!任何想法'std :: function'能做到這一點嗎? – Cam 2010-07-01 20:27:43

+0

std :: function做模板魔術,類似於std :: bind1st所做的,除了std :: function更容易使用:-)。它基於boost :: function框架,您可以在這裏看到http://www.boost.org/doc/libs/1_43_0/doc/html/function/tutorial.html#id866455。最終,std :: function正在創建一個新類(使用模板)。這個新類使用隱式轉換將lambda函數轉換爲新類。 – Dragontamer5788 2010-07-01 21:31:41

相關問題