|
Comparison between boost::function
objects cannot be implemented "well", and therefore will not be
implemented. The typical semantics requested for f ==
g given boost::function objects
f and g are:
- If
f and g
store function objects of the same type, use that type's
operator== to compare
them.
- If
f and g
store function objects of different types, return
false .
The problem occurs when the type of the function objects
stored by both f and g doesn't have an
operator== : we would like the expression f ==
g to fail to compile, as occurs with, e.g., the standard
containers. However, this is not implementable for
boost::function because it necessarily
"erases" some type information after it has been assigned a
function object, so it cannot try to call
operator== later: it must either find a way to call
operator== now, or it will never be able to call it
later. Note, for instance, what happens if you try to put a
float value into a
boost::function object: you will get an
error at the assignment operator or constructor, not in
operator() , because the function-call expression
must be bound in the constructor or assignment operator.
The most promising approach is to find a method of
determining if operator== can be called for a
particular type, and then supporting it only when it is
available; in other situations, an exception would be
thrown. However, to date there is no known way to detect if an
arbitrary operator expression f == g is suitably
defined. The best solution known has the following undesirable
qualities:
- Fails at compile-time for objects where
operator== is not accessible (e.g., because it is
private ).
- Fails at compile-time if calling
operator== is ambiguous.
- Appears to be correct if the
operator== declaration is correct, even though
operator== may not compile.
All of these problems translate into failures in the
boost::function constructors or
assignment operator, even if the user never invokes
operator==. We can't do that to users.
The other option is to place the burden on users that want
to use operator== , e.g., by providing an
is_equality_comparable trait they may
specialize. This is a workable solution, but is dangerous in
practice, because forgetting to specialize the trait will result
in unexpected exceptions being thrown from
boost::function 's
operator== . This essentially negates the usefulness
of operator== in the context in which it is most
desired: multitarget callbacks. The
Signals library has a way around
this.
|
|
Yes, boost::function is type
safe even though it uses void pointers and pointers to functions
returning void and taking no arguments. Essentially, all type
information is encoded in the functions that manage and invoke
function pointers and function objects. Only these functions are
instantiated with the exact type that is pointed to by the void
pointer or pointer to void function. The reason that both are required
is that one may cast between void pointers and object pointers safely
or between different types of function pointers (provided you don't
invoke a function pointer with the wrong type). |
|
Void returns are permitted by the C++ standard, as in this code snippet:
void f();
void g() { return f(); }
This is a valid usage of boost::function because void returns are not used. With void returns, we would attempting to compile ill-formed code similar to:
int f();
void g() { return f(); }
In essence, not using void returns allows
boost::function to swallow a return value. This is
consistent with allowing the user to assign and invoke functions and
function objects with parameters that don't exactly match.
|
|
In November and December of 2000, the issue of cloning
vs. reference counting was debated at length and it was decided
that cloning gave more predictable semantics. I won't rehash the
discussion here, but if it cloning is incorrect for a particular
application a reference-counting allocator could be used. |
|
The cost of boost::function can be reasonably
consistently measured at around 20ns +/- 10 ns on a modern >2GHz
platform versus directly inlining the code.
However, the performance of your application may benefit
from or be disadvantaged by boost::function
depending on how your C++ optimiser optimises. Similar to a
standard function pointer, differences of order of 10% have been
noted to the benefit or disadvantage of using
boost::function to call a function that contains a
tight loop depending on your compilation circumstances.
[Answer provided by Matt Hurd. See http://article.gmane.org/gmane.comp.lib.boost.devel/33278]
|