|
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