2012-09-19 19 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模板的想法沒有出現在我的腦海裏。豎起大拇指! –