#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; } }
This will lead to the conclusion
[struct tag_info *] = 2
I understand why this is so, but would rather have it output
[struct tag_info *] = 1
[struct tag_info *] = 2
I could, of course, typedef info like boost::error_info<struct tag_info, std::vector<std::string> > , and then accumulate all the information in std::vector before transferring it to the exception, but has two disadvantage:
a) It includes copying std :: vector
b) I need to create a vector before throwing, i.e. I cannot just use the shift operator to add additional information.
So now I'm looking for better solutions to add multiple details of the same error_info type to the exception.
EDIT:
I tried to do as Josh Kelly suggested in his comment below and overloaded 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; } }
This will lead to the conclusion
[struct tag_multiple_infos *] = 1 2
It's neat, but I like that Pyotrs respond better because it seems to me more natural and requires less code. However, if I wanted to add info for several catch 1 sites, then this solution would be more appropriate, because I do not need to know how much information I have already added.
1 = Ie dump the information into an exception, throw it, catch it somewhere else, transfer more information to it, and then rebook.