Boost logo

Boost :

From: Marco Costalba (mcostalba_at_[hidden])
Date: 2008-05-16 14:27:33


On Fri, May 16, 2008 at 5:04 PM, Mathias Gaunard
<mathias.gaunard_at_[hidden]> 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


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