Boost logo

Boost :

Subject: Re: [boost] [local_function] any interest in a LocalFunction library?
From: Lorenzo Caminiti (lorcaminiti_at_[hidden])
Date: 2010-09-16 15:53:41


On Wed, Sep 15, 2010 at 10:56 AM, Lorenzo Caminiti
<lorcaminiti_at_[hidden]> wrote:
> 10) I will not merge Boost.Local with Boost.ScopeExit into a more
> generic Boost.Scope library. However, I will provide macros
> `BOOST_LOCAL_EXIT/BOOST_LOCAL_EXIT_END` which will work like
> Boost.ScopeExit plus they will allow to bind `this`. Boost.ScopeExit
> does not allow to bind `this` correct?

I have decided to allow both const and non-const binding also for the
LOCAL_EXIT macros (Boost.ScopeExit instead alway binds non-const).
This way the syntax of these macros is a bit more verbose than the
Boost.ScopeExit macros but you can enforce constant correctness of
your scope exit blocks. Also these macros can bind `this`
(Boost.ScopeExit cannot).

This example (somewhat long) is adapted from Boost.ScopeExit
documentation (it compiles and works):

// Example adapted from Boost.ScopeExit documentation.

#include <contract/detail/local/exit.hpp>
#include <boost/foreach.hpp>
#include <boost/typeof/std/vector.hpp> // Typeof emulation mode.
#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() // Typeof emulation mode.
#include <vector>
#include <ostream>
#include <iostream>

class world;

class person {
    friend class world;
public:
    typedef unsigned int id_t;
    typedef unsigned int evolution_t;

    person(): id_(0), evolution_(0) {}

    friend std::ostream& operator<<(std::ostream& o, person const& p)
        { return o << "person: " << p.id_ << ", " << p.evolution_; }

private:
    id_t id_;
    evolution_t evolution_;
};

BOOST_TYPEOF_REGISTER_TYPE(person)

class world {
public:
    typedef unsigned int id_t;

    world(): next_id_(1) {}

    void add_person(person const& a_person);

    friend std::ostream& operator<<(std::ostream& o, world const& w) {
        o << "world: " << w.next_id_ << ", {";
        BOOST_FOREACH(person const& p, w.persons_) {
            o << ' ' << p << ',';
        }
        return o << "}";
    }
private:
    id_t next_id_;
    std::vector<person> persons_;
};

BOOST_TYPEOF_REGISTER_TYPE(world)

void world::add_person(person const& a_person) {
    persons_.push_back(a_person);

    // This block must be no-throw.
    person& p = persons_.back();
    person::evolution_t checkpoint = p.evolution_;

    CONTRACT_DETAIL_LOCAL_EXIT(
            (const bind)((checkpoint)(&p)) (bind)((this)) ) {
        if (checkpoint == p.evolution_) this_->persons_.pop_back();
        std::cout << "1st local exit" << std::endl;
    } CONTRACT_DETAIL_LOCAL_EXIT_END

    // ...

    checkpoint = ++p.evolution_;

    // Assign new id to the person.
    world::id_t const prev_id = p.id_;
    p.id_ = next_id_++;
    CONTRACT_DETAIL_LOCAL_EXIT(
            (const bind)((checkpoint)(prev_id)) (bind)((&p)(&next_id_)) ) {
        if (checkpoint == p.evolution_) {
            next_id_ = p.id_;
            p.id_ = prev_id;
        }
        std::cout << "2nd local exit" << std::endl;
    } CONTRACT_DETAIL_LOCAL_EXIT_END

    // ...

    checkpoint = ++p.evolution_;
}

int main() {
    person adamo, eva;
    std::cout << adamo << std::endl;
    std::cout << eva << std::endl;

    world w;
    w.add_person(adamo);
    w.add_person(eva);
    std::cout << w << std::endl;
}

I will leave it up to the library reviewers to decided if Boost.Local
and Boost.ScopeExit should be merged into a single library (maybe
named Boost.Scope? but then BOOST_SCOPE_FUNCTION is a worst name than
BOSOT_LOCAL_FUNCTION...).

--
Lorenzo

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