簡體   English   中英

C ++ 11:將lambdas轉換為源代碼中的函數對象

[英]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條)。

像往常一樣,您的代碼不應依賴於實現定義的語言部分-因此這沒什么大不了的,但是仍然可能導致意想不到的后果。

據我所知,還沒有構建這樣的工具,但是如果您要嘗試實現一個工具,那么最好的基礎結構選擇是ClangROSE

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM