
On Sun, Mar 6, 2011 at 1:54 PM, Sebastian Redl <sebastian.redl@getdesigned.at> wrote:
On 06.03.2011, at 16:05, Lorenzo Caminiti wrote:
Shall I ignore this case and require main() to always catch for the C++ emulations of D-style scope guards to work?
I don't think you have a choice. You *cannot* guarantee code execution upon an uncaught exception, at least not portably.
I see. Then I would simply declare an `error` local variable and add an extra instruction to set it before throwing: #include <boost/local/exit.hpp> #include <iostream> #include <stdexcept> void f() { bool error = false; // No error to start with. BOOST_LOCAL_EXIT( (void) ) { // Smae as D's `scope(exit)`. std::cout << "exit" << std::endl; } BOOST_LOCAL_EXIT_END BOOST_LOCAL_EXIT( (const bind& error) ) { // Same as D's `scope(success)`. if (!error) std::cout << "success" << std::endl; } BOOST_LOCAL_EXIT_END BOOST_LOCAL_EXIT( (const bind& error) ) { // Same as D's `scope(failure)`. if (error) std::cout << "failure" << std::endl; } BOOST_LOCAL_EXIT_END error = true; throw std::runtime_error("some error"); // Must set error. } int main() { // Program cannot terminate with uncaught exception (otherwise local exits // code is not guaranteed to be executed). try { f(); return 0; } catch(...) { return -1; } } And similarly for error numbers instead of exceptions: #include <boost/local/exit.hpp> #include <iostream> int f() { int error = 0; // No error to start with. BOOST_LOCAL_EXIT( (void) ) { // Same as D's `scope(exit)`. std::cout << "exit" << std::endl; } BOOST_LOCAL_EXIT_END BOOST_LOCAL_EXIT( (const bind& error) ) { // Sane as D's `scope(success)`. if (!error) std::cout << "success" << std::endl; } BOOST_LOCAL_EXIT_END BOOST_LOCAL_EXIT( (const bind& error) ) { // Same as D's `scope(failure)`. if (error) std::cout << "failure" << std::endl; } BOOST_LOCAL_EXIT_END return error = -1; // Must set error. } int main() { return f(); } IMO, this is a clean and simple way to provide D-style scope guards. -- Lorenzo