Boost logo

Boost :

From: Emil Dotchevski (emil_at_[hidden])
Date: 2007-10-02 21:29:16


> Emil Dotchevski wrote:
> >> <snip>
> >> I agree. But that use case will become even nicer if you don't have to
> >> throw the boost::exceptionS yourself as it's done by the components you
> >> use, won't it?
> >
> > Can you please clarify what do you mean? I do not understand the above
> > paragraph at all...
>
> I mean that Exception becomes more useful the more other libraries use it.

Ah, yes. Which is why adding this library to Boost makes sense to me.

> >> As you expressed you'd like boost::exception to become THE exception
> >> class, I think you should make it as flexible and inviting to use as
> >> possible: There is a whole bunch of existing (and stable) code that uses
> >> traditional exception classes. Providing means for a smooth transition
> >> will probably increase your library's acceptance.
> >
> > I don't want to get in an argument with my review manager :) but I
> > don't think I've said that I want boost::exception to become THE
> > exception class; it's designed to act as a base class for user-defined
> > exception types much like std::exception is used today.
>
> OK, then I probably misinterpreted this one:
>
> <cite>
>
> In my ideal world, the functionality of boost::exception would be
> implemented directly by std::exception ;)
>
> </cite>

I wouldn't call even std::exception THE exception class; it's not the
only class users throw, in fact (much like boost::exception) it can't
be thrown directly because it's an abstract class.

> > As for integration with existing exception classes, Boost Exception
> > provides a special function called enable_error_info which makes
> > integrating it into existing code base safe and easy:
> >
> > http://www.revergestudios.com/boost-exception/boost-exception.htm#enable_error_info
> >
>
> Oh my, I missed it. I should've read this part of the reference docs
> inspecting the library as that multiple inheritance approach seems
> highly questionable to me for the following reasons:
>
> 1. We can't access the data in the "traditional exception" the
> Boost.Exception way (it's not tagged), and

This is exactly the same behavior as if you write an exception class
that derives from boost::exception and adds its own functionality,
which I wouldn't consider to be a problem.

> 2. calling 'what' is probably ambiguous and it seems generally awkward
> to deal with that exception where (finally) caught.

The exact type of the object returned by enable_error_info is
unspecified; you're not supposed to catch the exception by that type.

Of course you can catch it as a boost::exception, in which case what()
is not ambiguous.

You can also catch it as its original type, in which case what() is
also not ambiguous.

What do you mean by awkward?

> One could argue there is no integration at all as its basically just two
> independent classes lumped together.

I call this integration, because it instantly enables the
boost::exception functionality without breaking user code.

> > Integration in Boost is even easier, as it can be done in a single
> > place, in the boost::throw_exception function.
>
> While technically possible, this measure requires the authors of
> throwing libraries to reach consensus that it should happen - and a
> single developer with objections might blow that plan.

It is my understanding that calling boost::throw_exception when
throwing an exception is a requirement, not a guideline.

The price of the proposed use of enable_error_info in
boost::throw_exception is one empty shared_ptr. In terms of space,
this amounts to the size of two pointers added to all exception
objects. Do you think that this would be a problem?

> >> Same goes for avoiding
> >> boilerplate code and overhead compared to the traditional approach.
> >
> > Could you please explain? How does using Boost Exception require more
> > boilerplate code than the traditional approach?
>
> I mean the throw site:
>
> throw an_error(a,b,c)
>
> vs.
>
> throw an_error() << boost::error_info<a_tag>(a)
> << boost::error_info<b_tag>(b) << boost::error_info<c_tag>(c)

When you use boost::exception as a base class for an_error, nothing
stops you from writing a constructor which takes a,b and c. Then you
can throw an_error(a,b,c) as you would if you didn't use
boost::exception. Compared to the traditional approach, I see no
difference.

I think that we disagree about this issue because without
boost::exception, each and every throw needs to provide all info
stored in the exception object, which is why it makes sense to write a
constructor so that each throw is streamlined.

With boost::exception, fewer throws pack the same data anyway. But of
course you can write a constructor (as usual) if that's not the case
(personally, I prefer using a namespace-scope function to do the same
job, as I illustrated in another reply.)

> Currently it adds both boilerplate code and overhead when porting
> existing code (in a way so that it throws first-class Boost.Exceptions,
> that is).

The easiest way to port existing code to using boost::exception is to
use enable_error_info. This adds no boilerplate code, and requires no
changes to any exception classes. All you have to do is replace "throw
my_exception(a,b,c)" with "throw
enable_error_info(my_exception(a,b,c))".

Cheers,
Emil Dotchevski


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