Boost logo

Boost :

From: Daniel Walker (daniel.j.walker_at_[hidden])
Date: 2008-06-02 17:35:53


On Sun, Jun 1, 2008 at 4:10 AM, Marco Costalba <mcostalba_at_[hidden]> wrote:
> On Sat, May 31, 2008 at 8:23 AM, Marco Costalba <mcostalba_at_[hidden]> wrote:
>>
>>> Sorry for the delay. I just put it on vault.
>>
>> I'm just back after a week off-line due to my job. This is a great
>> news, I'm going to download right now.
>>
>> More to come...
>>
>
> Hi Daniel,
>
> I have downloaded and tested Function
> Objects/polymorphic_function.zip from boost vault.
>
> Very nice stuff! really! a lot of new tricks to learn ;-)

Thanks! I learned most of these techniques from other boosters and
boost libraries. So, we're all just spreading the love!

>
> I have immediately replaced boost::function with
> boost::functional::polymorphic_function in msf-1.2 (also under vault,
> but in base directory) and gave it a spin.
>
> Unfortunately I was not able to make it work.
>
> Some boost::function API, necessary for msf-1.2, are not supported:
> operator==(), empty(), clear(), contains()

Yes, I didn't do any of those. I should add them. I'll try to do that
this week, but in the mean time, if you wanted to test the main
wrapper/dispatch functionality, you could just comment out API that
forwards to those missing functions.

>
> I said, ok not a biggie, I can just use polymorphic_function::target()
> and build something similar myself.
>
> But what stopped me is that target() does not seem to work.
>
> int foo1(char) { return -1; }
>
> boost::functional::polymorphic_function<int(char)> poly_fun(foo1);
>
> poly_fun.target(); // compile error here !
>
> Under gcc 4.2.3 I have
>
> test.cpp: In function 'int main(int, char**)':
> test.cpp:88: error: no matching function for call to
> 'boost::functional::polymorphic_function<int ()(char),
> false>::target()'
>
> I have checked the code and especially the SFINAE conditions in
> RANK_N_ACCESSOR, but I failed to understand why it doesn't work.

The problem here is that you're not passing target() the type of the
wrapped callable object. The target() API is the same as
boost::function, though I'm basing this off the documentation in
20.5.15.2.5 in N2606. Remember, boost::function always erases the
target type, so to get at it again, you have to give target() the type
of the wrapped object, because it doesn't know its own internal object
type (it knows the type_info, but that's it). polymorphic_function
behaves similarly. When polymorphic_function is instantiated like
boost::function with a call signature (thus erasing the target type),
target() attempts a run time conversion and will return a null pointer
on error. When polymorphic_function is instantiated with a polymorphic
signature, target() attempts a compile time conversion, which will
result in a compilation error if the requested target type and actual
target type are not convertible.

In your example, the target type is int(*)(char) - a pointer to
foo1(). Now, target() returns a pointer to the internal target object,
so to get at it you want something like...

int(*target_function)(char) = *poly_fun.target<int(*)(char)>();

Of course, in general, you would want to check the returned pointer
before dereferencing it in case of a run time error.

Daniel Walker


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