2017-02-20 189 views
4

如何捕获抛出的lambda作为异常?我试过如下:捕捉lambda异常

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

但是输出

投掷 实例终止后,被称为 '主:: {拉姆达()#1}'

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

+3

请记住,每个lambda都是它自己的唯一类型,它没有任何公共基类型。此外,抛出lambda似乎是一个坏主意。 –

+3

此外,抛出一个lambda需要解决的* actual *问题是什么?您向我们展示了一个解决未知问题的通缉解决方案,并请求我们提供该解决方案的帮助,而无需告知我们应该解决什么问题。典型的[XY问题](http://xyproblem.info/)。 –

+0

我实际上不会这样编码,我只是想知道它是否可以在理论上工作。我通常尽可能避免在我的真实代码中出现异常,所以请不要担心;) –

回答

4

可以抛出std::function明确:

int main() { 
    try { 
     throw std::function<void()>([](){std::cout << "Hello there!";}); 
    } catch (std::function<void()> & fn) { 
     fn(); 
    } 
} 
1
int main() { 
    try { 
     throw [](){}; 
    } catch (std::function<void()> & fn) { 
     fn(); 
    } 
} 

两个原因是异常处理程序将不会被执行:

  1. 您正在追赶你的异常通过lvalue参考的std::function<void()>对象,但抛出的对象是该类型的未既不它是抛出对象的基类。

  2. 即使您将参数更改为值,std::function<void()>也不会从异常处理中的lambda构造而成。见this


不过,也有办法让它 “工作”。见答案by SingerOfTheFallby skypjack

1

拉姆达有它自己的类型,是不是std::function。因此,你不捕捉拉姆达,你正在捕捉别的东西,从来没有抛出,可以被分配到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(); 
    } 
} 
0

时捕获异常是主要的要求对您所捕捉的对象的特定类型。您可以使用Lambda的don't have a specific, clean type。一个干净的方法是用你的Lambda包装std::function,然后你完全知道你在抓什么。