2011-07-27 5 views
5

Recientemente comencé a usar boost :: exception. Ahora me gustaría utilizar boost :: errinfo_nested_exception para imprimir información sobre la causa del error. El problema es que no puedo entender cómo obtener información de la causa. He intentado lo siguiente sin éxito:¿Cómo extraigo información de boost :: errinfo_nested_exception?

#include <iostream> 
#include <boost/exception/all.hpp> 

struct myex : public virtual boost::exception {}; 

int main() 
{ 
    myex cause; 
    cause << boost::errinfo_file_name("causefile.cpp"); 

    try { 
     myex ex; 
     ex << boost::errinfo_nested_exception(boost::copy_exception(cause)); 
     throw ex; 
    } 
    catch (myex& e) { 
     // Here I would like to extract file name from cause and print 
     // it in a nice way, but I cant figure out what to do with a 
     // boost::exception_ptr. 
     const boost::exception_ptr* c = 
     boost::get_error_info<boost::errinfo_nested_exception>(e); 

     // I cant do this: 
     // const std::string* file = boost::get_error_info<boost::errinfo_file_name>(*c); 

     // Nor this: 
     // const std::string* file = boost::get_error_info<boost::errinfo_file_name>(**c); 

     // This works fine and the nested exception is there, but that's not what I want. 
     std::cout << boost::diagnostic_information(e) << std::endl; 
    } 

    return 0; 
} 

Respuesta

2

Es necesario volver a lanzar la excepción anidada y examinar lo siguiente:

const boost::exception_ptr* c = 
    boost::get_error_info<boost::errinfo_nested_exception>(e); 
if(c) try { 
    boost::rethrow_exception(*c); 
} catch(boost::exception const& e) { // or a type derived from it 
    const std::string* file = boost::get_error_info<boost::errinfo_file_name>(e); 
    // ... 
} catch(...) { 
    // presumably you don't want the exception to escape if it is 
    // not derived from boost::exception 
} 

Yo personalmente uso un envoltorio get_error_info que devuelve el resultado de boost::get_error_info<some_error_info>(e), o si no se encuentra nada el resultado de get_error_info<some_error_info>(nested) (llamada recursiva aquí) o 0 si no hay una excepción anidada (o no está error_info-habilitado).

Alternativamente/como complemento, se puede factorizar el código de verificación de arriba (los diferentes catch cláusulas) en una función:

std::string const* // or return a tuple of what you examined etc. 
examine_exception() 
{ 
    try { 
     throw; // precondition: an exception is active 
    } catch(boost::exception const& e) { 
     // as above 
     return ...; 
    } 
} 
+0

un poco extraño a tener que retrhow, pero supongo que es una rareza en el impulso . Tal vez tiene algo que ver con tipear. De todos modos, resolvió mi problema. ;) – ygram

+0

@ygram Viene de cómo se especifica 'boost :: exception_ptr' - su interfaz es bastante minimalista, y la única manera de hacer algo útil con la excepción * stored * (en oposición al puntero en sí) es volver a lanzar . Dado que ha sido aceptado en 'std :: exception_ptr' y que los idiomas permiten lanzar, p. 'int', en realidad es un diseño bastante sólido. –

Cuestiones relacionadas