
Hello, Following up on several discussion over the last few weeks, I've placed an implementation of a polymorphic call wrapper (and associated utilities) similar to Boost.Function in the file polymorphic_function.zip in the Function Objects directory on vault at http://tinyurl.com/56zvo4. Here's a brief demonstration to give an idea of what's included: // Work with arbitrary callable objects without loss of polymorphism. template<class Signature> void do_division(polymorphic_function<Signature> f) { // Do floating point division. float one = 1, two = 2; assert(f(one, two) == 0.5); if(is_polymorphic_function<Signature>::value) { // Now, drop the remainder using integer division. int one = 1, two = 2; assert(f(one, two) == 0); // And now, use high precision floating point division to // compute the inverse product of a series of integers. int series[3] = { 1, 2, 3 }; double x = std::accumulate(&series[0], &series[3], 1.0, functional_cast<double(double,double)>(f)); assert(0.16666666 < x && x < 0.166666667); } } // A second class builtin function. float builtin_divide(float x, float y) { return x / y; } // A TR1 result_of compatible function object. struct divide { template<class Signature> struct result : argument_of<Signature, 0> { }; template<class T> T operator()(T x, T y) const { return x / y; } }; int main() { // Promote builtin functions to first class. do_division< float(float,float) >( builtin_divide ); // Perform type-erasure. do_division< float(float,float) >( std::divides<float>() ); // Use polymorphic function objects polymorphically. do_division< divide(_1,_1) >( divide() ); } The file polymorphic_function.hpp provides the following components: * signature/call_signature/erase are metafunctions used to describe polymorphic functions. They allow you to do things like erase the callable object type of a boost::result_of compatible signature so it can be used with boost::function. typedef signature<my_function(int)>::type signature_type; typedef result_of<signature_type>::type result_type; typedef function<erase<signature_type>::type> function_object_type; * is_polymorphic_function is a metafunction used to designate function prototypes that may have variable return types according to boost::result_of. These are a subset of the prototypes detected by boost::is_function. More pertinently, is_polymorphic_function distinguishes the boost::function protocol for specifying function signatures - a.k.a. call signatures - from the boost::result_of protocol - a.k.a. polymorphic signatures. * is_incomplete_function is a metafunction used to designate polymorphic functions with variable argument types. These are a subset of the prototypes detected by is_polymorphic_function. They are described using Boost.MPL placeholders as arguments in the signature. * argument_of is a metafunction used to deduce the types of arguments to functions. It's a more general, nary alternative to the C++98 argument_type member. For example, argument_of can be used to detect call-by-reference functions: template<class F> void g(F f) { int x = 0; int& y = f(x); if(is_reference<typename result_of<F(int)>::type>::value && is_reference<typename argument_of<F(int), 0>::type>::value) assert(&x == &y); } int& my_function(int& t) { return t; } int main() { g(my_function); } * polymorphic_function is a call wrapper, which can be used in place of boost::function to allow both builtin functions and function objects to be used interchangeably without the degradation of polymorphism incurred by wrapping polymorphic function objects in boost::function. Essentially, this is achieved by giving the user the option of either erasing the function object's type as one would with boost::function or retaining the function object's type as one would with boost::result_of. * functional_cast is used to change the signature of a call wrapper. It can be used with both std/boost::function and polymorphic_function. For example, by specifying a new signature one may change the arity or argument types of a call wrapper, so long as the underlying callable object can be described by the new signature. Also included is a test set. I tested on gcc 3.4, 4.3 and msvc 9. The code includes some documentation in the form of inline comments. As far as future work and known defects, this is the first time I have seriously played with C++0x forwarding conventions using std::forward and rvalue references. I'm not confident that I got it perfectly right, so any corrections/guidance would be greatly appreciated. In C++98, I use an argument forwarding technique similar to Boost.Bind and Boost.Lambda - arguments are taken as non-const references and forwarded as rvalue conversions of the types requested in the signature. Secondly, type deduction using argument_of could have better support for function objects in C++98 and currently only supports member template operator() in C++0x. Finally, I'm sure more boost::function-like features could be added to polymorphic_function including members for queryng capacity, comparison operators, an allocator template parameter, etc. Thanks for your time and consideration! Cordially, Daniel Walker