Search code examples
c++c++11boostboost-exception

How to use BOOST_THROW_EXCEPTION correctly?


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?


Solution

  • 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<<