我可以使用错误信息复制构造一个boost :: exception吗?

时间:2015-04-16 11:36:25

标签: c++ exception boost boost-exception

考虑使用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";}
};

(实际上这段代码更复杂。例如,如果后者不是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表达式的结果。因此,提升的例外必须是可复制的,并且他们当然不会丢失他们的信息。我必须在这里遗漏一些相当明显的东西。

我做错了什么?

1 个答案:

答案 0 :(得分:3)

对我来说工作完全没问题:
(我必须在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;
}

输出:

Throw location unknown (consider using BOOST_THROW_EXCEPTION)
Dynamic exception type: N5boost16exception_detail10clone_implI14exception_implI14some_exceptionEEE
std::exception::what: blah
[P12tag_test_int] = 42

使用编译:

  • g ++(Ubuntu 4.9.2-0ubuntu1~14.04)4.9.2
  • 提升1.55

我认为问题是你在构造函数中输出诊断信息而tag_test_int没有设置为jet。