For inclusion to boost::function

(repost, I accidentally posted this to boost::build list ... ugh). I have written code to solve this problem: I have class foo, like so: class foo { boost::function<void (foo *)> func_ptr; void call() { func_ptr(this); } }; I want func_ptr to be either a free-standing function (or class static), OR a class member function of a derived class, so: void bar(foo *f) { ... } OR: class baz : public foo { public: baz() { func_ptr = &baz::doit; } void doit() { } }; The obvious problem with the latter is that it needs to be downcast implicitly, and some kind of exception thrown if the wrong type is passed. I have created a boost::function proxy class to handle exactly this problem. It uses a lot of boost::function's own tricks with the pre-processor and such. I also had to use another suggestion I saw on this list to work around the fact boost::function does not accept member function pointer syntax (argh! That took a lot to figure out). My solution is this: http://www.neuromancy.net/fisheye/browse/mantra/trunk/Mantra-I/mantra/utils/... Which is included by a boost preprocessor iteration here: http://www.neuromancy.net/fisheye/browse/mantra/trunk/Mantra-I/mantra/utils/... As I mention, I use a lot of boost::function's own tricks. I think this would be a lot cleaner if done as part of boost::function, rather than me re-implementing the same macros and such. I have made sure my implementation works, and more importantly, has all the tests you would expect (ie. that the return value arguments except the class are the same, that the class is derived from the original function typedef's first argument, and so on). Here is my test case: http://www.neuromancy.net/fisheye/browse/mantra/trunk/Mantra-I/test/schedule... Any way, feedback is as always appreciated, but if someone could look at this for an addition to boost::function it would really be great PreZ

on Wed Sep 26 2007, "Preston A. Elder" <prez-AT-neuromancy.net> wrote:
(repost, I accidentally posted this to boost::build list ... ugh).
I have written code to solve this problem:
I have class foo, like so:
class foo { boost::function<void (foo *)> func_ptr;
void call() { func_ptr(this); } };
I want func_ptr to be either a free-standing function (or class static), OR a class member function of a derived class, so:
void bar(foo *f) { ... }
OR:
class baz : public foo { public: baz() { func_ptr = &baz::doit; }
void doit() { } };
The obvious problem with the latter is that it needs to be downcast implicitly, and some kind of exception thrown if the wrong type is passed.
I think this is what Boost.Bind is for. -- Dave Abrahams Boost Consulting http://www.boost-consulting.com

Preston A. Elder wrote:
[snip example]
The obvious problem with the latter is that it needs to be downcast implicitly, and some kind of exception thrown if the wrong type is passed.
This doesn't seem like the kind of thing you would want to do implicitly. Rather, the user should request this try-to-downcast-and-throw-if-it-fails behavior.
My solution is this: http://www.neuromancy.net/fisheye/browse/mantra/trunk/Mantra-I/mantra/utils/...
Which is included by a boost preprocessor iteration here: http://www.neuromancy.net/fisheye/browse/mantra/trunk/Mantra-I/mantra/utils/...
As I mention, I use a lot of boost::function's own tricks. I think this would be a lot cleaner if done as part of boost::function, rather than me re-implementing the same macros and such.
Interesting. It's unfortunate that you have to jump through so many syntactic hoops to make this kind of code work. I will use this opportunity to point out how trivial this kind of thing will be to write once we have variadic templates :)
I have made sure my implementation works, and more importantly, has all the tests you would expect (ie. that the return value arguments except the class are the same, that the class is derived from the original function typedef's first argument, and so on).
Here is my test case: http://www.neuromancy.net/fisheye/browse/mantra/trunk/Mantra-I/test/schedule...
Any way, feedback is as always appreciated, but if someone could look at this for an addition to boost::function it would really be great
I don't think it belongs in boost::function per se, because boost::function has a very narrow focus on bridging to arbitrary function objects. It doesn't do any kind of adaptation of arguments, because bind already doesn't that. It's more in line with mem_fn, which handles the adaptation of a member pointer to make it a proper function object. The name "mem_fn_proxy" is a little weak, in that it doesn't really state the important behavior: downcasting "this". For this functionality, I, personally, have called it "mem_fn_downcast" and given it the same interface and semantics as mem_fn, except with the addition of the automatic downcasting behavior. Then, it would be up to Peter to decide whether he wants to add this variant to the bind/mem_fn library. - Doug
participants (3)
-
David Abrahams
-
Douglas Gregor
-
Preston A. Elder