![](/img/trans.png)
[英]Why doesn't C++11 implicitly convert lambdas to std::function objects?
[英]C++11: convert lambdas to function-objects in source
我有一個C ++ 11代碼庫,需要在不支持lambda的較舊編譯器上構建。 手動將所有lambda更改為手工制作的功能對象是不切實際的。
有誰知道我可以在預編譯步驟中運行的工具,該工具會自動將所有lambda提取到它們等效的功能類中? 我想知道是否可以使用clang的前端。
有誰知道我可以在預編譯步驟中運行的工具,該工具會自動將所有lambda提取到它們等效的功能類中?
好的,這種工具理論上可能存在,但是即使這樣做,首先簡單地切換到較新的編譯器也會更實用。
讓我們考慮以下代碼:
template <class F>
auto apply_0(F f) -> decltype(f(0)) {
auto g = [f] (int x) { return f(x); };
return g(0);
}
在這種情況下,我們的工具需要生成返回auto
類型的函數對象(這意味着生成的代碼需要使用C ++ 14進行編譯)或實例化模板以檢測出現在代碼中的所有可能的返回類型。 (這時切換到C ++ 14會更容易)。
但是,讓我們考慮最樂觀的情況:整個項目中的所有lambda表達式都使用->
定義其返回類型,並且它們不會出現在模板函數中-在這種情況下,理論上您可以使用operator()
和構造函數將lambda表達式轉換為等效的struct,將變量捕獲為結構成員-它會給您代碼,其行為方式相同嗎? 答案是: 它是實現定義的 。
考慮甚至最小的lambda:
auto f = [] { return 0; };
cout << is_pod<decltype(f)>::value << endl;
使用g ++編譯時-此代碼將使用clang ++寫入'0'-將寫入'1'。 如果我們將此lambda轉換為函數對象-生成的結構在gcc和clang中均為POD類型。 另一個例子:
int x = 42;
auto f = [x] { return x; };
cout << is_pod<decltype(f)>::value << endl;
g ++仍然會給出“ 0”,clang ++仍然會給出“ 1”。 在轉換為struct的過程中,我們需要為函數對象的綁定成員x
編寫一些初始化程序(構造函數或其他)-根據實現的不同,實現方式可能是POD或非POD-可能與編譯器在創建時所做的不同lambda的匿名關閉對象。
C ++ 11標准第5.1.2.3節列出了可能更改的其他內容:
一個實現可以定義與以下描述不同的閉包類型,但前提是這不會改變程序的可觀察行為,除非更改:
- 閉合類型的大小和/或對齊方式,
- 閉包類型是否可微復制(第9條),
- 閉合類型是否為標准布局類(第9條),或者
- 閉合類型是否為POD類(第9條)。
像往常一樣,您的代碼不應依賴於實現定義的語言部分-因此這沒什么大不了的,但是仍然可能導致意想不到的后果。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.