[英]Type of lambdas in C++
我試圖學習C ++中的lambda,但是偶然發現了一些我不太了解的東西。
這是代碼:
#include <iostream>
typedef double Func(double);
double applyFunc(Func f, double x)
{
return f(x);
}
int main()
{
std::cout << applyFunc([](double x) {return x + 1;}, 3) << std::endl;
}
現在這可以正常工作(打印“ 4”),即所使用的lambda表達式的類型恰好是double (*)(double)
。
但是,如果我在lambda表達式中添加閉包,例如:
int main()
{
int n = 5;
std::cout << applyFunc([n](double x) {return x + n;}, 3) << std::endl;
}
然后我從編譯器得到一個錯誤:
In function ‘int main()’:
error: cannot convert ‘main()::__lambda0’ to ‘double (*)(double)’ for argument ‘1’ to ‘double applyFunc(double (*)(double), double)’
3) << std::endl;
^
我不明白為什么會這樣。 我的意思是,從applyFunc()
的角度來看,它仍然接收指向帶有double
參數並返回double
的函數的指針,並且它不知道我們從上下文中使用了變量'n',因此lambda表達式的類型應該與第一個示例相同,對嗎?
非常感謝您的幫助,在此先感謝您!
Lambda只有在沒有捕獲的情況下才可以轉換為函數指針,我們可以通過轉至標准草案第5.1.2
節Lambda表達式來說明這一點,該表達式表示( 強調我的 ):
沒有lambda捕獲的lambda表達式的閉包類型具有指向該函數的指針的公共非虛擬非顯式const 轉換函數,該函數具有與閉包類型的函數調用運算符相同的參數和返回類型。 該轉換函數返回的值應是一個函數的地址,該函數在被調用時與調用閉包類型的函數調用操作符具有相同的作用。
這是不依賴此轉換的替代解決方案:
template <typename Callable>
double applyFunc(Callable f, double x)
{
return f(x);
}
更新
如果您對使用std::function
和template之間的差異感興趣,則應閱讀std :: function vs template 。 那里有很多好的答案,還有很多值得深思的地方。
每個lambda表達式返回一個具有不同類型的對象。 如果lambda表達式沒有捕獲任何變量,則可以將其轉換為具有適當簽名的函數指針類型(即,返回類型和參數必須與lambda表達式的那些一致)。 當捕獲了一個變量時,創建的實體不能用普通函數表示。 相反,lambda表達式使用函數調用運算符產生類類型的對象。 也就是說,您的第二個代碼使用了一個lambda表達式,該表達式產生的類的對象大致與此相同:
class lambda {
int n;
public:
lambda(int n): n(n) {}
double operator()(double x) const { return x + n; }
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.