5
#include <boost/exception/all.hpp>
#include <iostream>

struct myexception : virtual boost::exception, virtual std::exception {};
typedef boost::error_info<struct tag_info, std::string> info;

void main()
{
    try
    {
        BOOST_THROW_EXCEPTION(myexception()
            << info("1")
            << info("2") );
    }
    catch(const myexception& e)
    {
        std::cout << boost::diagnostic_information(e) << std::endl;
    }
}

これは出力されます

[struct tag_info *] = 2

これが事実である理由は理解していますが、むしろ出力したいと思います

[struct tag_info *] = 1
[struct tag_info *] = 2

もちろん、typedef asinfoを実行し、例外にシフトする前にboost::error_info<struct tag_info, std::vector<std::string> >すべての情報を a に蓄積することもできますstd::vectorが、これには 2 つの欠点があります 。 、つまり、単純にシフト演算子を使用して情報を追加することはできません。

error_infoしたがって、同じタイプの複数の情報を例外に追加するためのより良い解決策を探しています。


編集:
ジョシュ・ケリーが以下のコメントで提案したように、オーバーロードしてみましたoperator <<:

#include <boost/exception/all.hpp>
#include <iostream>
#include <vector>

typedef boost::error_info<struct tag_info, std::string> info;
typedef boost::error_info<struct tag_multiple_infos, std::vector<std::string> > multiple_infos;

struct myexception : virtual boost::exception, virtual std::exception
{
    myexception& operator<< (const info& rhs)
    {
        std::vector<std::string>* pinfos = boost::get_error_info<multiple_infos, myexception>(*this);
        if (pinfos != NULL)
        {
            pinfos->push_back(rhs.value());
        }
        else
        {
            std::vector<std::string> infos;
            infos.push_back(rhs.value());
            *this << multiple_infos(infos);
        }
        return *this;
    }
};

std::string to_string(const multiple_infos& info)
{
    std::ostringstream oss;
    std::for_each(info.value().begin(), info.value().end(),
        [&oss](const std::string& str) { oss << str << ' '; });
    return oss.str();
}

void main()
{
    try
    {
        BOOST_THROW_EXCEPTION(myexception()
            << info("1")
            << info("2") );
    }
    catch(const myexception& e)
    {
        std::cout << boost::diagnostic_information(e) << std::endl;
    }
}

それは出力します

[struct tag_multiple_infos *] = 1 2

それはいいことですが、Pyotrs の回答の方が私にはより自然に見え、必要なコードが少ないため、Pyotrs の回答の方が良いと思います。infoただし、複数のキャッチ サイト1に s を追加したい場合は、既に追加した情報の数を知る必要がないため、このソリューションがより適しています。

1 = つまり、情報を例外にシフトし、スローし、別の場所でキャッチし、さらに情報をシフトしてから再スローします。

4

1 に答える 1

2

2 つのタグを使用するだけです。

struct tag_info1;
struct tag_info2;
typedef boost::error_info<tag_info1, std::string> info1;
typedef boost::error_info<tag_info2, std::string> info2;

次のように使用します。

    BOOST_THROW_EXCEPTION(myexception()
        << info1("1")
        << info2("2") );

さらに情報が必要な場合は、テンプレートを使用してください。

template <unsigned N>
struct tag_info {};

template <unsigned N>
struct Nth {
  typedef boost::error_info<tag_info<N>, std::string> info;
};

    BOOST_THROW_EXCEPTION(myexception()
        << Nth<1>::info("1")
        << Nth<2>::info("2") );
于 2012-09-19T15:59:59.840 に答える