It appears that the initial impression of the error handling syntax
is off-puting for some reviewers, which is understandable. However, some
see a semantic problem with the lambda functions. So let me clarify.
A Boost Exception-style interface would work like this, for some container
of error info e:
catch( .... )
{
if( my_info const * info = get_error_info(e) )
.... // we have a my_info object.
else
.... // we don't have a my_info object.
}
This style is directly supported by LEAF, except through a different syntax:
[]( catch_<....>, my_info const * info )
{
if( info )
.... // we have a my_info object.
else
.... // we don't have a my_info object.
}
The above is semantically equivalent to the Boost Exception-style of
programming: if my_info is not available, LEAF will pass null for info,
just like get_error_info would return null in this case.
In addition LEAF supports this alternative:
[]( catch_<....>, my_info const & info )
{
.... // we have a my_info object.
}
[]( catch_<....> )
{
.... // we don't have a my_info object.
}
Handlers, like catch statements, are processed in order. If my_info is not
available, LEAF won't match the first handler above, but will potentially
match the second.
When do you use the pointer interface, and when do you use the reference
interface? It depends on the circumstances. If you take multiple error
types and each may or may not be available, the pointer interface is more
convenient, more readable, and less prone to errors. But sometimes
(usually?) it makes more sense to write two or three simple handlers
instead of one complicated handler. The codegen should be roughly the same:
even when using the reference interface, LEAF will do the equivalent of the
get_error_info call internally, it's juts that you don't see it.