はい、最初の例は、キャプチャのないラムダ式を含む完全な式の評価中に作成されたすべての一時的なものの存続期間に関係なく、安全であると思います。
ワーキングドラフト(n3485)による5.1.2 [expr.prim.lambda] p6
ラムダキャプチャのないラムダ式のクロージャタイプには、クロージャタイプの関数呼び出し演算子と同じパラメータとリターンタイプを持つ関数へのポインタへのパブリック非仮想非明示const変換関数があります。この変換関数によって返される値は、呼び出されたときに、クロージャ型の関数呼び出し演算子を呼び出すのと同じ効果を持つ関数のアドレスでなければなりません。
上記の段落は、ラムダ式の評価後に期限切れになる関数へのポインターの有効性については何も述べていません。
たとえば、次のように機能することを期待します。
auto L = []() {
return [](int x, int y) { return x + y; };
};
int foo( int (*sum)(int, int) ) { return sum(3, 4); }
int main() {
foo( L() );
}
clangの実装の詳細は確かにC++の最後の言葉ではありませんが(標準はそうです)、気分が良くなる場合、これをclangで実装する方法は、ラムダ式が解析され、意味的に分析されるときに、ラムダ式が発明され、ラムダの関数呼び出し演算子と同様のセマンティクスで静的関数がクラスに追加されます。したがって、「L()」によって返されるラムダオブジェクトの存続期間は「foo」の本体内で終了しますが、関数へのポインターへの変換は、まだ有効な静的関数のアドレスを返します。
やや類似したケースを考えてみましょう。
struct B {
static int f(int, int) { return 0; }
typedef int (*fp_t)(int, int);
operator fp_t() const { return &f; }
};
int main() {
int (*fp)(int, int) = B{};
fp(3, 4); // You would expect this to be ok.
}
私は確かにcore-c++の専門家ではありませんが、FWIW、これは標準の文字の私の解釈であり、防御可能だと感じています。
お役に立てれば。