捕获lambda异常

时间:2017-02-20 07:11:58

标签: c++

如何捕获作为异常抛出的lambda?我尝试了以下方法:

#include <functional>
int main() {
    try {
        throw [](){};
    } catch (std::function<void()> & fn) {
        fn();
    }
}

然而输出是

  

在抛出一个实例后终止调用   '主:: {拉姆达()#1}'

是否有可能捕获抛出的lambda异常?

4 个答案:

答案 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();
    }
}

无法执行异常处理程序的两个原因:

  1. 您通过lvaluestd::function<void()>对象的引用捕获异常,但抛出的对象不是该类型的对象,也不是抛出对象的基类

  2. 即使您将参数更改为value,也不会在异常处理中从lambda构造std::function<void()>。请参阅this

  3. 但是,有一些方法可以使它“工作”。查看答案by SingerOfTheFallby 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,然后你就知道你正在捕捉什么。

相关问题