Adding multiple boost :: error_infos of the same type to boost :: exception

#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.

+4
source share
1 answer

Just use two tags:

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

Use this:

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

If you need more information, use the template:

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

Source: https://habr.com/ru/post/1435088/


All Articles