Boost logo

Boost :

From: Marco Costalba (mcostalba_at_[hidden])
Date: 2008-05-02 06:14:51


On Sun, Apr 27, 2008 at 4:22 PM, Steven Watanabe <watanabesj_at_[hidden]> wrote:
> >
> > /* Check if a function/functor Fun has a given signature Sig */
> >
> > template<typename Fun, typename Sig>
> > struct is_compatible
> > {
> > /* Check for a function */
> > template<class U> static
> > yes_type check(typename enable_if<is_same<U, Sig> >::type*);
> >
> > /* Check for a functor */
> > template<class U, Sig U::*> struct helper;
> >
> > template<class U> static
> > yes_type check(helper<U, &U::operator()>*);
> >
>
> This is not correct. It does not handle
>
> struct f {
> void operator()() *const* {}
> };
>
> Further, it cannot handle implicit conversions of the argument types
> and return types.
>

I have thought again on this issue and it come up to the conclusion
that this is really a feature :-)

In the context of multisignature boost.function the implicit
conversion of the argument could lead to misbehaviour.

As example define the following signatures:

    typedef boost::mpl::vector
    <
        int(double)
      , int(int)
> Signatures;

And define the multi-signature function on them

boost::multi_signature_function::function<Signatures> f;

Now you have two functions

int foo1(double);
int foo2(int);

Without implicit conversion of type arguments the following works as expected:

f = &foo1;
f = &foo2;

But if implicit conversion is in then, because int(double) is declared
BEFORE int(int) then the first will shadow the second in the overload
hierarchy and what we end up is that

f = &foo2;

overwrites the previous assignment so that the internal
boost::function corresponding to int(double) is assigned to &foo2,
while the other boost::function corresponding to int(int) is still
empty.

So the bottom line is that implicit conversion of the argument types
is not good in our context.

What the user should do is to wrap the function in a boost function
BEFORE to assign to multi-signature.

As example

int foo(int);

boost::multi_signature_function::function<int(double)> f;

boost::function<int(double)> wrapper;

wrapper = &foo; // now it works because there is no ambiguity for a
standard boost::function...

f = wrapper; // ... and it's assigned to the multi-signature f also if
foo has different signature.

Thanks
Marco

P.S: So now the only remaining issue (the other was promoted to a
feature!) is the handling of pointers to const member functions. BTW
note that the wrapping trick would work also to handle this case, but
in this case a 'native' solution would be preferable.


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