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