Рассмотрим следующий код, использующий класс форсированного исключения:
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";}
};
(На самом деле этот код более сложный. Например, exception_impl
происходит только от std::exception
, если последний не является прямым или косвенным базовым классом Exc
. Но это просто отвлекает от проблемы я есть, поэтому я пропустил это.)
Учитывая это, теперь я могу получить свои собственные классы исключений:
class some_exception : public exception {
// ...
};
И используйте их:
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) );
}
Тем не менее, оказывается, что в результате исключения не имеет объекта test_int_info
. Поэтому я изменил конструктор exception_impl
, чтобы предоставить некоторую диагностическую информацию:
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";
}
Это действительно показывает, что информация теряется при копировании объекта Exc
в объект базового класса 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, объекты исключений должны быть скопированы в соответствии со стандартом и, невзирая на возможные оптимизации, копируется результат выражения throw. Таким образом, форсированные исключения должны быть скопируемыми и, конечно же, не теряют информацию на этом пути. Я должен упустить что-то довольно очевидное здесь.
Что я делаю неправильно?