2012-05-28 14 views
6

Quiero crear una serie de tipos de excepciones que se derivan de std :: runtime_error y quiero que tengan la funcionalidad de tipo de secuencia de cadenas. Por lo tanto, he creado una clase de excepción de que consta un std::stringstream y que se deriva de std::runtime_error:¿Por qué no puedo ver esta excepción?

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_; 
}; 

Y he creado un tipo de excepción más específica que a su vez deriva de este error_stream excepción:

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

Sin embargo, me he encontrado con algo que no entiendo aquí, porque cuando lanzo un w32file_exception en realidad solo puedo verlo ya que es el padre error_stream. ¿Alguien puede ver lo que estoy haciendo mal?

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

No conozco su caso de uso del 'operador <<' así que no sé si esto ayuda, pero solo quería mencionar [Boost.Exception] (http://www.boost.org/ doc/libs/1_49_0/libs/exception/doc/boost-exception.html) y, en particular, [Transporte de datos arbitrarios al sitio de captura] (http://www.boost.org/doc/libs/1_49_0/libs /exception/doc/tutorial_transporting_data.html) –

Respuesta

13

Qué hace exactamente su throw parece? ¿Está utilizando su operator<< antes de llamar a tiro, así:

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

entonces la respuesta es, que sus operator<< devuelve un error_stream y sin w32file_exception por lo que el tipo de la excepción lanzada es error_stream.

Se puede resolver este problema de esta manera:

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); 
    } 
    // ... 
}; 

Pero entonces perder la capacidad de captar cada error_stream excepción porque es un nuevo tipo para cada tipo DERIVED.

+0

Ahh sí, eso parece, gracias! – Benj

+0

Un par de problemas (lo intenté yo mismo pero me ganaste a la respuesta): 1. 'catch (error_stream & e)' necesita un parámetro adicional (pero esto podría deberse a que estaba usando DevStudio 2005) y 2. No hice 'static_cast', sino que tenía un' virtual D & GetThis() = 0; 'que devolvía el puntero' this' del tipo derivado, definido en el tipo derivado como 'virtual w32file_exception & GetThis() {return * this ; } ' – Skizz

+0

@Skizz 1. sí, no pensé en esto, podría predeterminar el segundo parámetro de plantilla a' error_stream'. 2. no debe hacer ninguna diferencia real. Creo que ambas soluciones funcionan –

Cuestiones relacionadas