|
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