c++ - remix - smart contracts ethereum
¿Puedo copiar y construir un boost:: excepción con la información de error? (1)
Funciona perfectamente bien para mí:
(Tuve que agregar un constructor predeterminado a exception_impl)
#include <iostream>
#include <exception>
#include <boost/exception/all.hpp>
using std::cout;
class myException : public virtual boost::exception {
};
template <class T>
class exception_impl : public virtual std::exception, public T {
public:
exception_impl() {}
exception_impl(const T& ex) : T(ex) {}
virtual const char* what() const throw() {return "blah";}
};
class some_exception : public myException {
};
struct tag_test_int;
typedef boost::error_info<tag_test_int,int> test_int_info;
void f()
{
boost::throw_exception( exception_impl<some_exception>() << test_int_info(42) );
}
int main() {
try {
f();
} catch (boost::exception& e) {
cout << boost::diagnostic_information(e);
}
return 0;
}
Salida:
Throw location unknown (consider using BOOST_THROW_EXCEPTION)
Dynamic exception type: N5boost16exception_detail10clone_implI14exception_implI14some_exceptionEEE
std::exception::what: blah
[P12tag_test_int] = 42
Compilado usando:
- g ++ (Ubuntu 4.9.2-0ubuntu1 ~ 14.04) 4.9.2
- impulso 1.55
Creo que el problema es que arrojas información de diagnóstico dentro del constructor y tag_test_int no está configurado a chorro.
Considere el siguiente código que emplea la clase de excepción de boost:
class exception : virtual public boost::exception {
// ...
};
template<typename Exc>
class exception_impl : virtual public std::exception
, public Exc {
public:
exception_impl(const Exc& exc) : Exc(exc) {}
virtual const char* what() const throw() {return "blah";}
};
(En realidad este código es más complejo. Por ejemplo, exception_impl
solo deriva de std::exception
si este último ya no es una clase base directa o indirecta de Exc
. Pero esto simplemente distrae del problema que tengo, así que me salté encima de eso.)
Dado esto, ahora puedo derivar mis propias clases de excepción:
class some_exception : public exception {
// ...
};
Y úsalas:
struct tag_test_int;
typedef boost::error_info<tag_test_int,int> test_int_info;
void f()
{
boost::throw_exception( exception_impl<some_exception>() << test_int_info(42) );
}
Sin embargo, resulta que la excepción resultante no tiene el objeto test_int_info
. Así que cambié el constructor exception_impl
para proporcionar cierta información de diagnóstico:
exception_impl(const Exc& exc)
: Exc(exc) {
std::cerr << "========================================================================/nexc:/n";
std::cerr << boost::diagnostic_information(exc);
std::cerr << "========================================================================/n*this:/n";
std::cerr << boost::diagnostic_information(*this);
std::cerr << "========================================================================/n";
}
Esto de hecho muestra que la información se pierde cuando copio el objeto Exc
en el objeto de la clase base exception_impl
:
======================================================================== exc: Throw location unknown (consider using BOOST_THROW_EXCEPTION) Dynamic exception type: some_exception [tag_test_int*] = 42 ======================================================================== *this: Throw location unknown (consider using BOOST_THROW_EXCEPTION) Dynamic exception type: exception_impl std::exception::what: "blah"
IIRC, los objetos de excepción deben poder copiarse de acuerdo con el estándar y, sin tener en cuenta posibles optimizaciones, se copia el resultado de una expresión de lanzamiento. Así que las excepciones de boost deben ser copiables y ciertamente no pierden su información en el camino. Debo estar perdiendo algo bastante obvio aquí.
¿Qué estoy haciendo mal?