|
Boost : |
Subject: Re: [boost] [function] "paranoia" vs efficiency
From: OvermindDL1 (overminddl1_at_[hidden])
Date: 2009-10-02 15:15:30
On Fri, Oct 2, 2009 at 10:40 AM, Domagoj Saric <dsaritz_at_[hidden]> wrote:
>
> "Mathias Gaunard" <mathias.gaunard_at_[hidden]> wrote in message
> news:ha52jl$4oc$1_at_ger.gmane.org...
>> Domagoj Saric wrote:
>>> As far as I can see boost::function<>::operator() performs:
>>> if (this->empty())
>>> Â Â Â boost::throw_exception(bad_function_call());
>>> before invoking the stored function (object)...
>>> My question is why or why only this "checked"/"safe" approach/method of
>>> invocation exists?
>>
>> BOOST_ASSERT(!empty()) would be better in my opinion indeed, but it's hard to
>> make that change now for compatibility reasons.
>
> considering the improvement is more than cosmetic i'm (always) for breaking
> changes (but then again i do not, yet, 'live' in the 'conservative corporate
> universe' where you bow to BackwardCompatibility ;)...
>
> but, come to think of it, there is an (almost) win win solution...
> what if the check-and-throw is not performed with an explicit if-and-throw but
> rather a default constructed or emptied boost::function<> object does not
> actually become 'empty' (in the sense that it holds a null pointer/object) but
> rather it holds a default/static/shared function pointer/object that does the
> actual throw...
> ...this is an 'almost' win win solution because you now get a thin/inlined away
> function<>::operator() and the same 'safe' behaviour but are still left with
> exceptions (the compiler still must 'regard' operator() as a possibly throwing
> function)...
> if we go further we could add one more useful behaviour without breaking
> changes...the default behaviour could be parameterized (with the default being
> the exception throw for backward compatibility) to be:
> 1. throw
> 2. assert in debug - access violate on a null pointer in release
> 3. nop
>
> the third option would eliminate the tipical: { if ( myFunction )
> myFunction(); } code (it would, in fact/actually eliminate the branching from
> the generate code itself, because it would be implemented by calling a function
> through a pointer, that you would do anyway, that does nothing, simply
> returns)...
>
> now, if we make the parameter for the OnEmpty behaviour a template parameter we
> could have a truly win-win solution (if ofcourse, one could implicitly add the
> __declspec( nothrow ) or equivalent function declaration 'decorator' to the
> boost::function<>::operator() based on a template parameter and/or actual used
> function object type)...
>
> seeing this article http://www.codeproject.com/KB/cpp/fastdelegate2.aspx makes
> me realize (or just think?) that the same approach can be used to create
> multicast functions/delegates (didn't yet have time to check how was it
> implemented in that article/if there is a better solution) without 'breaking
> changes', or creating a new boost::multicast_function<> class or adding any
> runtime overhead to boost::function<> instances that would not use multicasting
> capabilities (multicasting would/could be implemented by a special internal
> function object that calls the many stored functions in a list, or thru a
> function chain of some sort...)
That is something I have been curious about since I first looked at
the Boost.Function source. I was curious why it did not use any real
policies like most other things in boost, for example one policy could
enforce it to only use function pointers (no functors) for situations
where you know it would only be pointers so you could get a speed
advantage, or ones for other purposes (such as the multi-cast example
above, that sounds fascinating, I would use it).
And I *love* the idea about using a nop static func that throws, or
perhaps asserts, all depending on policy settings for example. :)
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk