¿Cómo se debe registrar cuando se desencadena una excepción?

En un programa que escribí recientemente, quería iniciar sesión cuando mi código de "lógica empresarial" activaba una excepción en las API de terceros o de proyectos. (Para aclarar, quiero iniciar sesión cuando el uso de una API provoca una excepción. Esto puede ser muchos marcos por encima del realthrow, y puede haber muchos cuadros debajo del realcatch (donde puede ocurrir el registro de la carga útil de excepción). Hice lo siguiente:

void former_function()
{
    /* some code here */
    try
    {
       /* some specific code that I know may throw, and want to log about */
    }
    catch( ... )
    {
       log( "an exception occurred when doing something with some other data" );
       throw;
    }
    /* some code here */
}

En resumen, si se produce una excepción, cree una cláusula general, registre el error y vuelva a lanzar. En mi opinión esto es seguro. Sé que en general el catch-all se considera malo, ya que uno no tiene ninguna referencia a la excepción para obtener información útil. Sin embargo, solo voy a volver a tirarlo, para que nada se pierda.

Ahora, por sí solo estaba bien, pero algunos otros programadores modificaron este programa y terminaron violando lo anterior. Específicamente, pusieron una gran cantidad de código en el bloque de prueba en un caso, y en otro eliminaron el 'lanzamiento' y colocaron un 'retorno'.

Ahora veo que mi solución era frágil; No fue una prueba de modificación futura.

Quiero una solución mejor que no tenga estos problemas.

Tengo otra solución potencial que no tiene el problema anterior, pero me pregunto qué piensan los demás. Utiliza RAII, específicamente un objeto de "Salida de alcance" que se dispara implícitamente sistd::uncaught_exception no es cierto en la construcción, aúnes verdadero en la destrucción:

#include <ciso646> // not, and
#include <exception> // uncaught_exception

class ExceptionTriggeredLog
{
private:
    std::string const m_log_message;
    bool const m_was_uncaught_exception;
public:
    ExceptionTriggeredLog( std::string const& r_log_message )
      : m_log_message( r_log_message ),
        m_was_uncaught_exception( std::uncaught_exception() )
    {
    }
    ~ExceptionTriggeredLog()
    {
        if( not m_was_uncaught_exception
            and std::uncaught_exception() )
        {
            try
            {
                log( m_log_message );
            }
            catch( ... )
            {
                // no exceptions can leave an destructor.
                // especially when std::uncaught_exception is true.
            }
        }
    }
};

void potential_function()
{
    /* some code here */
    {
       ExceptionTriggeredLog exception_triggered_log( "an exception occurred when doing something with some other data" );
       /* some specific code that I know may throw, and want to log about */
    }
    /* some code here */
}

Quiero saber:

Técnicamente, ¿esto funcionaría de manera robusta? Inicialmente parece funcionar, pero sé que hay algunas advertencias sobre el uso destd::uncaught_exception.¿Hay otra manera de lograr lo que quiero?

Nota: He actualizado esta pregunta. Específicamente, he:

añadido eltry/catch que inicialmente faltaba, alrededor dellog Llamada de función.añadido el seguimiento de lastd::uncaught_exception Estado en construcción. Esto protege contra el caso en que este objeto se crea dentro de un bloque 'try' de otro destructor que se activa como parte de la excepción de desenrollado de la pila.arreglado el nuevo 'potencial_función' para crear unllamado objeto, no untemporal Objeto como antes.

Respuestas a la pregunta(1)

Su respuesta a la pregunta