Boost logo

Boost :

Subject: Re: [boost] [local_function] any interest in a LocalFunction library?
From: Lorenzo Caminiti (lorcaminiti_at_[hidden])
Date: 2010-09-13 13:57:36


On Sun, Sep 12, 2010 at 2:47 PM, Lorenzo Caminiti <lorcaminiti_at_[hidden]> 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

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