2013-01-09 8 views
23

पर क्या() पर कॉल कर सकता हूं यह मेरे पास कोड है।मैं std :: exception_ptr

try 
{ 
// code throws potentially unknown exception 
} 
catch (...) 
{ 
    std::exception_ptr eptr = std::current_exception(); 
     // then what ? 
} 

आदर्श रूप में, यदि मैं std :: अपवाद है तो मैं अपवाद से जुड़ी स्ट्रिंग प्राप्त करना चाहता हूं।

उत्तर

9

std::current_exception का उपयोग करना आपके मामले में शीर्ष पर थोड़ा सा लगता है, क्योंकि आप बाद में प्रसंस्करण के लिए std::exception_ptr को स्टोर या कॉपी करना नहीं चाहते हैं (जो इसका एकमात्र इरादा है, यह अतिरिक्त जानकारी प्राप्त करने में सहायता नहीं करता है किसी भी तरह से एक अज्ञात अपवाद)।

try 
{ 
    // code throws potentially unknown exception 
} 
catch (const std::exception &e) 
{ 
    std::cerr << e.what() << '\n'; // or whatever 
} 
catch (...) 
{ 
    // well ok, still unknown what to do now, 
    // but a std::exception_ptr doesn't help the situation either. 
    std::cerr << "unknown exception\n"; 
} 
+1

फिर std :: upgrade_ptr का असली उपयोग क्या है? – Ram

+7

@Ram इसका उपयोग एक अपवाद संग्रह और प्रतिलिपि बनाने के लिए है (जिसमें मनमाना प्रकार हो सकता है)। यह एक तरह का स्मार्ट सूचक है। कल्पना करें कि यह 'std :: shared_ptr 'जैसा है, बस यह किसी भी प्रकार के किसी भी अपवाद के लिए काम करता है (यही कारण है कि यह किसी भी प्रकार की जानकारी प्रदान नहीं करता है)। यह धागे के बीच अपवादों को प्रसारित करने के लिए विशेष रूप से उपयोगी होता है, जहां उदा। एक 'std :: वादे 'को किसी अन्य थ्रेड में' std :: भविष्य' के मान तक पहुंचने का प्रयास करते समय बाद में पुनर्स्थापित करने के लिए एक असाधारण अपवाद * स्टोर करने की आवश्यकता होती है। –

+2

@Ram अंत में जब भी आप बाद के उपयोग के लिए एक फेंक दिया अपवाद स्टोर करना चाहते हैं तो यह उपयोगी होता है (आमतौर पर कैच ब्लॉक समाप्त होने के बाद इसे नष्ट कर दिया जाएगा)। [यह] देखें (http://en.cppreference.com/w/cpp/error/exception_ptr) और इसके संबंधित पृष्ठ। –

12
try 
{ 
    std::rethrow_exception(eptr); 
} 
catch (const std::exception& e) 
{ 
    std::cerr << e.what() << std::endl; 
} 

http://en.cppreference.com/w/cpp/error/exception_ptr

+4

आपको शायद उस मामले के बारे में कुछ करना चाहिए जहां अपवाद * std :: अपवाद' से प्राप्त नहीं हुआ है ... –

+0

ओपी के मामले में ओपी के मामले में बहुत अनावश्यक है क्योंकि ओपी पहले से ही 'पकड़' ब्लॉक में है । और आम तौर पर मुझे नहीं लगता कि यह काम करेगा क्योंकि यह पहले से ही फेंक दिया अपवाद में हस्तक्षेप कर सकता है। –

+0

@KerrekSB हाँ, हमें किसी भी अपवाद को पकड़ना चाहिए और "अज्ञात त्रुटि" के बारे में कुछ प्रिंट करना चाहिए ... KonradRudolph वैसे भी, मानक द्वारा कोई अन्य मामला नहीं है। हम फ़ंक्शन लिख सकते हैं और कोशिश/पकड़ ब्लॉक के बाद इसे कॉल कर सकते हैं। – ForEveR

1

नहीं मेरी राय में सबसे अच्छा समाधान है, लेकिन काम करने के लिए लगता है।

try 
{ 
// code throws potentially unknown exception 
} 
catch (const std::exception& e) 
{ 
    std::cerr << e.what() << std::endl; 
} 
catch (...) 
{ 
    std::exception_ptr eptr = std::current_exception(); 
     // then what ? 
    LogUnknownException(); 
} 

हमेशा धन्यवाद प्रारंभिक समाधान के लिए, लेकिन मुझे यकीन है कि अगर मैं पकड़ ब्लॉक के भीतर फिर से फेंक करना चाहते हैं नहीं कर रहा हूँ करने के लिए।

+1

'current_exception' का उपयोग करना व्यर्थ है, यह कुछ भी नहीं जोड़ता है। –

4

// तो क्या: तुम सिर्फ एक std::exception के मामले में, क्या साधारण के बारे में इलाज के लिए चाहते हैं?

#include <exception> 
#include <stdexcept> 
#include <iostream> 
#include <string> 

std::string what(const std::exception_ptr &eptr = std::current_exception()) 
{ 
    if (!eptr) { throw std::bad_exception(); } 

    try { std::rethrow_exception(eptr); } 
    catch (const std::exception &e) { return e.what() ; } 
    catch (const std::string &e) { return e   ; } 
    catch (const char   *e) { return e   ; } 
    catch (...)      { return "who knows"; } 
} 

int main() 
{ 
    try { throw std::runtime_error("it's success!"); } 
    catch (...) { std::cerr << "Here is WHAT happened: " << what() << std::endl; } 

    try { throw 42; } catch (...) { std::cerr << "and now what: " << what() << std::endl; } 
} 

क्या यह प्रिंट:

यहाँ क्या है

Here is WHAT happened: it's success! 
and now what: who knows 

http://coliru.stacked-crooked.com/a/1851d2ab9faa3a24

तो यह कैच-ऑल खंड में what प्राप्त करने के लिए अनुमति देता है।

लेकिन अगर अपवाद घोंसला है तो क्या होगा ???

std::string what(const std::exception_ptr &eptr = std::current_exception()); 

template <typename T> 
std::string nested_what(const T &e) 
{ 
    try   { std::rethrow_if_nested(e); } 
    catch (...) { return " (" + what(std::current_exception()) + ")"; } 
    return {}; 
} 

std::string what(const std::exception_ptr &eptr) 
{ 
    if (!eptr) { throw std::bad_exception(); } 

    try { std::rethrow_exception(eptr); } 
    catch (const std::exception &e) { return e.what() + nested_what(e); } 
    catch (const std::string &e) { return e   ; } 
    catch (const char   *e) { return e   ; } 
    catch (...)      { return "who knows"; } 
} 

here से उदाहरण का उपयोग: यहाँ क्या है

#include <fstream> 

... 

// sample function that catches an exception and wraps it in a nested exception 
void open_file(const std::string& s) 
{ 
    try { 
     std::ifstream file(s); 
     file.exceptions(std::ios_base::failbit); 
    } catch(...) { 
     std::throw_with_nested(std::runtime_error("Couldn't open " + s)); 
    } 
} 

// sample function that catches an exception and wraps it in a nested exception 
void run() 
{ 
    try { 
     open_file("nonexistent.file"); 
    } catch(...) { 
     std::throw_with_nested(std::runtime_error("run() failed")); 
    } 
} 

int main() 
{ 
    try { throw std::runtime_error("success!"); } 
    catch (...) { std::cerr << "Here is WHAT happened: \"" << what() << '\"' << std::endl; } 

    try { run(); } 
    catch (...) { std::cerr << "what happened for run: \"" << what() << '\"' << std::endl; } 
} 

क्या छपा है:

Here is WHAT happened: "success!" 
what happened for run: "run() failed (Couldn't open nonexistent.file (basic_ios::clear))" 

http://coliru.stacked-crooked.com/a/901a0c19297f02b5

लेकिन क्या हुआ अगर प्रत्यावर्तन बहुत गहरा? क्या होगा अगर stackoverflow?अनुकूलित क्या:

#include <typeinfo> 

template <typename T> 
std::exception_ptr get_nested(const T &e) 
{ 
    try 
    { 
     auto &nested = dynamic_cast<const std::nested_exception&>(e); 
     return nested.nested_ptr(); 
    } 
    catch (const std::bad_cast &) 
     { return nullptr; } 
} 

#if 0 // alternative get_nested 
    std::exception_ptr get_nested() 
    { 
     try         { throw    ; } 
     catch (const std::nested_exception &e) { return e.nested_ptr(); } 
     catch (...)       { return nullptr  ; } 
    } 
#endif 

std::string what(std::exception_ptr eptr = std::current_exception()) 
{ 
    if (!eptr) { throw std::bad_exception(); } 

    std::string whaaat; 
    std::size_t num_nested = 0; 
    next: 
    { 
     try 
     { 
      std::exception_ptr yeptr; 
      std::swap(eptr, yeptr); 
      std::rethrow_exception(yeptr); 
     } 
     catch (const std::exception &e) { whaaat += e.what() ; eptr = get_nested(e); } 
     catch (const std::string &e) { whaaat += e   ; } 
     catch (const char   *e) { whaaat += e   ; } 
     catch (...)      { whaaat += "who knows"; } 

     if (eptr) { whaaat += " ("; num_nested++; goto next; } 
    } 
    whaaat += std::string(num_nested, ')'); 
    return whaaat; 
} 

ही क्या:

Here is WHAT happened: "success!" 
here is what: "run() failed (Couldn't open nonexistent.file (basic_ios::clear))" 

http://coliru.stacked-crooked.com/a/32ec5af5b1d43453

युपीडी

इसी तरह की सुविधा सी ++ 03 में एक चाल का उपयोग करके लागू किया जा सकता है कि अनुमति देता है कैच ब्लॉक के बाहर throw वर्तमान अपवाद के लिए: https://stackoverflow.com/a/3641809/5447906

+0

'dynamic_cast' के बजाय - 'bad_cast' पकड़ें' - 'वापसी nullptr', आपको संदर्भ के बजाय केवल' dynamic_cast' पॉइंटर चाहिए। – Miral

संबंधित मुद्दे