是的,我相信第一个示例是安全的,无论在评估涉及无捕获 lambda 表达式的完整表达式期间创建的所有临时对象的生命周期如何。
根据工作草案 (n3485) 5.1.2 [expr.prim.lambda] p6
没有 lambda 捕获的 lambda 表达式的闭包类型有
公共非虚拟非显式 const 转换函数到指针
函数具有与闭包相同的参数和返回类型
类型的函数调用运算符。此转换返回的值
function 应该是一个函数的地址,当它被调用时,有
与调用闭包类型的函数调用运算符的效果相同。
上面的段落没有说明函数指针的有效性在 lambda 表达式评估后过期。
例如,我希望以下工作:
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 中实现的方式是在解析 lambda 表达式并在语义上分析一个闭包为 lambda 表达式发明了 -type,并在类中添加了一个静态函数,其语义类似于 lambda 的函数调用运算符。因此,即使 'L()' 返回的 lambda 对象的生命周期在 '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,这是我对标准字母的解释,我觉得它是可以辩护的。
希望这会有所帮助。