|
Boost : |
Subject: Re: [boost] [function] "paranoia" vs efficiency
From: Domagoj Saric (dsaritz_at_[hidden])
Date: 2009-10-02 12:40:50
"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 men do not learn very much from the lessons of history is the most important of all the lessons of history." Aldous Huxley
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk