Boost logo

Boost :

Subject: Re: [boost] [local_function] any interest in a LocalFunction library?
From: Lorenzo Caminiti (lorcaminiti_at_[hidden])
Date: 2010-09-12 14:47:07


On Tue, Aug 31, 2010 at 4:33 PM, Pierre Morcello
<pmorcell-cppfrance_at_[hidden]> wrote:
>> > Sorry, I think I just realized I told you something
>> wrong earlier on the list. One year ago, interest was raised
>> towards unnamed local fonction. I missed that you were
>> aiming for named function. we did not discuss named local
>> function.
>>
>> Do you have a link to that email thread? I would like to
>> take a closer
>> look at that discussion.
>>
>
> the beginning discussion was there :
> http://archives.free.net.ph/message/20090906.123719.b890ff7a.el.html
>
> and the point that interest you can be seen there :
> http://lists.boost.org/Archives/boost/2009/09/156126.php

Ok, I read the entire email thread. A couple of notes follow --
Boost.Breakable functionality would be provided by Boost.Block via
`return;`.

1) Prompted by Alexander Nasonov questions, both David Abrahams and
Vicente Botet expressed interest in "local functions with
ScopeExit-like interface".

> Re: [Boost.Breakable] Any interest in a Boost Breakable library?
> by Vicente Botet Escriba Sep 08, 2009; 10:39am :: Rate this Message: - Use ratings to moderate (?)?
> Reply | Print | View Threaded | Show Only this Message
>
> David Abrahams-3 wrote:
> on Mon Sep 07 2009, Alexander Nasonov <alnsn-AT-yandex.ru> wrote:
>
>> Mathias Gaunard wrote:
>>> What about using a lambda?
>>> [&]() -> void
>>> ...
>>> That kind of thing can also be made with macros instead of lambdas using
>>> a similar technique to that of Boost.ScopeExit.
>>
>> Is there still an interest in local fuctions with ScopeExit-like
>> interface?
>
> I'm interested.
>
> --
> Dave Abrahams

While this interest was expressed in the context of unnamed lambda,
Alexander question was not limited to unnamed local functions. I think
the expressed interest applies 100% (if it is still there) to
Boost.LocalFunction which is "(named) local functions with
ScopeExit-like interface". However, interest from Alexander, Vicente,
and possible Steven Watanabe (but I am not sure about David) is not a
surprise because these are the people that suggested me to look into
Boost.LocalFunction in the first place.

> Still, unnamed void function with N parameters, that are called immediately are useful in certain cases (not always of course).

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:

#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) return; // `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 );
            return; // 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_;
};

However, the only use case I can think of for `BOOST_BLOCK` is to
break to the block's end using `return;` and I have to say I was not
convinced of the real existence of such a use case from the email
thread http://archives.free.net.ph/message/20090906.123719.b890ff7a.el.html.
The situation is much different for `BOOST_BLOCK_CONST` for which the
use case is to add semantic information that a group of instructions
should locally be executed in const-correct context so to allow the
compiler to catch eventual programmers errors.

At the end, using Boost.LocalFunction should be easy enough to program
local functions taking parameters or not and to execute them
immediately or not depending on your specific needs.

--
Lorenzo

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