Subject: Re: [boost] [function] function wrapping with no exceptionsafetyguarantee
From: Daniel Walker (daniel.j.walker_at_[hidden])
Date: 2010-10-30 14:47:21


On Sat, Oct 30, 2010 at 1:55 PM, Emil Dotchevski
<emil_at_[hidden]> wrote:
> On Sat, Oct 30, 2010 at 9:43 AM, Daniel Walker
> <daniel.j.walker_at_[hidden]> 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