
On Fri, May 16, 2008 at 5:04 PM, Mathias Gaunard <mathias.gaunard@ens-lyon.org> wrote:
Marco Costalba wrote:
Hi all,
this is the first official version of multi-signature boost::function extension (MSF) pushed to Boost Vault under the name msf-1.0.zip
Personally, I always thought getting a function objet per signature was a bad idea. Just take a single one with multiple overloads. Basically what you do with set_polymorphic_object, except you don't store it N times but only once.
Well, I'm changing again the API (yes I know it's painful, but this time is the last one, I promise). I would like to use operator=() also for polymorphic function objects and deal the single copy issue as presented by Giovanni with a class policy. I explain better with the example stripped from the new test.cpp now just in my private trunk, btw it works! struct poly_t { int call_cnt; poly_t() : call_cnt(0) {} template<class T> T operator()(T t) { call_cnt++; return t; } }; .......strip..... /* In case the assigned object is a polymorphic function object * then all the internal boost::functions are bounded in one go */ poly_t poly_obj; msf::function<boost::mpl::vector<char(char), string(string)> > fp(poly_obj); assert( fp('x') == 'x' ); assert( fp("hello") == "hello" ); assert( fp("hello") == "hello" ); /* By default boost::function makes a copy of the functor, so * we end up with a different copy of poly_obj for each signature * and the variable poly_obj::call_cnt is updated independently * by the two calls. Below we retrieve the object wrapped by * each of the two underlying boost::function and verify that * poly_t::call_cnt is duplicated. */ assert( fp.get<char(char)>().target<poly_t>()->call_cnt == 1 ); assert( fp.get<string(string)>().target<poly_t>()->call_cnt == 2 ); /* In some cases it is expensive (or semantically incorrect) to * clone a polymorphic function object. In such cases, it is possible * to request to keep only a reference to the actual function object. * This is done using the ref() function to wrap a reference to a * polymorphic function object */ poly_t external_poly_obj; fp = boost::ref(external_poly_obj); external_poly_obj('x'); // note that we call this not through fp external_poly_obj("hello"); assert( fp.get<char(char)>().target<poly_t>()->call_cnt == 2 ); assert( fp.get<string(string)>().target<poly_t>()->call_cnt == 2 ); /* A special case is when we need to have only a single copy of the * polymorphic object for all the signatures. In this case we have to * set to poly_single_copy the Tag template parameter of msf::function * that normally defaults to poly_multi_copy */ poly_t* poly_obj_ptr = new poly_t(); msf::function< boost::mpl::vector<char(char), string(string)>, msf::poly_single_copy > fp_si(*poly_obj_ptr); // work both as c'tor argument... fp_si = *poly_obj_ptr; //... and as assignment delete poly_obj_ptr; // delete now, a copy has already been made assert( fp_si('x') == 'x' ); assert( fp_si("hello") == "hello" ); assert( fp_si("hello") == "hello" ); /* Only one poly_t::call_cnt shared across the signature's slots */ assert( fp_si.get<char(char)>().target<poly_t>()->call_cnt == 3 ); assert( fp_si.get<string(string)>().target<poly_t>()->call_cnt == 3 );
You may also want to provide a (separate) generic tool to generate a single function object from multiple ones.
Please could you better explain this point with an example ? thanks ? Thanks Marco