
On 2/6/2011 9:17 AM, Lorenzo Caminiti wrote: [...]
I am posting here the code generated by the macros which might help curious readers in spotting costly operations performed by Boost.Local (if there are any). This of course does not include the preprocessing time. (I hope it's not too much code... just try to get passed the typeof noise at the beginning...)
Is the use of Boost.Typeof optional? I.e., can I just provide the types of the arguments and bound variables myself?
int main() { double sum = 0.0; int factor = 10;
// BOOST_LOCAL_FUNCTION( (void) (add)( (double)(num) (const bind)((factor)) ) expands to: // Determining bound variable types (taken from Boost.ScopeExit). typedef void (*boost_se_tag_0_add36)(int factor ); typedef void (*boost_se_tag_1_add36)(int&sum );
Where did sum come from??? I don't see it in the BOOST_LOCAL_FUNCTION( ... ) line...I guess you're *really* showing the expansion of a similar macro invocation, but with sum also bound...?
typedef __typeof__(boost::type_of::ensure_obj(boost::scope_exit::aux::wrap( boost::scope_exit::aux::deref(factor, (boost_se_tag_0_add36)0)))) boost_se_wrapped_t_0_add36; typedef boost_se_wrapped_t_0_add36::type boost_se_capture_t_0_add36; typedef __typeof__(boost::type_of::ensure_obj(boost::scope_exit::aux::wrap( boost::scope_exit::aux::deref(&sum, (boost_se_tag_1_add36)0)))) boost_se_wrapped_t_1_add36; typedef boost_se_wrapped_t_1_add36::type boost_se_capture_t_1_add36;
I have a feeling there should be a typename here when boost_se_wrapped_t_1_add36 is a dependent type...
struct boost_se_params_t_add36 { typedef boost_se_capture_t_0_add36 boost_se_param_t_0_add36; typedef boost_se_capture_t_1_add36 boost_se_param_t_1_add36; boost::scope_exit::aux::member< boost_se_param_t_0_add36, boost_se_tag_0_add36> boost_se_param_0_add36; boost::scope_exit::aux::member< boost_se_param_t_1_add36, boost_se_tag_1_add36> boost_se_param_1_add36; } boost_local_auxXparams_add36 = { { boost::scope_exit::aux::deref(factor, (boost_se_tag_0_add36)0) } , { boost::scope_exit::aux::deref(&sum, (boost_se_tag_1_add36)0) } }; boost::scope_exit::aux::declared< boost::scope_exit::aux::resolve< sizeof(boost_local_auxXargs)>::cmp1<0>::cmp2> boost_local_auxXargs;
Shouldn't the name boost_local_auxXargs have some kind of line number or counter or function name pasted into it to prevent name collision of multiple BOOST_LOCAL_FUNCTION declarations in the same scope?
boost_local_auxXargs.value =&boost_local_auxXparams_add36; // Functor for the local function. typedef ::boost::local::function_ref< void ( double ) , 0> boost_local_auxXaddXref; struct boost_local_auxXfunctorXadd : ::boost::local::aux::function_base< void ( double ), 0> { explicit boost_local_auxXfunctorXadd(void* bind_params) : boost_local_auxXparams( (boost_se_params_t_add36*) bind_params) {}
static_cast ? Just being picky here... ;)
void operator()( double num ) { return boost_local_auxXbody( *this , boost_local_auxXparams-> boost_se_param_0_add36.value , boost_local_auxXparams-> boost_se_param_1_add36.value , num ); } private: boost_se_params_t_add36* boost_local_auxXparams; static void boost_local_auxXbody( boost_local_auxXfunctorXadd& add , ::boost::add_const< boost_se_params_t_add36:: boost_se_param_t_0_add36>::type factor , boost_se_params_t_add36:: boost_se_param_t_1_add36&sum , double num )
// Programmers' write the local function body. { sum += factor * num; std::clog<< "Summed: "<< sum<< std::endl; }
// BOOST_LOCAL_FUNCTION_END(add) expands to: }; boost_local_auxXfunctorXadd boost_local_auxXobjectXadd( boost_local_auxXargs.value); boost_local_auxXaddXref add( boost_local_auxXobjectXadd); // Finally the actual functor...
add(100.0);
return 0; }
For maintenance purposes, do you plan on providing a brief sketch of the above mechanism (e.g., the main players in the above macro expansion, and the inheritance from function_base and type-erasure to simulate the binding of local functions to template parameters)? I remember you doing an earlier study on the performance impact of using this type erasure (compared to moving the local function to namespace scope and avoid the overhead of the virtual dispatch)...is that included in the documentation? I don't see it from a quick glance... - Jeff