Boost logo

Boost Users :

Subject: Re: [Boost-users] Exception: adding diagnostic information from a dtor?
From: Emil Dotchevski (emildotchevski_at_[hidden])
Date: 2011-06-14 18:18:15


Michael,

You're right, the boost::current_exception function is only valid
within a try block.

The issue you're raising has to do with the postconditions of
operator<<. Its current semantics guarantee that upon return the error
info is successfully stored in the exception object. This means that
when you catch an exception, you can rely on certain error info to be
present:

catch( file_read_error & e )
{
    assert(get_error_info<errinfo_file_name>(e)!=0);
    std::cerr << "Error reading " << *get_error_info<errinfo_file_name>(e);
}

Without this guarantee, the catch site would be required to deal with
any exception even if it has no error info in it.

If you are to add error info to exception objects in destructors, this
guarantee can not hold. So it seems that even though it is less
convenient and more explicit, the catch( boost::exception & e ) { e <<
errinfo_file_name(n); throw; } approach is preferable.

That said, I am not against implementing a generic type that adds
error info in its destructor as you and others have suggested, as long
as it is kept separate and doesn't change the current op<<
postconditions. Implementing this functionality in a portable manner
is not trivial, but if you or someone else wants to tackle it, I can
provide some support.

Emil Dotchevski
Reverge Studios, Inc.
http://www.revergestudios.com/reblog/index.php?n=ReCode

On Tue, Jun 14, 2011 at 2:45 PM, Michael Schuerig
<michael.lists_at_[hidden]> wrote:
>
> The FAQ for boost exception contain this example snippet for adding
> further information to an exception while the call stack is unwound
>
> catch( boost::exception & e )
>    {
>    e << foo_info(foo);
>    throw; //Okay, re-throwing the original exception object.
>    }
>
> I like that this possible, but I think the resulting code is somewhat
> tedious:
>
> void foo(const string& file_name) {
>    try {
>        do_something_fallible(file_name);
>    } catch( boost::exception & e ) {
>        e << boost::errinfo_file_name(file_name);
>        throw;
>    }
> }
>
> I'd rather write it like this:
>
> void foo(const string& file_name) {
>    diagnostic<errinfo_file_name>(file_name);
>    do_something_fallible(file_name);
> }
>
> My first, non-generic attempt fails:
>
> class diagnostic {
> public:
>    explicit diagnostic(const string& file_name)
>        : file_name_(file_name) {}
>    ~diagnostic() {
>        if ( boost::exception_ptr e = boost::current_exception() ) {
>             *e << boost::errinfo_file_name(file_name_.c_str());
>        }
>    }
> private:
>    const string file_name_;
> };
>
> The requirements for boost::current_exception() state that it may only
> be called inside a catch block, therefore the code above is illegal to
> begin with. Ignoring that, operator<< doesn't appear to be suitably
> overloaded for this use, anyway.
>
> Now, I'm wondering, is what I'm trying to achieve a bad idea? If not, is
> there another way to do it?
>
> Michael
>
> --
> Michael Schuerig
> mailto:michael_at_[hidden]
> http://www.schuerig.de/michael/
> _______________________________________________
> Boost-users mailing list
> Boost-users_at_[hidden]
> http://lists.boost.org/mailman/listinfo.cgi/boost-users


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net