3

The Boost Exception framework is great. You can add information to an exception derived from std::exception and boost::exception at the appropriate level of an application, as described in the documentation.

But how can such information be added if you do not control the throw site in the code, e.g. the std lib throws an exception, e.g. map throws out_of_range?

It cannot be caught as boost::exception, because it does not derive from it:

try {
  my_map.at(id);
} catch(boost::exception &e) { // NOT caught
  e << errinfo_desc("id not found, map out of range");
  throw;
}

It can be caught as std::exception because out_of_range derives from std::exception, but then no information can be added because it not a boost::exception:

try {
  my_map.at(id);
} catch(std::exception &e) {
  // compile error: e << errinfo_desc("id not found, map out of range"); 
  throw;
}

Catching a std::exception and throwing a new boost::exception loses the original location of the exception which is not desired:

try {
  my_map.at(id);
} catch(std::exception &e) {
  BOOST_THROW_EXCEPTION(my_exception() 
                        << errinfo_desc("id not found, map out of range")); 
}

Is is possible to preserve the original exception with its location etc. and still be able to add more information later? How?

user3141592
  • 121
  • 1
  • 10
  • 4
    No it's not possible to do what you want. – Some programmer dude Sep 10 '14 at 07:11
  • Are there other/better workarounds than the my last method of catching the std::exception and throwing a boost::exception, or is that the best I can do? – user3141592 Sep 10 '14 at 07:16
  • 2
    @JoachimPileborg Perhaps it _is_ possible to do what he _wants_ (who knows). Just not what he _asked_ for :) – sehe Sep 10 '14 at 11:22
  • Well, all I try to do is collect as much information as possible on all the different levels when an exception occurs, basically as explained for Boost Exception. @JoachimPileborg If you turn your comment into an answer, I'll accept it. – user3141592 Sep 11 '14 at 04:43

2 Answers2

0

Personally, I use the std::exception hierarchy wherever possible. And when they are not sufficient, then I just derive my exception class from std::exception. Never had any use case for boost::exception (perhaps all my code is too simple for that, don't know).

But if you really want to combine both, here is a wild idea: use multiple inheritance. Code sketch (untested, more like pseudocode):

// two personalities in one exception object
class MyException: public std::exception, public boost::exception {
  explicit MyException(const std::exception& stdex) { ... }
  ... other ctors as needed...

  ... other stuff ...
};

...

try {
  my_map.at(id);
} catch (const std::exception& stdex) {
  MyException myex(stdex); // gets SOME of the std::exception information
  myex << errinfo_desc("id not found, map out of range"); // boost::exception goodies
  throw myex;
}

Obvious caveat: slicing issues when initialising MyException objects with a std::exception reference. And the usual problems with MI. You have been warned :-)

András Aszódi
  • 8,948
  • 5
  • 48
  • 51
0

You can do this by catching both cases: boost::exception and std::exception

try {
    my_map.at(id);
} catch(boost::exception &e) { 
    // If already a boost exception, catch here and add information
    e << errinfo_desc("id not found, map out of range");
    throw;
} catch(std::exception &) {
    // Otherwise, catch here and convert to a boost exception
    try { boost::rethrow_exception( boost::current_exception() ); }
    catch( boost::exception& e ) { 
      e << errinfo_desc("id not found, map out of range"); 
      throw; 
    }    
}

If find it's a pain to write that much code, so I asked if there was a cleaner way of doing this: Adding error_info to std::exception

Community
  • 1
  • 1
user1924406
  • 111
  • 1
  • 8