Boost logo

Boost :

Subject: Re: [boost] Boost and exceptions
From: Robert Ramey (ramey_at_[hidden])
Date: 2012-06-23 17:25:47


Steven Watanabe wrote:
> AMDG
>
> On 06/23/2012 12:11 PM, Robert Ramey wrote:
>>
>> I also used boost::throw_exception in order to permit the system
>> to gracefully handle the case where exception were either not
>> available or not permited in the user environment.
>> boost::throw_exception was explicilty designed for this purpose and
>> no other.
>>
>
> This is the basic point of contention.

> According to those who favor the new version,
> boost::throw_exception is a hook to control the
> behavior of exceptions thrown by Boost libraries, and
> I think this is a perfectly reasonable interpretation.
> The original behavior was limited to two options:
>
> a) throw e;
> b) User defined boost::throw_exception(std::exception&)
>
> Boost.Exception added a third option:
> c) throw enable_current_exception(enable_error_info(x))
>
> The important thing is that adding (c) didn't
> change the /interface/ of boost::throw_exception.
>

agreed to all of the above.

>> So - boost::throw_except is changed and.... what? I already included
>> all the useful information I can add. How can boost::throw_exception
>> add to this on it's own?

> It can't. Boost.Exception allows /callers/
> of your library to add their own information
> to the exception if they have more context
> than the Serialization library itself does.

agreed - but one doesn't need boost.exception to do that.

>>> However, if all thrown exceptions inherit from boost::exception,
>>> then
>>> you simply catch that exception type, ask it to clone itself, and
>>> rethrow in a different thread. You preserve all the original error
>>> information, and crucially, all the original type information, even
>>> though the future doesn't itself know what the actual dynamic type
>>> of
>>> the caught and rethrown exception is.
>>
>> Hmmm - I don't see how just changing the implementation of
>> boost::throw_exception would change this in anyway. Perhaps you're
>> suggesting that in addition to chaning the functionality of
>> boost::throw the serialization libary should redefine
>> archive_exception to derive
>> from boost::exception rather directly from std::exception. Of course
>> that's a totally different topic than we've been discussing up until
>> now. and I guess would be a new thread. But maybe you're not
>> suggesting
>> that. Sorry if I got this wrong.
>>
>
> Actually, inheriting from boost::exception doesn't
> work for this. To enable copying you have to throw
> using boost::enable_current_exception.

> try {
> throw enable_current_exception(x);
> } catch(...) {
> exception_ptr e = current_exception();
> }
> // move e to another thread
> rethrow_exception(e);

OK - get it - but I don't see that it adds any value compared to

try {
    throw x;
}
catch(...){
    exception_ptr e = std::current_exception();
    std::rethrow_exception(e); // n3242 18.8}
}

>
>> So it looks to me that changing the functionality of boost::throw
>> adds nothing
>> to libraries which don't use boost::exception.
>>
>
> You're looking at this the wrong way. It isn't
> necessarily the /library/ that uses Boost.Exception
> functionality.

agreed.

> Whether Boost.Exception is useful
> depends on the users of the library.

agreed..

> As such,
> it seems reasonable to allow users to decide whether
> they want to use Boost.Exception, which is exactly
> what happens if the library uses the current
> incarnation of boost::throw_exception.

A user can use all the useful features of boost exception just by
just using a normal throw.

> The code using Boost.Exception would look like:

> typedef boost::error_info<
> struct tag_archive_filename, std::string> archive_filename;
> ...
>
> try {
> ifstream is(filename);
> binary_archive ia(is);
> my_data d;
> ia >> d;
> } catch (boost::exception& e) {
> e << archive_filename(filename);
> throw;
> }

lol - now you've thrown away all the information in archive_exception!
Use this instead.

try {
    ifstream is(filename);
    binary_archive ia(is);
    my_data d;
    ia >> d;
} catch (boost::archive::exception& ae) {
    // assuming you love boost exception
    boost::exception e(ae);
    ae << archive_filename(filename);
    throw(ae);
} catch(std::exception & se){
    // special sauce for standard library exceptions
    throw ...
}

Nothing in this requires any special help from boost::throw_exception.
It's all in he user's program.

>> If you really like
>> boost::exception
>> your code when you eventually can eventually rethrow
>>
>> catch (std::exception e){
>> BOOST_EXCEPTION_THROW_EXCEPTION(e)
>> }
>>
>
> This of course loses the original type of the exception.

I don't think that's true. It's not clear to me from the documentation.
I get this idea from looking at the code. Of course if it
were true it would be huge blunder in the design of the library.

>> How is this different from using std::exception ?

> std::exception doesn't allow any addition annotation.
> Using std::exception, there's simply no way to
> add any additional information without either
> a) Knowing the type of the original exception, or
> b) Discarding all the type information of the original exception.

A user can create an object at the catch site to add any information he
wants. He can do this using boost exception if he wants or any other
system he prefers. This doesn't require any thing special from the
throw site. That is, there is no reason not to use anything but simple
throw which of course is the original definition of boost::throw_exception.

Robert Ramey

>
> In Christ,
> Steven Watanabe
>
> _______________________________________________
> Unsubscribe & other changes:
> http://lists.boost.org/mailman/listinfo.cgi/boost


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk