
On Fri, Aug 27, 2010 at 1:39 PM, Pierre Morcello <pmorcell-cppfrance@yahoo.fr> 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 ?
::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(); } }
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 private: int x_; }; int main() { c cc; cc.f(1); return 0; } -- Lorenzo