
On Sat, Oct 30, 2010 at 1:55 PM, Emil Dotchevski <emil@revergestudios.com> wrote:
On Sat, Oct 30, 2010 at 9:43 AM, Daniel Walker <daniel.j.walker@gmail.com> wrote:
Yes, if you look at the code in the benchmark, you will see that it is measuring the cost of a call to a non-empty boost::function. In optimized object code, the call is 4% faster without the check, but removing the check means that it is necessary to store a special, internal static object per instantiation to hold an "empty" function that must be available if boost::function becomes empty.
Do you really need a placeholder for each different boost::function signature?
Yes. Internally, boost::function creates a static object for each signature to hold the target function. To hold the "empty" target function, it must create a second static object per signature: one for actual targets, one for an empty target.
Since all it does is throw an exception, it should be safe to use the same placeholder for all signatures: http://codepad.org/3GxiTHZA.
The issue is not whether we create a new _type_ for the placeholder per signature, but whether we create a new static _object_. So, adapting your example, the following makes your function look a little more like boost::function. template<class R, class T0, class T1> struct function { typedef R (*target_type)(T0,T1); target_type f; function() { static target_type stored_f = (target_type)&placeholder; f = stored_f; } R operator()(T0 a, T1 b) { f(a,b); } }; You can see that function<void, int, int> f; function<void, double, double> g; would create two static stored_f objects, one per instantiation, regardless of the type of placeholder. Good question! Daniel Walker