2011-07-13 42 views
4

從n3290 ISO草案A點: Lambda表達式:第5.1.2節,第6段:Lambda表達式:n3290草案

  "The closure type for a lambda-expression with no 
     lambda-capture has a public non-virtual non-explicit const 
     conversion function to pointer to function having the same 
     parameter and return types as the closure type’s function 
     call operator. The value returned by this conversion 
     function shall be the address of a function that, when 
     invoked, has the same effect as invoking the closure 
     type’s function call operator." 

任何一個可以用一個例子說明了這一點嗎?

+0

有沒有這個特定的部分,你覺得混亂?有沒有你不明白的術語?你不明白要求的行爲是什麼? –

+0

@ James:typedef int(* pf)(int);我們可以使用int callback(pf func){returnfunc(3);} pf func = [](int k) - > int {k--;返回k;}; – user751747

+0

@ James:就是上面的..example ..表示上面的語句... iam對於這個點有點困惑,「與調用閉包類型的函數調用操作符相同的效果」..但我可以用程序來證明.. – user751747

回答

4

簡短的回答

這只是意味着沒有捕獲任何東西的lambda可以轉換成具有相同簽名的函數指針:

auto func = [](int x) { return x * 2; }; 
int (*func_ptr)(int) = func; // legal. 

int y = func_ptr(2); // y is 4. 

並捕獲m碟剎是非法的:

int n = 2; 
auto func = [=](int x) { return x * n; }; 
int (*func_ptr)(int) = func; // illegal, func captures n 

長的答案

Lambda表達式是速記創建一個仿函數:

auto func = [](int x) { return x * 2; }; 

等同於:

struct func_type 
{ 
    int operator()(int x) const { return x * 2; } 
} 

func_type func = func_type(); 

在這種情況下func_type是「封閉式」and operator()是「函數調用操作符」。當你把一個lambda的地址,這是因爲如果你聲明的operator()靜態和取它的地址,像任何其他功能:

struct func_type 
{ 
    static int f(int x) { return x * 2; } 
} 

int (*func_ptr)(int) = &func_type::f; 

當你拍攝的變量,它們成爲func_type成員。 operator()取決於這些成員,因此它不能進行靜態:

struct func_type 
{ 
    int const m_n; 

    func_type(int n) : m_n(n) {} 
    int operator()(int x) const { return x * m_n; } 
} 

int n = 2; 
auto func = func_type(n); 

一個普通的函數沒有成員變量的概念。保持這個想法,只有在沒有成員變量的情況下,lambda才能被視爲普通函數。

+0

你知道編譯器是否應該診斷不捕獲嗎?例如,如果我寫'[=](int x){return x * 2;}',那麼即使我指定按值捕獲,我也不捕獲任何東西。 –

+0

[=]僅改變默認捕捉 - 只要您沒有捕捉任何東西,您仍然可以轉換爲函數指針。 –

+0

@ Cory這個......語句怎麼樣?「這個轉換函數返回的值應該是被調用的函數的地址,它與調用閉包類型的函數調用操作符具有相同的效果」,請您解釋一下。 。這也是 – user751747

2

這是(大致)說新的C++ 0x lambda具有轉換操作符到函數指針(具有相同的簽名)。當你調用該函數指針時,就像調用lambda(傳遞相同的參數)一樣。

...一個lambda表達式沒有拉姆達捕捉...

「沒有拉姆達捕獲」意味着你沒有捕獲從包含範圍內的任何變量,因此它是獨立的。

從這個Blurb的,我想你不能做轉換,如果你拍攝的變量(例如從本地範圍內):

// this is fine... 
std::vector<int> some_list; 
int total = 0; 
std::for_each(some_list.begin(), some_list.end(), [&total](int x) { 
    total += x; 
}); 

// so is this... 
int total = 0; 
auto someLambda = [](int x) { return x * 5; }; 
int (*pointerToLambda)(int) = someLambda; 
someFunction(pointerToLambda); 

// this won't work, because of capture... 
int total = 0; 
auto someLambda = [&total](int x) { total += x; return total; }; 
int (*pointerToLambda)(int) = someLambda; 
someFunction(pointerToLambda); 
+0

如果你捕獲任何東西,它們不能保證它,因爲它們不能。捕獲的值存儲在對象中,所以它的operator()不能是靜態的,所以它不能被轉換爲靜態/非成員函數指針。 –