Boost logo

Boost :

From: Joel de Guzman (joel_at_[hidden])
Date: 2007-09-30 20:25:04


Joel de Guzman wrote:
> Dean Michael Berris wrote:
>
>> So the only alternative really (or at least the one I see that doesn't
>> run into the forwarding problem) is the linear inheritance approach
>> I've been mentioning. Now getting towards implementing that approach
>> is another discussion and effort in itself -- one I'm still mulling
>> around if it's even worth pursuing, given the cases I intend to cover
>> with the dispatcher. If at all possible, even an enhancement to
>> Boost.Function might be handy which will allow it to contain function
>> pointers to multiple signatures -- but I'm not that ambitious (yet) to
>> try and hack at Boost.Function to enable multiple signature support
>> and compile-time dispatching based on argument type lookup.
>
> I think I've mentioned that I have such a "overloads" library
> extension in my HD somewhere. At one point, I asked Doug on
> the possibility of adding it to boost.function and he expressed
> his interest. Of course that means documentation and stuff.
> I'll try to see if I can squeeze some time to get this into
> completion. At any rate, I can post the code sans docs.

[CC'ing Doug]

Ok, here's the proof of concept:

     http://spirit.sourceforge.net/dl_more/overload/

Here's the original text I sent Doug:

Boost.function is a very useful library for wrapping function
objects. Yet, one limitation it has, compared to generic function
objects, is that it is monomorphic. It has a specific fixed
signature and is unusable polymorphically. One particular
case it can't be used for, for example, is as a visitor for boost
variant. But that view is minimalistic. I don't think I need to
expound on the virtues of overloaded functions. But, let me show
some examples anyway...

Say we have a boost.function named "concat". It can be called
much like any function. For example:

     concat(str, str2)

Boost.function has a fixed signature.
For example, "concat" can be declared as:

     function<std::string(std::string, std:string)>

Now here lies the problem... But, I'd like to also allow:

     concat(str, 'x')
     concat(str, "Hi")
     concat("Hi", str)
     concat('x', str)

or possibly even:

     concat("Hi", ", World")
     concat('x', 'y')

Unfortunately, we can't use boost.function like that because it is
monomorphic. (Sure, "Hi" can be implicitly converted to a std::string,
but a temporary will have to be created. We are out of luck for
'x': there is no implicit conversion).

Hence, I'd like to propose an extension (or a separate library)
for allowing overloads for boost.function. The example above can
be declared as:

     boost::overload<
         std::string(std::string, std:string)
       , std::string(std::string, char)
       , std::string(std::string, char const*)
       , std::string(char, std::string)
       , std::string(char const*, std::string)
>
     concat;

Since "concat" is polymorphic, its declaration can be extended
to also support wide strings. Sure, you can have different return
types! Also, we are not limited to 2 argument overloads. We can
also allow:

     concat(str, cstr, len)

[...end concat example...]

Now, for Spirit, what I wanted to do, for a long time now, is
reduce the Spirit "rule" to a boost.function. Yet, as of Spirit
1.8, I found that it is not possible to use boost.function as-is
because its "rule" can be parameterized to take in a couple of
scanner types (e.g. one with space-skipping, one without):

     r.parse(plain-scanner);
     r.parse(skip-scanner);

With the proposed overload extension, I can now do that.

Here's Doug's reply:

Very cool. This is one of those "... you don't need it often, but when
you need it you *really* need it" features. If you're interested in
finished it up, I'd be happy to put it straight into the Function
library.

Regards,

-- 
Joel de Guzman
http://www.boost-consulting.com
http://spirit.sf.net

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