
Hi, I ran into a problem when trying to use BOOST_TRY/BOOST_CATCH to add no-exception support to property tree. Here's an example of the original code; try { write_ini(stream, pt, flags); } catch (ini_parser_error &e) { BOOST_PROPERTY_TREE_THROW(ini_parser_error( e.message(), filename, e.line())); } I converted this code to use the macros from core/no_exception_support.hpp *BOOST_TRY *{ write_ini(stream, pt, flags); } *BOOST_CATCH *(ini_parser_error &e) { BOOST_PROPERTY_TREE_THROW(ini_parser_error( e.message(), filename, e.line())); } *BOOST_CATCH_END* The issue is that now the exception, ini_parser_error& e, is not defined when I compile with exceptions off. I solved this by adding a local instance of ini_parser_error above the try block *ini_parser_error e("", "", 0);* BOOST_TRY { write_ini(stream, pt, flags); } BOOST_CATCH (ini_parser_error &e) { BOOST_PROPERTY_TREE_THROW(ini_parser_error( e.message(), filename, e.line())); } BOOST_CATCH_END This is a little gross, but it's not too bad and I was expecting the variable to be optimized away. But it isn't -- instantiating that exception on the stack is very clearly generating instructions on VS2015 and GCC 5.3. While this is not a huge deal, I don't like it so one way I can think to fix this is to conditionally compile out the catch block, but that defeats the purpose of the macros in the first place. BOOST_TRY { write_ini(stream, pt, flags); } BOOST_CATCH (ini_parser_error &e) { *#ifdef BOOST_NO_EXCEPTIONS* BOOST_PROPERTY_TREE_THROW(ini_parser_error( e.message(), filename, e.line())); *#endif* } BOOST_CATCH_END Then I thought maybe I can declval a fake 'e' in the else block by redefining the macros as follows; #ifndef BOOST_NO_EXCEPTIONS #define BOOST_TRY { try { #define BOOST_CATCH(type, var) } catch(type var) { #define BOOST_CATCH_END } } #else #define BOOST_TRY { if(true) { #define BOOST_CATCH(type, var) } else if(false) { type var = boost::declval<type>(); #define BOOST_CATCH_END } } #endif This is working, but is possibly undefined behaviour. Does anyone have thoughts on that? It also requires splitting up the type from the variable name. The next step to this would be to add a third parameter for some constructor args so we can just create an exception object directly. Something like: #define BOOST_CATCH(exception_type, var, args) } else if(false) { boost::decay<exception_type>::type var args; So now the original code would look like this: BOOST_TRY { write_ini(stream, pt, flags); } BOOST_CATCH (ini_parser_error&, e, ("", "", 0)) { BOOST_PROPERTY_TREE_THROW(ini_parser_error( e.message(), filename, e.line())); } BOOST_CATCH_END This is starting to look a little nasty to me so I'm wondering if anyone has any thoughts on this? Should I stop worrying about it and just use the #ifdef? The reality is that I work in an environment without exceptions and we hit these things from time to time so I'd like to fix up as many as possible. Thanks, -- chris