はい、コードは標準に準拠しています。は+
、ラムダの単純な古い関数ポインターへの変換をトリガーします。
何が起こるかは次のとおりです。
コンパイラは最初のラムダ ( []{}
) を見て、§5.1.2 に従ってクロージャ オブジェクトを生成します。ラムダは非キャプチャラムダであるため、以下が適用されます。
5.1.2 ラムダ式 [expr.prim.lambda]
6ラムダ キャプチャのないラムダ式のクロージャ型には、クロージャ型の関数呼び出し演算子と同じパラメーターと戻り値の型を持つ関数へのポインターへの public 非仮想非明示的な const 変換関数があります。この変換関数によって返される値は、呼び出されたときにクロージャー型の関数呼び出し演算子を呼び出すのと同じ効果を持つ関数のアドレスでなければなりません。
単項演算子+
には組み込みのオーバーロードのセット、具体的には次のオーバーロードがあるため、これは重要です。
13.6 組み込み演算子 [over.built]
8すべてのタイプについてT
、次の形式の演算子関数の候補が存在します。
T* operator+(T*);
これにより、何が起こるかは非常に明確です: operator+
がクロージャー オブジェクトに適用されると、オーバーロードされた組み込み候補のセットには任意ポインターへの変換が含まれ、クロージャー型には 1 つの候補が含まれます: 関数への変換ラムダのポインター。
test
したがって、 inの型はauto test = +[]{};
と推定されvoid(*)()
ます。2 行目は簡単です。2 番目のラムダ/クロージャー オブジェクトでは、関数ポインターへの代入によって、1 行目と同じ変換がトリガーされます。2 番目のラムダのクロージャー型は異なりますが、結果として得られる関数ポインターはもちろん互換性があり、代入できます。