
On Tue, May 13, 2008 at 3:11 PM, Marco Costalba <mcostalba@gmail.com> wrote:
On Mon, May 12, 2008 at 7:39 PM, Giovanni Piero Deretta <gpderetta@gmail.com> wrote:
I.e. MSF is the natural extension of boost::function in the realm of polymorphic function objects (well, you still have to choose beforehand the types you want to work with, but it is still much better than boost::function).
[ BTW, by a quick at the code of MSF you do not seem to implement the result_of protocol. You definitely should, as MSF is definitely a polymorphic function object,]
IOW you mean that given
typedef boost::msf_function<double(double), int(int),std::string(std::string)> MSF;
The implementation should lead to...
boost::result_of<MSF(double)>::type i; // i is a double boost::result_of<MSF(int)>::type i; // i is an int boost::result_of<MSF(std::string)>::type i; // i is a std::string
Is this correct?
Exactly! MSF should support it.
Still your current implementation has a problem.
--strip----
msf_function<int(int), double(double), my_big_int(my_big_int)> x = frob(10);
it has two downsides ... 1) it does N dynamic allocations, one for each signature.
well, a boost::function is allocated (empty) on the stack because it's a member data.
boost::function in most cases does an internal allocation. If I follow the implementation correctly (which of course might not be:) ) , I think that MSF contains a boost::function for every possible signature. For funciton pointers this shouldn't be a problem because boost::function is optimized for small objects, but for more consistent functors it might require a fair number of allocations.
2) it has N copies of 'frob::state', which for a small object as an int it is not a problem, but in principle it can be wasteful
... and a serious problem: As there are n different states, the increment is separate for each type, and not for all of them:
This is more a "behaviour" then a problem,
It is a problem only if one expects that behavior. The current implementation isn't necessarily wrong, but I think that is surprising, since MSF wants to be an obvious extension to boost::function.
as example I can have a state named calls_counter that counts how many time an operator() has been called for each different type of arguments. In this case having separate state is a need:
T operator()(T i) {
calls_counter++;
...do something....
return some_value; }
My point is that you get the separate objects behavior from the same object behaviour at no extra cost, while the reverse is impossible. This is why I think that the 'same object' behavior is more fundamental (and IMHO the expected) and it is what MSF should implement.
The real problem IMHO is that this behaviour is not well documented, I'll fix this.
In practice MSF acts as N different boost::function objects with a think type based dispatcher. I can of course fix the problem by adding another layer of indirection:
Have you tried to fix it with
msf_function<int(int), double(double), my_big_int(my_big_int)> x;
x = boost::ref( frob(10) );
Indeed boost::function supports ref() and cref() to avoid the copy when is not needed or when the copy is simply wrong. MSF supports ref() and cref() too and forwards them, still wrapped, to the underlying boost::function objects so that no copy of the wrapped polymorphic function object is made.
This has different semantics from what I wanted. I do not want to have to keep the wrapped object in the stack to add it in a wrapper. In this case I need I want MSF to copy my object (i.e. to manage its lifetime) but I want it to do only one copy (usually for efficiency, but sometimes like this case, for correctness).
Thanks
Thanks to you. I think that MSF might be a valid addition to boost. -- gpd