
On Sun, Sep 12, 2010 at 2:47 PM, Lorenzo Caminiti <lorcaminiti@gmail.com> wrote:
2) This functionality plus the one of Boost.Breakable-like breakability would be provided by Boost.Block in terms of both const and non-const blocks.
I implemented Boost.Block using Boost.LocalFunction. Note that from within a Boost.Block, return jumps to the end of the block (and it does not exit the enclosing function) therefore also proving the Boost.Breakable functionality discussed in http://archives.free.net.ph/message/20090906.123719.b890ff7a.el.html. However, I am not sure if this "block breakability" via return is a feature or a limitation because users could expect `return;` to quit exit the enclosing function as usual and not just the local void-function used to implement the Boost.Block (only `return;` is allowed because the local function is void so if the enclosing function returns non-void this confusion does not exist). For example:
Actually, I just fixed this. If you try to use a `return` from within a Boost.Block code block you get this compiler error: error: return-statement with no value, in function returning ‘contract::detail::block::aux::ERROR_cannot_use_return_from_within_block’ The return type name should make it clear that you should not use return from the block so to avoid confusion with programmers using return from within a block attempting to exit the enclosing function. However, Boost.Block provides the macro `BOOST_BLOCK_BREAK` which can be used anywhere from within a code block to exit the block -- this is Boost.Breakable functionality (note that I do not feel strongly about this block-breakability feature, it was trivial so I added it to Boost.Block but I can also trivially remove the `BOOST_BLOCK_BREAK` if Booster don't want this feature). The following example now uses `BOOST_BLOCK_BREAK` instead of the `return;` (as the `return;` would have now generated the compiler error above):
#include <contract/detail/block.hpp> #include <contract/detail/local_function.hpp> #include <cassert>
struct c { c(): x_(0.0) {}
void f(int const& x) { // Non-const member function so `this` is not const.
// Non-const block binds params all by `&` but with they original // `const` qualifier (i.e., `x` is `const&` but `this` is not const). CONTRACT_DETAIL_BLOCK( (this)(x) ) { if (x <= 0) CONTRACT_DETAIL_BLOCK_BREAK; // `return` jumps to block's end. this_->x_ = x; // OK, `f` (so `this`) is non-const member function. } CONTRACT_DETAIL_BLOCK_END
// Const-block using the macros (preferred). // Params automatically bound as `const&` -- users do not specify `&`. CONTRACT_DETAIL_BLOCK_CONST( (this)(x) ) { // NOTE: Correctly, compiler error if `=` used instead of `==`. assert(this_->x_ == x); assert(x > 0 ); CONTRACT_DETAIL_BLOCK_BREAK; // Jump to block's end. assert(false); } CONTRACT_DETAIL_BLOCK_END
{ // Or, equivalently using the local function directly. CONTRACT_DETAIL_LOCAL_FUNCTION( (void) (block)( (const bound)((this)(&x)) ) ) { assert(this_->x_ == x); assert(x > 0 ); return; assert(false); } CONTRACT_DETAIL_LOCAL_FUNCTION_END(block) block(); // Execute code block immediately. } }
private: int x_; };
-- Lorenzo