ラムダをサポートしていない古いコンパイラでビルドする必要がある C++11 コードのライブラリがあります。すべてのラムダを手作りの関数オブジェクトに手動で変更するのは現実的ではありません。
すべてのラムダを同等の関数クラスに自動的に抽出する、コンパイル前のステップとして実行できるツールを知っている人はいますか? おそらくclangのフロントエンドを使用できるかどうか疑問に思っていました。
ラムダをサポートしていない古いコンパイラでビルドする必要がある C++11 コードのライブラリがあります。すべてのラムダを手作りの関数オブジェクトに手動で変更するのは現実的ではありません。
すべてのラムダを同等の関数クラスに自動的に抽出する、コンパイル前のステップとして実行できるツールを知っている人はいますか? おそらくclangのフロントエンドを使用できるかどうか疑問に思っていました。
すべてのラムダを同等の関数クラスに自動的に抽出する、コンパイル前のステップとして実行できるツールを知っている人はいますか?
まあ、そのようなツールは理論的には存在するかもしれませんが、存在したとしても、最初から新しいコンパイラに切り替える方が現実的です。
次のコードを考えてみましょう。
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 に切り替える方が簡単です)。
しかし、最も楽観的な状況を考えてみましょう: プロジェクト全体のすべてのラムダ式は、 を使用して戻り値の型を定義し->
、テンプレート関数には表示されません。この場合、理論的にはoperator()
、変数を構造体としてキャプチャするコンストラクターを使用して、ラムダ式を同等の構造体に変換できます。メンバー - 同じように動作するコードを提供しますか? 答えは:それは実装定義です。
可能な限り最小のラムダも考慮してください。
auto f = [] { return 0; };
cout << is_pod<decltype(f)>::value << endl;
g++ でコンパイルすると、このコードは「0」を書き込み、clang++ を使用すると「1」を書き込みます。このラムダを関数オブジェクトに変換すると、結果の構造体は gcc と clang の両方で POD 型になります。もう一つの例:
int x = 42;
auto f = [x] { return x; };
cout << is_pod<decltype(f)>::value << endl;
g++ は「0」を返し、clang++ は「1」を返します。構造体への変換中に、関数オブジェクトのバインドされたメンバーの初期化子 (コンストラクターまたはその他) を記述する必要がありx
ます。実装に応じて、POD または非 POD のいずれかになります。匿名を作成するときにコンパイラーが行うこととは異なる場合があります。ラムダのクロージャ オブジェクト。
変更される可能性のあるその他の事項は、C++11 標準、§ 5.1.2.3 によってリストされています。
実装は、変更以外にプログラムの観察可能な動作を変更しないという条件で、以下で説明するものとは異なる方法でクロージャ タイプを定義することができます。
- クロージャータイプのサイズおよび/または配置、
- クロージャー型が自明にコピー可能かどうか (第 9 節)、
- クロージャータイプが標準レイアウトクラス(条項9)であるかどうか、または
- クロージャータイプが POD クラスであるかどうか (条項 9)。
いつものように、コードは実装で定義された言語の部分に依存すべきではありません。そのため、これはそれほど大きな問題ではありませんが、それでも予期しない結果につながる可能性があります。