The lambda has its own type that is not std::function
. Therefore you are not catching the lambda, you are catching something else that is never thrown and can be assigned to a std::function
.
To work around it, you can wrap the lambda directly in a std::function
or a handler class an throw it.
As a minimal, working example (using a wrapper, that is a bit funnier to write):
#include <functional>
#include<utility>
#include<type_traits>
#include<iostream>
struct Base {
virtual void operator()() = 0;
};
template<typename F>
struct Lambda: F, Base {
Lambda(F &&f): F{std::forward<F>(f)} {}
void operator()() override { F::operator()(); }
};
template<typename F>
auto create(F &&f) {
return Lambda<std::decay_t<F>>{std::forward<F>(f)};
}
int main() {
try {
throw create([](){ std::cout << "doh" << std::endl; });
} catch (Base &fn) {
fn();
}
}