
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_err...
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