Boost logo

Boost :

Subject: Re: [boost] (Boost.)Overload vs Boost.Functional/OverloadedFunction (was Re: Status of proposed boost.overload?)
From: Marco Cecchetti (mrcekets_at_[hidden])
Date: 2012-03-28 09:55:55

On Tue, 27 Mar 2012 23:10:59 +0200, lcaminiti <lorcaminiti_at_[hidden]>

> Marco Cecchetti wrote
>> On Mon, 26 Mar 2012 14:39:10 +0200, lcaminiti &lt;lorcaminiti@&gt;
>> wrote:
>>> Marco Cecchetti wrote
>>>> On Sun, 25 Mar 2012 00:15:38 +0100, lcaminiti &lt;lorcaminiti@&gt;
>>>> wrote:
>>>>> How's this different from:
>>>> Hi Lorenzo,
>>>> (Boost.)Overload is a dynamic wrapper of multiple callable objects.
>>>> All started from a Joel de Guzman's post where he showed a proof
>>>> of concept of a thin-wrapper of several Boost.Functions.
>>>> See:
>>>> On that code base, I designed (Boost.)Overload that provides an
>>>> interface similar to Boost.Function.
>>>> A first difference is that with (Boost.)Overload is possible
>>>> to create an empty boost::overload object, and then set up
>>>> callable targets at a later time, obviously the library provides
>>>> methods for checking if a given callable target is empty.
>>>> That matches exactly what Boost.Function does.
>>>> Here's a basic example extracted from the tutorial:
>>> It seems that the two libraries do the same things a part for a
>>> slightly
>>> different API.
>> Well, indeed I find the 'slightly' adjective a bit inappropriate.
>> In fact for what I can see OverloadedFunction API is made of
>> constructors and call operators only, whilst Overload provides
>> also more than 15 methods, some metafunctions and Boost.ResultOf
>> support.
>> I understand that such a minimalism is due to the fact that you
>> designed such a library mainly for providing overloaded functions
>> in Boost.Local, but I am evaluating OverloadedFunction as a standalone
>> library. I hope to have not been rude.
>> For more details, you can give a look at the overload class reference:
>>> At a first look, your library API seems a super set of mine.
>>> Therefore, if your library passes the review maybe it can simply extend
>>> my OverloadedFunction adding default constructors, set(), etc (so we
>>> don't end up with two different libraries serving the same purpose).
>> I agree that the two library overlap, on the other hand I have good
>> reasons for retaining my implementation:
> Sure you can keep your implementation. The main point is if your library
> (with your implementation) can replace mine after your library gets
> accepted. I'd think so because my library API seems to be a subset of
> yours
> but can you think if that replacement will be possible or not? (The
> "replacement" is important so users that start using my library can later
> use yours without affecting backward compatibility.
> For example, have you
> tried to compile my library examples using your library and viceversa?
> That might be a good start in assessing if my library will be able to be
> replaced by yours. These things will come up during the review of your
> library so
> it's better to address them now :)

I agree, I'll do some test for checking compatibility.

>> 1) overload&lt;S1, S2, ..., SK&gt; inherits from boost::function<SI> for
>> 1<=I<=K
>> that means you can pass an overload object that support the call
>> signature S everywhere a boost::function<S> is expected.
>> Btw, why do you prefer to wrap each boost::function in an ad-hoc
>> base class ?
> For performance (based on a very quick analysis I've done back then...).

Ok, that looks sensible, but I think "backward compatibility" is a
nice feature.

>> 2) the Overload API implementation is heavily based on the fact that
>> boost::overload inherits recursively from base classes (similar to
>> Boost.Tuple) containing metainfo (types, static const data fields).
>> 3) I have already tested my implementation with a good amount of
>> compilers
>> (gcc 3.4.2+, Intel 9.1+, clang 2.9, ekopath 4, MSVC 7.1+, mingw
>> 3.4.2+)
>> and where I got failures I provided workarounds.
> Also OveloadedFunction seems to pass most trunk regression tests :)

I see, but with a minimalist API is easier! :)
Indeed, the biggest workaround is needed for MSVC 7.1, now it has been
removed from the compiler set used for regression tests, but on 2007
when I started implementing the library it had to be supported.

>> 4) I keep dependencies from other libraries as minimal as possible,
>> for what I can see OverloadedFunction has two more dependencies:
>> Boost.FunctionTypes and Boost.MPL.
>>> BTW, do you have something similar to my make_overloaded_function?
>> Yep, Overload provides a make_overload utility:
>> Indeed, I'm not so happy with that because it requires Boost.TypeOf,
>> for such a reason I prefer to keep it in a separate header.
> BTW, I wasn't able to handle polimorphic functions. For example, the
> following will not work :(
> struct poly {
> template<typename T>
> void operator()( T const& x ) { std::cout << "poly" << std::endl; }
> };
> void mono( int x, int y ) { std::cout << "mon" << std::endl;
> overload_function< void(int, int), /* some type which I couldn't figure
> out
> */ > f(mono, poly);
> f(1, 2); // call mono
> f(123); // call poly
> f("abc"); // call poly
> // or even harder
> auto g = make_overloaded_function(mono, poly);
> g(1, 2); // call mono
> g(123); // call poly
> g("abc"); // call poly
> Can your library handle polymorphic functions?

No Overload supports a *finite* overload set, what you'd like to
design is a TemplateFunction supporting an *infinite* overload set:

template_function< void(int, int), void (_1) > f( &mono, poly() );

where _1 is a placeholder for a template parameter.

As Steven Watanabe explained very clearly in the other post that
is not doable in general.

However Overload provides a method that accepts a polymorphic
function object as argument. The passed function object sets/replaces
all the existent object targets related to the call signatures
supported by both the given instantiation of the template class overload
and the passed function object itself.

poly polyfunc;
overload< void (int, int ), void (int ), void (std::string )> f(&mono);
f.set_for_each_shared_signature( boost::ref(polyfunc) );

f(1, 2); // call mono(1,2)
f(123); // call polyfunc(123)
f("abc"); // call polyfunc("abc")

Passing to a less complex issue, do you know a way for getting
the call signature of the call object resulting from a lambda or
phoenix bind expression ?
Can you pass a bind expression to make_overloaded_function ?

-- Marco

Using Opera's revolutionary e-mail client:

Boost list run by bdawes at, gregod at, cpdaniel at, john at