2016-04-21 51 views
2

在C++ 11及更高版本中,可以使用current_exception()檢索到當前異常的exception_ptr。是否有可能在運行時確定所指向的異常的類型?如何在運行時確定exception_ptr指向的異常類型?

更確切地說,如何獲得exception_ptr所指異常的type_info的引用?我知道根據類型catch是可能的,但程序員需要爲所有可能的異常類型編寫catch塊,但這不是解決此問題的方案。

try { 
    userProvidedRuntimePlugin.executeAction(); // May throw anything 
} catch (...) { 
    auto e = std::current_exception(); 
    std::type_info & info = /* ??? */; 
    std::cerr << "Exception of type " << info.name() << " thrown." << std::endl; 
} 
+1

沒有,類型信息不能直接從異常指針中獲得。但是,真正的用例是什麼?你總是可以重新投擲和捕捉。 –

+0

@KerrekSB我只能通過類型捕獲,如果我知道異常的類型或異常的基類的類型,並非總是如此。很抱歉,由於法律原因,我無法分享有關真實用例的更多信息。 – jotik

+0

「真實」並不意味着「你在做什麼」。它可以很好地指代包含與您的真實項目相同的*設計元素的人工構建場景。你甚至不必指出這個元素是什麼。 「真實」僅僅意味着你不應該給我們一條線,而是說它不會做你想做的事。在C++中有許多你不能做的特殊事情,但這本身並不有趣。問題是,是否有什麼你可能真的想要因爲它而無法完成。 –

回答

1

嘗試類似如下:

#include <cxxabi.h> 

using namespace __cxxabiv1; 

std::string util_demangle(std::string to_demangle) 
{ 
    int status = 0; 
    char * buff = __cxxabiv1::__cxa_demangle(to_demangle.c_str(), NULL, NULL, &status); 
    if (!buff) return to_demangle; 
    std::string demangled = buff; 
    std::free(buff); 
    return demangled; 
} 

try 
{ 
    /* .... */ 
} 
catch(...) 
{ 
    std::cout <<"exception type: '" << util_demangle(abi::__cxa_current_exception_type()->name()) << "'\n"; 
} 
+0

謝謝!你的回答實際上導致我也在SO上發現了一些我的問題的重複。例如,我的問題似乎也[這裏回答](http://stackoverflow.com/a/28538250/3919155)。歡迎來到堆棧溢出! :-) – jotik

+0

'__cxa_demangle'可能會返回0,然後'std :: string demangled = buff'會導致應用程序崩潰。 –

+0

「崩潰你的應用程序」 - 不一定:如果buff == 0,則拋出std :: logic_error。 –

0

不,很遺憾,您將無法檢測到異常類型。 您auto e變量將僅僅是類型std::exception_ptr e

的。如果你想不同的行爲在特定類型的異常,你需要做的就是抓住這個例外在第一什麼的。例如:

try{ 
    userProvidedRuntimePlugin.executeAction(); // May throw anything 
} catch (std::exception e) { 
    //handle std::exception 
} catch (your::exception e2) { 
    //handle your::exception 
}catch (...) { 
    std::exception_ptr e = std::current_exception(); 
    cout << "unknown exception" << endl; 
    std::rethrow_exception(e); // for example 
} 

,如果你不知道該怎麼在這個水平上一個選項與意外的異常做重新拋出它使用std::rethrow_exception(e);