Re: [boost] [announce] Multi-signature overload of any function or function object

Marco Costalba wrote:
Yet another C++ toy announce!
After the object factory this time it comes a multi-signature function overload.
My old overload zip package in Vault has been replaced by a complete new one.
This one is much simpler and very small although it's completely self contained (no _any_ library needed, even not standard ones) and is, IMHO, a better example of an exercise on C++ templates.
BTW it even seems to work ;-)
Interested people could find it in boost Vault under the name overload_5_3_2008.zip of course any feedback is welcomed.
Thanks for your attention Marco
Do you have any design doc I can read?

On Wed, Mar 5, 2008 at 12:19 PM, Neal Becker <ndbecker2@gmail.com> wrote:
Do you have any design doc I can read?
A struct overload it's a hierarchy of many overload_function template classes. Each overload_function template it's instantiated on given signature. One overload_function per signature. The overload_function template defines one operator() that forwards its calling arguments to a function wrapper called 'functor'. This functor it's a very simple home made replacement of boost.function. Each overload_function defines also a couple of set() member functions that are used to link one of our simplified 'functor' with a specific function/function object the user passes in as the set() argument. At calling time, according to the passed in arguments the correct overload_function::operator() will be linked by the compiler, but how to invoke the correct overload_function::set() among all the ones that are instantiated by our struct overload ? To achieve this a SFINAE tecnique is used on an (hidden) second argument of set(). Indeed one signature of set() is: template<typename Fun> void set(Fun* fun, typename enable_if<is_compatible<Fun, Sig>::value>::type = 0); When, as example, a pointer to a function 'fun' is passed in the signature Fun of the pointer is tested against Sig that is the signature on which this overload_function is instantiated. Value of is_compatible<Fun, Sig>::value is true only for types F that are functions with signature Sig or functors whose operator() has signature Sig. So, given that all the signatures on which is defined an overload struct are unique, only one of the set() member functions will be enabled. More or less that's all. Marco

----- Original Message ----- From: "Marco Costalba" <mcostalba@gmail.com> To: <boost@lists.boost.org> Sent: Wednesday, March 05, 2008 1:53 PM Subject: Re: [boost] [announce] Multi-signature overload of any function orfunction object
On Wed, Mar 5, 2008 at 12:19 PM, Neal Becker <ndbecker2@gmail.com> wrote:
Do you have any design doc I can read?
A struct overload it's a hierarchy of many overload_function template classes.
Each overload_function template it's instantiated on given signature. One overload_function per signature.
The overload_function template defines one operator() that forwards its calling arguments to a function wrapper called 'functor'.
This functor it's a very simple home made replacement of boost.function.
Each overload_function defines also a couple of set() member functions that are used to link one of our simplified 'functor' with a specific function/function object the user passes in as the set() argument.
At calling time, according to the passed in arguments the correct overload_function::operator() will be linked by the compiler, but how to invoke the correct overload_function::set() among all the ones that are instantiated by our struct overload ?
To achieve this a SFINAE tecnique is used on an (hidden) second argument of set().
Indeed one signature of set() is:
template<typename Fun> void set(Fun* fun, typename enable_if<is_compatible<Fun, Sig>::value>::type = 0);
When, as example, a pointer to a function 'fun' is passed in the signature Fun of the pointer is tested against Sig that is the signature on which this overload_function is instantiated.
Value of is_compatible<Fun, Sig>::value is true only for types F that are functions with signature Sig or functors whose operator() has signature Sig. So, given that all the signatures on which is defined an overload struct are unique, only one of the set() member functions will be enabled.
More or less that's all.
Marco
Hello, I have take a lock to the code. Could you tell us if there is a deep raison to not use boost::function, boost::enable_if, boost::mpl::list ...? I have no doubt of the usefulness of such a overload class. What happens if we forget to initialize one of the signatures? crash ? What can you do to improbe this aspect. Do you think that is possible to have a version ensuring a default function for each signature? Somting like overload_ns::overload < signatures<int() , int(char), , double(int, char), , char(string), , string(string, string, string) >, default_functions<foo1, &foo2, foo3, &foo4, foo5_ptr> > f; or overload_ns::overload < fct<int(),foo1>, , fct<int(char), &foo2>, , fct<double(int, char), foo3>, , fct<char(string), &foo4>, , fct<string(string, string, string), foo5_ptr> > f; Could you give a practical example? Which is the context you have used it? Regards _____________________ Vicente Juan Botet Escriba

On Wed, Mar 5, 2008 at 10:40 PM, vicente.botet <vicente.botet@wanadoo.fr> wrote:
I have take a lock to the code. Could you tell us if there is a deep raison to not use boost::function, boost::enable_if, boost::mpl::list ...?
Only to be self contained, this is not intended to be library, it's more of an example and a concept proposal thing, in case there is interest I can trasnform it in a stable and reliable thing using the above mentioned facilities.
What happens if we forget to initialize one of the signatures? crash ?
Yes. Why it shouldn't ;-) IOW if you "forget" to initialize a function it's a bug. A crash is a very good diagnostic for such a bug.
What can you do to improbe this aspect.
Do you think that is possible to have a version ensuring a default function for each signature? Somting like
overload_ns::overload < signatures<int() , int(char), , double(int, char), , char(string), , string(string, string, string) >, default_functions<foo1, &foo2, foo3, &foo4, foo5_ptr> > f;
A possible better way could be to set the functions directly in the constructor: overload_ns::overload < signatures<int() , int(char), , double(int, char), , char(string), , string(string, string, string) > f(foo1, &foo2, foo3, &foo4, foo5_ptr); BTW in my opinion default functions to avoid a crash when user "forgets" to initialize properly it means to replace a simply discoverable bug with a much more subtle one. This is just my opinion. Thanks Marco
participants (3)
-
Marco Costalba
-
Neal Becker
-
vicente.botet