Boost logo

Boost :

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


On Fri, Aug 27, 2010 at 1:39 PM, Pierre Morcello
<pmorcell-cppfrance_at_[hidden]> wrote:
> Lorenzo Caminiti wrote :
>> I got a first version of Boost.LocalFunction implemented.
> 2/ Is it possible to have look at your code?

You can find the source code at:
http://dbcpp.svn.sourceforge.net/viewvc/dbcpp/trunk/src/contract/detail/

There are some tests and examples in:
http://dbcpp.svn.sourceforge.net/viewvc/dbcpp/trunk/test/local_function_/
http://dbcpp.svn.sourceforge.net/viewvc/dbcpp/trunk/example/local_function_/

This is still a work in progress!! Tests/examples that bound `this`
only work on GCC for now (because of MSVC error C2355 -- Boosters
indicated a workaround but I still have to implement it).

If the libraries in "contract/detail" were to be proposed to Boost:
1) Symbols will be renamed `CONTRACT_DETAIL` --> `BOOST_DETAIL`,
`contract::detail` --> `boost::detail`, etc.
2) "contract/detail/local_function*" and
"contract/detail/const_block*" will be proposed as Boost.LocalFunction
and Boost.ConstBlock outside "boost/detail". The other supporting
libraries in "contract/detail" will be proposed to be added to
"boost/detail".
3) Another idea would be to add local functions and const-blocks to
the existing Boost.ScopeExit library. Then Boost.ScopeExit could be
renamed to Boost.Scope and the macros could be named
`BOOST_SCOPE_EXIT`, `BOOST_SCOPE_FUNCTION`, `BOOST_SCOPE_CONST`, etc.
(The current "boost/scope_exit.hpp" could still be kept for backward
compatibility.)

I don't really have a strong opinion between 2) and 3) but "local
function" might be a better known to users than "scope function" so 2)
might be a better option -- I am interested in what Boosters think.

> 3/ What is the generated code output by your example ?

This example for both const-block and local function:

#include <contract/detail/local_function.hpp>
#include <contract/detail/const_block.hpp>
#include <cassert>

struct c {
    c(): x_(0.0) {}

    void f(int x) {
        x_ = x;

        // Const-block using the macros (preferred).
        // Params automatically bound as `const&` -- user doesn't specify `&`.
        CONTRACT_DETAIL_CONST_BLOCK( (this)(x) ) {
            // NOTE: Correctly compiler error if `=` used instead of `==`.
            assert(this_->x_ == x);
            assert(x > 0 );
        } CONTRACT_DETAIL_CONST_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 );
            } CONTRACT_DETAIL_LOCAL_FUNCTION_END(block)
            block(); // Execute block code immediately.
        }
    }

private:
    int x_;
};

int main() {
    c cc;
    cc.f(1);
    return 0;
}

Expands to:

...

struct c {
    c(): x_(0.0) {}
    void f(int x) {
        x_ = x;
        { typedef void (*boost_se_tag_0_14)(int this_ ); typedef void
(*boost_se_tag_1_14)(int &x ); typedef
__typeof__(boost::type_of::ensure_obj(boost::scope_exit::aux::wrap(
boost::scope_exit::aux::deref(this, (boost_se_tag_0_14)0))))
boost_se_wrapped_t_0_14; typedef boost_se_wrapped_t_0_14::type
boost_se_capture_t_0_14; typedef
__typeof__(boost::type_of::ensure_obj(boost::scope_exit::aux::wrap(
boost::scope_exit::aux::deref(&x, (boost_se_tag_1_14)0))))
boost_se_wrapped_t_1_14; typedef boost_se_wrapped_t_1_14::type
boost_se_capture_t_1_14; struct boost_se_params_t_14 { typedef
boost_se_capture_t_0_14 boost_se_param_t_0_14; typedef
boost_se_capture_t_1_14 boost_se_param_t_1_14;
boost::scope_exit::aux::member< boost_se_param_t_0_14,
boost_se_tag_0_14 > boost_se_param_0_14;
boost::scope_exit::aux::member< boost_se_param_t_1_14,
boost_se_tag_1_14 > boost_se_param_1_14; }
contractXlocal_function_params_14X = { {
boost::scope_exit::aux::deref(this, (boost_se_tag_0_14)0) } , {
boost::scope_exit::aux::deref(&x, (boost_se_tag_1_14)0) } };
boost::scope_exit::aux::declared< boost::scope_exit::aux::resolve<
sizeof(contractXlocal_function_argsX) >::cmp1<0>::cmp2 >
contractXlocal_function_argsX; contractXlocal_function_argsX.value =
&contractXlocal_function_params_14X; class
contractXlocal_function_functorXcontract_detail_const_block_function_name_14_X
{ struct contractXlocal_function_castableX; public:
contractXlocal_function_functorXcontract_detail_const_block_function_name_14_X(void*
bound_params) : contractXlocal_function_paramsX(
(boost_se_params_t_14*) bound_params) {} void operator()( ) { return
contractXlocal_function_castableX:: contractXlocal_function_bodyX (
contractXlocal_function_paramsX-> boost_se_param_0_14.value ,
contractXlocal_function_paramsX-> boost_se_param_1_14.value ); }
private: boost_se_params_t_14* contractXlocal_function_paramsX; struct
contractXlocal_function_castableX { static void
contractXlocal_function_bodyX( ::contract::detail::add_pointed_const<
boost_se_params_t_14:: boost_se_param_t_0_14 >::type this_ ,
::boost::add_const< boost_se_params_t_14:: boost_se_param_t_1_14
>::type &x ) {
            ((this_->x_ == x) ? (void)0 : __assert_func
("example/local_function_/const_block.cpp", 16, __PRETTY_FUNCTION__,
"this_->x_ == x"));
            ((x > 0) ? (void)0 : __assert_func
("example/local_function_/const_block.cpp", 17, __PRETTY_FUNCTION__,
"x > 0"));
        } }; } contract_detail_const_block_function_name_18_(
contractXlocal_function_argsX.value);
contract_detail_const_block_function_name_18_(); }
        {
            typedef void (*boost_se_tag_0_23)(int this_ ); typedef
void (*boost_se_tag_1_23)(int &x ); typedef
__typeof__(boost::type_of::ensure_obj(boost::scope_exit::aux::wrap(
boost::scope_exit::aux::deref(this, (boost_se_tag_0_23)0))))
boost_se_wrapped_t_0_23; typedef boost_se_wrapped_t_0_23::type
boost_se_capture_t_0_23; typedef
__typeof__(boost::type_of::ensure_obj(boost::scope_exit::aux::wrap(
boost::scope_exit::aux::deref(&x, (boost_se_tag_1_23)0))))
boost_se_wrapped_t_1_23; typedef boost_se_wrapped_t_1_23::type
boost_se_capture_t_1_23; struct boost_se_params_t_23 { typedef
boost_se_capture_t_0_23 boost_se_param_t_0_23; typedef
boost_se_capture_t_1_23 boost_se_param_t_1_23;
boost::scope_exit::aux::member< boost_se_param_t_0_23,
boost_se_tag_0_23 > boost_se_param_0_23;
boost::scope_exit::aux::member< boost_se_param_t_1_23,
boost_se_tag_1_23 > boost_se_param_1_23; }
contractXlocal_function_params_23X = { {
boost::scope_exit::aux::deref(this, (boost_se_tag_0_23)0) } , {
boost::scope_exit::aux::deref(&x, (boost_se_tag_1_23)0) } };
boost::scope_exit::aux::declared< boost::scope_exit::aux::resolve<
sizeof(contractXlocal_function_argsX) >::cmp1<0>::cmp2 >
contractXlocal_function_argsX; contractXlocal_function_argsX.value =
&contractXlocal_function_params_23X; class
contractXlocal_function_functorXblockX { struct
contractXlocal_function_castableX; public:
contractXlocal_function_functorXblockX(void* bound_params) :
contractXlocal_function_paramsX( (boost_se_params_t_23*) bound_params)
{} void operator()( ) { return contractXlocal_function_castableX::
contractXlocal_function_bodyX ( contractXlocal_function_paramsX->
boost_se_param_0_23.value , contractXlocal_function_paramsX->
boost_se_param_1_23.value ); } private: boost_se_params_t_23*
contractXlocal_function_paramsX; struct
contractXlocal_function_castableX { static void
contractXlocal_function_bodyX( ::contract::detail::add_pointed_const<
boost_se_params_t_23:: boost_se_param_t_0_23 >::type this_ ,
::boost::add_const< boost_se_params_t_23:: boost_se_param_t_1_23
>::type &x ) {
                ((this_->x_ == x) ? (void)0 : __assert_func
("example/local_function_/const_block.cpp", 24, __PRETTY_FUNCTION__,
"this_->x_ == x"));
                ((x > 0) ? (void)0 : __assert_func
("example/local_function_/const_block.cpp", 25, __PRETTY_FUNCTION__,
"x > 0"));
            } }; }; contractXlocal_function_functorXblockX block(
contractXlocal_function_argsX.value);
            block();
        }
    }
private:
    int x_;
};

int main() {
    c cc;
    cc.f(1);
    return 0;
}

-- 
Lorenzo

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