2012-05-28 18 views
6

मैं std :: runtime_error से प्राप्त कई अपवाद प्रकार बनाना चाहता हूं और मैं चाहता हूं कि उन्हें स्ट्रिंगस्ट्रीम प्रकार की कार्यक्षमता हो। इसलिए मैं एक अपवाद वर्ग है जो एक std::stringstream तैयार करता है और जो std::runtime_error से निकला बना लिया है:मैं इस अपवाद को क्यों नहीं पकड़ सकता?

template<typename T> 
class error_stream : public std::runtime_error 
{ 
public: 
     error_stream() : 
     std::runtime_error(""), ss(std::make_shared<std::basic_stringstream<T>>()) 
     { 
     } 

     ~error_stream() throw() 
     { 
     } 

     template <typename T> 
     error_stream & operator << (const T & t) 
     { 
      *ss << t; 
      return *this; 
     } 

     virtual const char * what() const throw() 
     { 
      get_str(s_, ss->str()); 
      return s_.c_str(); 
     } 

protected: 

    template <typename T> 
    void get_str(std::basic_string<char> & s_, const std::basic_string<T> & str) const 
    { 
     s_ = str; 
    } 

    template<> 
    void get_str(std::basic_string<char> & s_, const std::basic_string<wchar_t> & str) const 
    { 
     std::basic_string<char> ret(str.begin(), str.end()); 
     s_ = ret; 
    } 

protected: 
    std::shared_ptr<std::basic_stringstream<T>> ss; 
    mutable std::basic_string<char> s_; 
}; 

और मैं एक अधिक विशिष्ट अपवाद प्रकार है जो बदले में इस error_stream अपवाद से निकला बना लिया है:

template<typename T> 
class w32file_exception : public w32utils::error_stream<T> 
{ 
public: 
    w32file_exception() : error_stream<T>() {} 
}; 

हालांकि, मुझे कुछ ऐसा सामना करना पड़ा है जो मुझे समझ में नहीं आता है, क्योंकि जब मैं w32file_exception फेंकता हूं तो मैं वास्तव में इसे केवल error_stream के रूप में पकड़ सकता हूं। क्या कोई देख सकता है कि मैं क्या गलत कर रहा हूं?

try 
    { 
     throw w32file_exception<char>() << "test"; 
    } 
    catch (w32file_exception<char> & e) 
    { 
     ASSERT_PASSED; 
    } 
    catch (error_stream<char> & e) 
    { 
     std::cout << e.what() << std::endl; // Why do I end up here? 
    } 
+0

मुझे 'ऑपरेटर <<' का उपयोग करने का मामला नहीं पता है, इसलिए मुझे नहीं पता कि इससे मदद मिलती है - लेकिन मैं बस [बूस्ट.एक्सप्शन] का उल्लेख करना चाहता था (http://www.boost.org/ डॉक्टर/libs/1_49_0/libs/अपवाद/डॉक्टर/बूस्ट-अपवाद.html) और विशेष रूप से [कैच साइट पर मनमाने ढंग से डेटा का परिवहन] (http://www.boost.org/doc/libs/1_49_0/libs /exception/doc/tutorial_transporting_data.html) –

उत्तर

13

आपके throw वास्तव में क्या दिखता है? यदि आप अपने फेंक operator<< कॉल करने से पहले उपयोग कर रहे हैं इस तरह:

throw w32file_exception<T>() << "fooobar"; 

तो जवाब है, कि अपने operator<< रिटर्न एक error_stream और कोई w32file_exception और इतने फेंका अपवाद के प्रकार error_stream है।

आप इस समस्या को इस तरह से हल कर सकते थे:

template<typename T, typename DERIVED> 
    class error_stream : public std::runtime_error 
{ 
public: 
    // ... 
    template <typename U> 
     DERIVED & operator << (const T & t) 
    { 
     *ss << t; 
     return static_cast<DERIVED&>(*this); 
    } 
    // ... 
}; 

लेकिन तब आप ढीला है, क्योंकि यह हर DERIVED प्रकार के लिए एक नया प्रकार है कि हर error_stream अपवाद को पकड़ने के लिए की क्षमता।

+0

आह हाँ, ऐसा लगता है, धन्यवाद! – Benj

+0

कुछ मुद्दों (मैंने इसे स्वयं से बाहर करने की कोशिश की लेकिन आपने मुझे जवाब में हराया): 1. पकड़ो (error_stream और ई) 'को एक अतिरिक्त पैरामीटर की आवश्यकता है (लेकिन ऐसा इसलिए हो सकता है क्योंकि मैं DevStudio 2005 का उपयोग कर रहा था) और 2। मैंने 'static_cast' नहीं किया था, बल्कि 'वर्चुअल डी और GetThis() = 0;' जो व्युत्पन्न प्रकार के 'सूचक' को वापस लौटा, जिसे व्युत्पन्न प्रकार में परिभाषित किया गया था 'वर्चुअल w32file_exception और GetThis() {return * ; } ' – Skizz

+0

@ स्किज़ 1. हाँ - इस बारे में नहीं सोचा - आप दूसरे टेम्पलेट पैरामीटर को 'error_stream' में डिफ़ॉल्ट कर सकते हैं। 2. कोई वास्तविक अंतर नहीं करना चाहिए। मुझे लगता है कि दोनों समाधान –

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