2017-02-20 185 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,然後你完全知道你在抓什麼。