The problem is your lambda. It doesn’t do what you think it does:
function<const A&(const A& r)> foo1 = [](const A& r) {
// ~~~~~~
return r;
};
Note that there’s no trailing return type. That means that it’s automatically deduced. Deduction never gives you a reference type, so this lambda returns an A, not an A const&. That returned temporary A is then bound to the return A const& of function‘s operator(). That temporary is not lifetime-extended. But the time we finish calling foo1(), we have a dangling reference to that temporary A. This is undefined behavior, which I guess with your compiler, gave you a helpful runtime error.
To fix this, you need to explicitly specify the return type:
function<const A&(const A& r)> foo1 = [](const A& r) -> A const& {
return r;
};
But even this is dangerous, since you can still pass a temporary A into this function and get a dangling reference out. No real way around that one.
The ease of falling into this trap is also LWG Issue 2813