2012-09-19 21 views
4
#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; 
    } 
} 

这将输出增加若干个升压::同类型一个boost ::例外

的error_infos [结构tag_info *] = 2

我明白这是为什么了的情况,但宁可让它输出

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

我可以,当然,类型定义infoboost::error_info<struct tag_info, std::vector<std::string> >,然后积聚在std::vector所有的相关信息将其移动到异常之前,但它具有两个缺点:
一个)它涉及一个std的复制:: vector
b)我需要在投掷之前建立矢量,即我不能简单地使用移位运算符来添加更多信息。

因此,我现在正在寻找更好的解决方案,以便将与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; 
    } 
} 

将输出

[结构tag_multiple_infos *] = 1 2

这很整洁,但我更喜欢Pyotrs的答案,因为它对我来说显得更自然,需要的代码更少。但是,如果我想在多个捕获站点之间添加info,那么此解决方案将更合适,因为我不需要知道已添加多少个信息。

= I.e.将信息转化为例外,扔掉它,在别的地方抓住它,把更多的信息转移到它,然后重新抛出。

+2

你可以,当然,定义自己的结构提供了一个<<运算符,然后转换为boost :: error_info。这会照顾你的(b)而不是(a)。 (然而,根据你的确切的异常处理要求,我没有看到一个额外的std :: vector副本作为一个巨大的缺点。) –

回答

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")); 
+0

我想过自己编写error_infos,但有一个error_info模板的想法没有出现在我的脑海里。竖起大拇指! –