[][]boost.exceptionでエラー箇所を階層ごとに記録する。


最初から定義されてるboost::throw_functionなんかを使うとどんどん上書きされていってしまうので、例外を投げる階層ごとに異なる型を定義する。

#include <boost/exception.hpp>

#ifndef MEL_THROW_EXCEPTION
#define MEL_THROW_EXCEPTION(x) BOOST_THROW_EXCEPTION(x)
#endif // MEL_THROW_EXCEPTION

#ifndef MEL_RETHROW_EXCEPTION
#define MEL_RETHROW_EXCEPTION(e) MEL_RETHROW_EXCEPTION_IMPL(e, __LINE__)
#endif // MEL_RETHROW_EXCEPTION

#ifndef MEL_RETHROW_EXCEPTION_IMPL
#define MEL_RETHROW_EXCEPTION_IMPL(e, x) \
    e << boost::error_info<struct BOOST_JOIN(tag_mel_throw_function_, x), char const *>(BOOST_CURRENT_FUNCTION) \
      << boost::error_info<struct BOOST_JOIN(tag_mel_throw_file_, x), char const *>(__FILE__) \
      << boost::error_info<struct BOOST_JOIN(tag_mel_throw_line_, x), int>(__LINE__); \
    throw \
/**/
#endif // MEL_RETHROW_EXCEPTION_IMPL
#include <iostream>
#include <stdexcept>

class my_exception
    : public boost::exception
    , public std::runtime_error
{
public:
    my_exception(const char* msg)
        : std::runtime_error(msg)
    {}
};

void a()
{
    MEL_THROW_EXCEPTION(my_exception("test exception"));
}

void b()
{
    try { a(); }
    catch (boost::exception& e) { MEL_RETHROW_EXCEPTION(e); }
}

void c()
{
    try { b(); }
    catch (boost::exception& e) { MEL_RETHROW_EXCEPTION(e); }
}

void d()
{
    try { c(); }
    catch (boost::exception& e) { MEL_RETHROW_EXCEPTION(e); }
}

int main()
{
    try { d(); }
    catch (boost::exception& e) { std::cout << boost::diagnostic_information(e) << std::endl; }
}

出力

main.cpp(37): Throw in function void a()
Dynamic exception type: N5boost16exception_detail10clone_implI12my_exceptionEE
std::exception::what: test exception
[P21tag_mel_throw_file_43] = main.cpp
[P21tag_mel_throw_file_49] = main.cpp
[P21tag_mel_throw_file_55] = main.cpp
[P21tag_mel_throw_line_43] = 43
[P21tag_mel_throw_line_49] = 49
[P21tag_mel_throw_line_55] = 55
[P25tag_mel_throw_function_43] = void b()
[P25tag_mel_throw_function_49] = void c()
[P25tag_mel_throw_function_55] = void d()

でもこれだと型がわからないので出力するだけでboost::get_error_infoで取ってこれない。

template <int N>
struct tag_throw_function
    : boost::mpl::int_<N>
{};

みたいにすればそれぞれを取り出せるかなーと思ったんだけど、catchしたboost::exceptionからじゃ階層の深さがわからなそうなのでとりあえずこれでいいや。

コメント
0件
トラックバック
0件
ブックマーク
0 users
y_mashiro
y_mashiro

てきとうに