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