2

I try to use boost exceptions and fall. There are the problem code:

struct exception_base : virtual std::exception, virtual boost::exception 
{
    exception_base(std::exception&& e)
        : std::exception(e)
    {}
};

int main()
{
    std::string exception_description;

    try
    {
        BOOST_THROW_EXCEPTION(exception_base(std::runtime_error("hello exception")));
    }
    catch (exception_base& ex)
    {
        exception_description = boost::diagnostic_information(ex);
    }

    return 0;
}

In this case the value of the exception_description have the last string - "std::exception::what: Unknown exception". It is unexpected value. If I change BOOST_THROW_EXCEPTION to usual throw - the last string of exception_description value looks expected - "std::exception::what: hello exception"

So how to use BOOST_THROW_EXCEPTION correctly?

milbrandt
  • 1,438
  • 2
  • 15
  • 20
AeroSun
  • 2,401
  • 2
  • 23
  • 46

1 Answers1

2

Your custom exception class is not necessary, and is the root cause of your problems. If you remove it you can just do this:

BOOST_THROW_EXCEPTION(std::runtime_error("hello exception"));

Then:

catch (const std::exception& ex)

And the code will work the way you expect.

Why was it not working before? Well, your exception_base class has no storage for the error message, so when you construct it from a std::exception it cannot store the message (e.g. from the original runtime_error).

You could fix it a lot of different ways, but ultimately they will boil down to the same thing: if you want your custom exception class to contain a message string, it must somehow contain that message string.

I'm a fan of not defining custom exception types 95% of the time, so I'd advise you to just keep it simple and use runtime_error (and/or logic_error).

Note that BOOST_THROW_EXCEPTION automatically adds boost::exception as a base class for the thrown type, so you do not need to do that yourself anyway--there's no advantage.


other things:

  • at your catch site use std::cerr << boost::diagnostic_information(ex) << std::endl; and that will print all the metadata that BOOST_THROW_EXCEPTION adds on like: file, line, function, etc
  • if you are throwing a std::exception inside of the BOOST_THROW_EXCEPTION() you can wrap your std::exception with boost::enable_error_info() to change the type to boost::exception and that allows you to enrich the exception with other arbitrary fields via operator<<
Trevor Boyd Smith
  • 18,164
  • 32
  • 127
  • 177
John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • Hi John, you dont get my point. It is the moust simple code that describe the trouble. I need the additional boost exception futures as line number, function name, filename where exception appears. So I need to use the class exception_base in the way as described in the boost documentation. Also for boost futures I need to use BOOST_THROW_EXCEPTION instead plain throw keyword. – AeroSun Feb 02 '18 at 12:08
  • If you try the code I suggested, you will find that it does support line number, function name, and file name where the exception was thrown. All that is done automatically by `BOOST_THROW_EXCEPTION`. Try it! – John Zwinck Feb 02 '18 at 12:10
  • I got you point. Your code just needs some fix - there must be boost::exception in the catch instead std::exception. With std::exception it is not works on my side, but with boost it works. BUT! If I need the custom exception - what I can do? – AeroSun Feb 02 '18 at 12:46
  • Also I dont get your point about "class has no storage for the error message" - why? It is derived from std::exception - so it has all functionality of the std::exception – AeroSun Feb 02 '18 at 12:48
  • If you absolutely must have a custom exception class, then you need to implement it properly, storing the message inside. You could do this by deriving from `runtime_error` or by adding a `std::string` inside the class and storing the message there. `std::exception` has no error message inside it--you can know this by observing that it has no constructor which accepts a string. – John Zwinck Feb 02 '18 at 12:49