
Hi, <...those that followed the latest function related discussions can skip the first paragraph...> For about a year and half now (or even more but that's about how long I've been involved in the matter) there have been repeated discussions/requests/complaints about various aspects of Boost.Function. Most of those fall into one or more of these categories: - overall code speed overhead - overall code bloat overhead - lack of configurability - dependencies on RTTI and exception handling with the most frequently brought up specific issue being the various implications (in all of the above mentioned areas) of the hardcoded throw-on-empty behaviour... Unfortunately Boost.Function code remained virtually unchanged (except for the added RTTI emulation for platforms w/o RTTI support) with all of the issues still remaining... The new implementation proposal @: https://svn.boost.org/svn/boost/sandbox/function/boost/function http://www.boostpro.com/vault/index.php?&direction=0&order=&directory=Function Objects solves or at least provides drastic improvements for all of the mentioned issues. It is intended as a drop in replacement for the current implementation and as such I have so far tested it in the following ways: - compiling some real world code: VC10, GCC 4.2.1, LLVM-GCC 4.2.1, GCC 4.5.1, GCC 4.6, Clang 2.0, Clang 2.8 - compiling and running a real world project: VC10, Clang 2.8 - building Boost trunk: VC10, GCC 4.2.1, GCC 4.5.1, Clang 2.0 - running Boost regression tests for Function, Signals, Signals2, Thread, Program Options and Graph libraries: VC10, GCC 4.2.1, Clang 2.0. (All of the tests passed except for two bogus assertion failure boxes that pop up with VC10 and the Program Options tests during the automated regression test procedure that OTOH do not popup when I run the same tests manually through the VC10 IDE, i.e. the tests finish successfully...I tried to make sure all the relevant compiler switches were the same in both cases so I am out of ideas what else can make the difference.....) Next, let me give you a comparison of for-size-optimized code generated by VC10 with both the current and the proposed implementation for a short code snippet demonstrating invocation, construction and assignment: struct X { int foo( int const x ) const { return x + y; }; int y; }; int main( int /*argc*/, char * * /*argv*/ ) { using namespace boost; X x; function<int(int)> foof( boost::bind( &X::foo, &x, _1 ) ); foof( 0 ); function<int(int)> barf; barf = foof; barf( 1 ); return 0; } Notice in new_function_code_listing.txt how all of the wrapper code in the new Function was completely transparent to the compiler and was completely inlined to relatively simple machine code with direct calls to/through the vtable pointers...while OTOH in current_function_code_listing.txt the code generated for the "barf = foof;" assignement alone is several times larger than the entire code generated for the new Function implementation. The small asm snippet of the generated invoker/'thunk'/'trampoline' code also demonstrates the effects of various tweaks done to minimize or all together remove the need for any stack adjustment on the invoker side... The new implementation of course has the same semantics and exception safety guarantee levels as the original/current one. Listing all of the improvements and detailed implementation changes here in the first post would be quite cluttering as they are quite numerous. Those that desire more tests and details right now, can follow this trail: http://lists.boost.org/Archives/boost/2010/01/160908.php As for the dependencies issue this is solved in several ways: - use of exception handling: new code uses guard objects instead of explicit exception handling and provides a way to change on-empty-behaviour so that the EH code/dependency can easily be removed/disabled - use of RTTI (for getting the type of the stored function object): this can be globally disabled with the BOOST_FUNCTION_NO_RTTI macro. BOOST_NO_RTTI is not used for this purpose for backward compatibility reasons: in the current implementation it actually turns on RTTI emulation...The idea is to also add per instantiation RTTI on-off configurability... 'Configurability' will probably be the most controversial issue/change because it required the addition of an extra template parameter through which an MPL list of policies can be specified at compile-time. This parameter is properly defaulted to allow existing code to compile without changes while providing current Boost.Function behaviour (e.g. on-empty- behaviour). As all the performed tests showed this to also be true in practice the proposed code should IMO go in as a straight drop-in replacement but, of course, I might have missed some important higher level detail/concern so this is open to discussion... Currently two policies are supported: - on throw behaviour (with throw-on-empty, nop-on-empty and assert-on-empty handlers provided) - whether the function instantiation should mark itself (i.e. its operator()) as nothrow. Additional policies my be added later, for example: - sizeof and/or alignment of the SBO buffer - default allocator - per instantiation RTTI on/off ... Finally, there is one more addition, somewhat 'unholy' as it brings in the concept of binding into Boost.Function but considering its efficiency and/or verbosity benefits (and the fact that the first issue can be 'explained away' by saying that this is not actually 'binding' but a workaround for the lack-of-delegates-support C++ language deficiency). The addition is in the form of two more assign() member function overloads (one for a free function that has the exact signature as the Boost.Function instantiation, and one for a member function that has a matching signature with the addition of a this pointer) that allow assignment of (suitably typed) plain (free or member) functions specified as non-type-template parameters. This allows for the removal of the extra indirect-call-through-function-pointer otherwise incurred by traditional assignment of function pointers (not functors), which is actually a rather common use case. For example, in the above example given, one can now write: foof.assign<X, &X::foo>( x ); and get a trivial invoker with the X::foo() target function inlined straight in... -- "What Huxley teaches is that in the age of advanced technology, spiritual devastation is more likely to come from an enemy with a smiling face than from one whose countenance exudes suspicion and hate." Neil Postman