Boost logo

Boost :

Subject: Re: [boost] D-style scope guards?
From: Lorenzo Caminiti (lorcaminiti_at_[hidden])
Date: 2011-03-07 17:01:07


On Sun, Mar 6, 2011 at 1:54 PM, Sebastian Redl
<sebastian.redl_at_[hidden]> 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

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk