我可以用错误信息复制构造一个 boost::exception 吗?
Can I copy-construct a boost::exception with the error info?
考虑以下使用 boost 异常的代码 class:
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";}
};
(实际上这段代码更复杂。例如,如果 std::exception
还不是 [= 的直接或间接基础 class,则 exception_impl
仅派生自 std::exception
17=]。但这只是分散了我的注意力,所以我跳过了它。)
鉴于此,我现在可以得出自己的异常 classes:
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
基础 class 对象时,信息丢失了:
========================================================================
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 表达式的结果被复制。所以 boost 的异常必须是可复制的,并且它们肯定不会在过程中丢失它们的信息。我一定在这里遗漏了一些相当明显的东西。
我做错了什么?
非常适合我:
(我必须向 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。
考虑以下使用 boost 异常的代码 class:
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";}
};
(实际上这段代码更复杂。例如,如果 std::exception
还不是 [= 的直接或间接基础 class,则 exception_impl
仅派生自 std::exception
17=]。但这只是分散了我的注意力,所以我跳过了它。)
鉴于此,我现在可以得出自己的异常 classes:
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
基础 class 对象时,信息丢失了:
======================================================================== 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 表达式的结果被复制。所以 boost 的异常必须是可复制的,并且它们肯定不会在过程中丢失它们的信息。我一定在这里遗漏了一些相当明显的东西。
我做错了什么?
非常适合我:
(我必须向 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。