
On Sat, May 10, 2008 at 11:36 AM, Marco Costalba <mcostalba@gmail.com> wrote:
On Sat, May 10, 2008 at 10:43 AM, vicente.botet <vicente.botet@wanadoo.fr> wrote:
Try with struct foo_t { template<class T> void operator()(T){} } foo;
Yep, sorry for the typo :)
boost::function<void(int)> f = foo; // ok it works, no ambiguity, object is instantiated as foo_t::operator<int>()
boost::multi_signature_function:: function<boost::mpl::vector<void(int), void(std::string)> > msf = foo;
// error! Ambiguous call <strip> could be void(int) or <strip> void(std::string)
msf = f; // this works! no more ambiguity, foo_t is instantiated with T = int
So the bottom line is that it does not work because compiler does not know to which internal boost::function to bound foo, because it could be bounded to both boost::function<void(int)> and boost::function<void(std::string)> an "ambiguous call" type error arise...as it should, if I can dare.
Well my idea was that an unconstrained template function object would be bound to all internal boost::functions (in fact this would require MSF to hold N instances of the function objects, in an ideal case it would only hold one instance and have a function pointer per every signature). In fact in this case using operator= makes sense: you use it only one and all signatures are applied to the object in the RHS. I think that in your case, using operator= is confusing because you are not really reassigning the MSF but just adding an overload. What if operator= tries to bind all signatures at once (and thus allows for boost::function like adaptability) and operator+= (or an explicit add member function) is strict and allows to replace a single overload? This might not be what MSF is for, but I was thinking, for example, of something like this: struct visitor { template<class T, class State> void operator(State, T) { /* do something generically using State and T*/ } }; typedef boost::fusion::tuple<int, std::string, double, char> my_seq; void for_each(my_seq&, msf<int, std::string, double, char>); // for_each can now be implemented in another translation unit // and used like this: my_seq f; struct my_state {...} state; // note that with the current implementation we would have N copies // state for_each(f, boost::bind<void>(visitor(), _1, state));
Replying to a previous message...
This library extension, although flexible and IMHO powerful is notably very simple and small, so I would like to ask if someone is interested to add this code in some way directly to boost.function
While useful, I do not think this library belongs in boost function (which is monomorphic), but it should be a library of its own.
Form boost.function documentation:
"Generally, any place in which a function pointer would be used to defer a call or make a callback, Boost.Function can be used instead"
Where boost.function naturally models a function, multi-signature boost::function naturally models an overload set
Actually it is a bit more, because you can have different state for each overload. I would need something in the middle: a single polymorphic closure which can be accessed dynamically with multiple objects. I can of course do this with your MSF by adding another level of indirection, but it seems wasteful. it would be better if it was the reverse (you have to pay for the storage of each signature state only if you need it), IMHO it would be better. -- gpd