
On Wed, Sep 15, 2010 at 10:56 AM, Lorenzo Caminiti <lorcaminiti@gmail.com> 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