如何捕获作为异常抛出的lambda?我尝试了以下方法:
#include <functional>
int main() {
try {
throw [](){};
} catch (std::function<void()> & fn) {
fn();
}
}
然而输出是
在抛出一个实例后终止调用 '主:: {拉姆达()#1}'
是否有可能捕获抛出的lambda异常?
答案 0 :(得分:4)
您可以明确地抛出std::function
:
int main() {
try {
throw std::function<void()>([](){std::cout << "Hello there!";});
} catch (std::function<void()> & fn) {
fn();
}
}
答案 1 :(得分:1)
int main() {
try {
throw [](){};
} catch (std::function<void()> & fn) {
fn();
}
}
无法执行异常处理程序的两个原因:
您通过lvalue
对std::function<void()>
对象的引用捕获异常,但抛出的对象不是该类型的对象,也不是抛出对象的基类
即使您将参数更改为value,也不会在异常处理中从lambda构造std::function<void()>
。请参阅this
但是,有一些方法可以使它“工作”。查看答案by SingerOfTheFall和by skypjack
答案 2 :(得分:1)
lambda有自己的类型std::function
。因此,您没有捕获lambda,您正在捕获其他从未抛出的东西,并且可以将其分配给std::function
。
要解决它,你可以直接将lambda包装在std::function
或处理程序类中。
作为一个最小的工作示例(使用包装器,写起来有点有趣):
#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();
}
}
答案 3 :(得分:0)
捕获异常时的主要要求是为您要捕获的对象设置特定类型。您可以使用Lambda的don't have a specific, clean type。一个干净的方法是用std::function
包裹你的Lambda,然后你就知道你正在捕捉什么。