On 15/02/2022 15:38, Peter Dimov wrote:
I think there might be a misunderstanding here. What I envisage is this
void (*throw_handler)( std::exception const& ex, boost::exception& bx, boost::source_location const* loc ) = default_throw_handler;
void set_throw_handler( auto* p ) { throw_handler = p; } [...]
My point is that only the final end-user can call set_throw_handler (unless perhaps you make it a registration chain instead, and invoke all of the callbacks -- which after adding RAII makes it resemble the context objects I mentioned previously), which makes it harder to tack on additional information from a library context (or in passing rather than having to catch and rethrow). But that's also a bit different from what I was envisaging -- why is it that you've modified the callback signature to carry the source_location across? Wouldn't this be better: void (*throw_handler)( std::exception const& ex, boost::exception& bx ) = default_throw_handler; void set_throw_handler( auto* p ) { throw_handler = p; } void default_throw_handler( std::exception const& ex, boost::exception& bx ) { } template<class E> BOOST_NORETURN void throw_exception( E const & e ) { wrapexcept<E> wx( e ); throw_handler( e, wx ); throw wx; } template<class E> BOOST_NORETURN void throw_exception( E const & e, boost::source_location const & loc ) { wrapexcept<E> wx( e ); wx.set_location( loc ); throw_handler( e, wx ); throw wx; } (Or perhaps only passing the boost::exception to the handler; I'm not sure why it would need both.) This means the source_location is just like any other data you want to attach; it doesn't get special treatment.