Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I extract any information from boost::errinfo_nested_exception?

I have recently started using boost::exception. Now I would like to use boost::errinfo_nested_exception to print information about the cause of the error. The problem is I can't figure out how to get information from the cause. I have tried the following with no success:

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

struct myex : public virtual boost::exception {};

int main()
{
   myex cause;
   cause << boost::errinfo_file_name("causefile.cpp");

   try {
      myex ex;
      ex << boost::errinfo_nested_exception(boost::copy_exception(cause));
      throw ex;
   }
   catch (myex& e) {
      // Here I would like to extract file name from cause and print
      // it in a nice way, but I cant figure out what to do with a
      // boost::exception_ptr.
      const boost::exception_ptr* c = 
         boost::get_error_info<boost::errinfo_nested_exception>(e);

      // I cant do this:  
      // const std::string* file = boost::get_error_info<boost::errinfo_file_name>(*c);

      // Nor this: 
      // const std::string* file = boost::get_error_info<boost::errinfo_file_name>(**c);

      // This works fine and the nested exception is there, but that's not what I want.
      std::cout << boost::diagnostic_information(e) << std::endl;
   }

   return 0;
}
like image 991
ygram Avatar asked Oct 10 '22 09:10

ygram


1 Answers

You need to rethrow the nested exception and examine that:

const boost::exception_ptr* c = 
    boost::get_error_info<boost::errinfo_nested_exception>(e);
if(c) try {
    boost::rethrow_exception(*c);
} catch(boost::exception const& e) { // or a type derived from it
    const std::string* file = boost::get_error_info<boost::errinfo_file_name>(e);
    // ...
} catch(...) {
    // presumably you don't want the exception to escape if it is
    // not derived from boost::exception
}

I personally use a get_error_info wrapper that returns the result of boost::get_error_info<some_error_info>(e), or if nothing is found the result of get_error_info<some_error_info>(nested) (recursive call here) or 0 if there is no nested exception (or it is not error_info-enabled).

Alternatively/as a complement, you can factor the checking code above (the different catch clauses) in a function:

std::string const* // or return a tuple of what you examined etc.
examine_exception()
{
    try {
        throw; // precondition: an exception is active
    } catch(boost::exception const& e) {
        // as above
        return ...;
    }
}
like image 132
Luc Danton Avatar answered Oct 19 '22 22:10

Luc Danton