
I have upload in Vault an updated version of the multi-signature function wrapper aka "overload" File is called overload_20_3_2008.zip I think this will be the last one because it's feature complete and "nice" enough. New in this version is: - Support for pointer-to-member functions - Added is_set() and reset() to check for and clear a specific signature - Updated documentation (see test.cpp) - Code cleaned up and IMHO at the same quality level of my previous object factory example. Code is very small and completely self contained (apart for auto_ptr that is used internally instead of plain pointers). I think this could be an interesting example of use of C++ templates at beginner/intermediate level. Thanks Marco

Marco Costalba wrote:
I have upload in Vault an updated version of the multi-signature function wrapper aka "overload"
File is called overload_20_3_2008.zip
I couldn't find any documentation, so I would like to ask you a few questions: The function object can be empty or contain more or less function objects. What happens when calling the function object and there is nothing corresponding to the given signature? I suppose that combination of types that would generate ambiguous deduction are detected and generate an error at the declaration of an overload?

On Thu, Mar 20, 2008 at 6:19 PM, Mathias Gaunard <mathias.gaunard@ens-lyon.org> wrote:
Marco Costalba wrote:
I have upload in Vault an updated version of the multi-signature function wrapper aka "overload"
File is called overload_20_3_2008.zip
I couldn't find any documentation, so I would like to ask you a few questions:
The function object can be empty or contain more or less function objects. What happens when calling the function object and there is nothing corresponding to the given signature?
In this case a dereferencing of a NULL pointer occurs with obvious consequences. I have added the helper is_set to let the user check for it: void foo(int); overload<void(int)> f; cout << f.is_set<void(int)>() << endl; // prints 0 // f(); segfault here ! f.set(foo1); cout << f.is_set<void(int)>() << endl; // prints 1 f(7); // ok, calls foo1 Other options that I have evaluated are: - Assert instead of NULL dereferencing: does not gain much at run-time, always a crash occurs - Silently fail, as example returning a default value: much more dangerous then segfaulting IMHO Any suggestion? (compile time assert does not seem an option because it's related to the runtime value stored in an auto_ptr pointer).
I suppose that combination of types that would generate ambiguous deduction are detected and generate an error at the declaration of an overload?
Overload does NOT impose any additional constrain above what C++ states for overloaded member functions: struct base { void foo1(int) { cout << "base called\n"; } void foo2(double) { cout << "double called\n"; } }; struct derived : base { using base::foo1; using base::foo2; void foo1(int) { cout << "derived called\n"; } void foo2(float) { cout << "float called\n"; } }; int main(int, char**) { derived d; d.foo1(7); // prints "derived called" // d.foo2(7); compile error: ambiguous call } So, as example: void foo(int) { cout << "foo called"; } overload<void(int), void(int)> f(foo); // will work, first signature is hidden by second one f(7); // will print "foo called" IOW the first signature will be hidden by the second one both at assign time then at calling time, it's like first signature is never take in account. Different is the case of ambiguous call... void test1(float) {} void test2(double) {} overload<void(float), void(double)> g(test1, test2); // g(7); compile error: ambiguous call So to answer your questions: - If a signature is declared more then once only the last one is actually used, the others are hidden (100% harmless) - If two different signatures are declared then declaration of overload succeed, but if overload is then called with an argument for which no exact match occurs, but that can be converted to BOTH the overloaded function then a compile error occurs of the type "ambiguous call" Marco

Marco Costalba wrote:
Other options that I have evaluated are:
- Assert instead of NULL dereferencing: does not gain much at run-time, always a crash occurs
- Silently fail, as example returning a default value: much more dangerous then segfaulting IMHO
Any suggestion? (compile time assert does not seem an option because it's related to the runtime value stored in an auto_ptr pointer).
I guess you considered throwing an exception eg argument_error. If you don't mind me asking (its the way to learn) if you did reject throwing an exception, why? On the surface it seems that throwing at least allows the possibility of graceful termination for programs (I do realise uncaught exceptions still abort the program without cleanup), so I suspect there must be something deeper that I have missed. Kevin

On Sat, Mar 22, 2008 at 12:12 PM, Kevin Scarr <kscarr@iinet.net.au> wrote:
Marco Costalba wrote:
On the surface it seems that throwing at least allows the possibility of graceful termination for programs (I do realise uncaught exceptions still abort the program without cleanup), so I suspect there must be something deeper that I have missed.
Throwing an exception it's a possibility. Actually I have not really considered it, but probably it's my fault. Normally I mentally associate exceptions with something that can go wrong in some "strange" way, eventually out of the control of the caller. It comes much more naturally to me to think at this: if (ptr) ptr->doSomething(); then this try { ptr->doSomething(); } catch (ptr_is_null) In our case it is possible to use is_set() to check for a NULL pointer before to call the function, but, again, this is only my way to think, perhaps exceptions are the more idiomatic way to code in this case. Anyhow exception is a perfectly viable solution. Thanks for the suggestion Marco

Marco Costalba wrote:
It comes much more naturally to me to think at this:
if (ptr) ptr->doSomething();
Ok. This usage is fine with me. I guess I just hadn't seen the overload<> as being a declaration of an object with pointer behaviour. If that is what it is, then I would prefer the usage above. Thanks for the clarification, Kevin

On Sat, Mar 22, 2008 at 7:18 PM, Kevin Scarr <kscarr@iinet.net.au> wrote:
Marco Costalba wrote:
It comes much more naturally to me to think at this:
if (ptr) ptr->doSomething();
Ok. This usage is fine with me. I guess I just hadn't seen the overload<> as being a declaration of an object with pointer behaviour.
If that is what it is, then I would prefer the usage above.
Thanks for the clarification,
I'm browsing standard exceptions but I fail to see something suitable in this case. A little of background: when you call an overload with some arguments, as example f(7); According to the arguments type and arity a specific operator() of the overload class is called by the compiler. This operator() mainly dereferences the content of an auto_ptr that points to a functor wrapper that does the job. If no function as been already assigned then auto_ptr is empty and is here the a segfault occurs, when you try to dereference it's content. So, I would like to ask you what exception type do you suggest could be suitable to throw in this case? Thanks Marco

Marco Costalba wrote:
So, I would like to ask you what exception type do you suggest could be suitable to throw in this case?
Interestingly, I looked at the std::exception classes as well when I saw your earlier post and, I agree, there is nothing that leaps out as directly appropriate. I guess at a stretch you could use "invalid argument" since the null pointer is caused by not having an operator defined with those arguments, but it is a stretch and not very satisfying. There is also "runtime error" which is so general as to require a note in the overload document in big bold letters to explain why you are using it. Again, not so satisfying. Alternatively, you can derive your own exception from std::exception in the overload namespace with a more descriptive type. Then you can put some diagnostic information in the exception to help the programmer track it down. Such an exception is also catchable as a std::exception. Kevin

On Sat, Mar 22, 2008 at 8:21 PM, Kevin Scarr <kscarr@iinet.net.au> wrote:
Marco Costalba wrote:
So, I would like to ask you what exception type do you suggest could be suitable to throw in this case?
Interestingly, I looked at the std::exception classes as well when I saw your earlier post and, I agree, there is nothing that leaps out as directly appropriate.
Ok, I have stolen boost.function exception: struct bad_function_call : std::runtime_error { bad_function_call() : std::runtime_error("call to empty function") {} }; With this I have two things: - A correct exception to throw when an empty slot is called - The proof that you are right: it's idiomatic to throw an exception in this case I plan to post an update with exception's support (I have already implemented it in the meantime ;-) just after Easter holidays (Monday evening), so to leave some time for other suggestions. Thanks again Marco

On Sun, Mar 23, 2008 at 3:49 AM, Marco Costalba <mcostalba@gmail.com> wrote:
I plan to post an update with exception's support (I have already implemented it in the meantime ;-) just after Easter holidays (Monday evening), so to leave some time for other suggestions.
Thanks again Marco
How about overwriting what's in the sandbox instead of posting it to the vault? I'm glad that you've moved forward with the overload implementation -- should it be time to update the documentation as well? -- Dean Michael C. Berris Software Engineer, Friendster, Inc. [http://blog.cplusplus-soup.com] [mikhailberis@gmail.com] [+63 928 7291459] [+1 408 4049523]

On Sat, 22 Mar 2008 21:17:00 +0100, Dean Michael Berris <mikhailberis@gmail.com> wrote:
On Sun, Mar 23, 2008 at 3:49 AM, Marco Costalba <mcostalba@gmail.com> wrote:
I plan to post an update with exception's support (I have already implemented it in the meantime ;-) just after Easter holidays (Monday evening), so to leave some time for other suggestions.
Thanks again Marco
How about overwriting what's in the sandbox instead of posting it to the vault?
I'm glad that you've moved forward with the overload implementation -- should it be time to update the documentation as well?
Hi Dean, maybe there is a misunderstanding :-) If you remind there were two Marco working on different overload implementation. I didn't work anymore on Boost.Overload, I'm sorry but I had been really busy. I hope to have time for working on the library in May. So be patient. Hi Marco, how are you ? Now I have no time to review your new implementation, but I'm happy that you didn't give up. Kind Regards, Marco Cecchetti -- Using Opera's revolutionary e-mail client: http://www.opera.com/mail/

On Sat, Mar 22, 2008 at 10:49 PM, Marco <mrcekets@gmail.com> wrote:
On Sat, 22 Mar 2008 21:17:00 +0100, Dean Michael Berris
How about overwriting what's in the sandbox instead of posting it to the vault?
Hi Dean, Glad to hear you :-) Indeed I have no files in the sandbox...
Hi Marco, how are you ? Now I have no time to review your new implementation, but I'm happy that you didn't give up.
I'm fine, thanks, I'm glad to hear you again. Two things made me rewrite overload: - The finding that is possible to use (a much easier) SFINAE technique instead of metaprogramming indexing - The finding of an extension of Mesonide's trick (do you remember ;-) to handle pointer-to-member functions too This two points made me rewrite the whole stuff: it's much more clean, small, easy to follow and I would say feature complete then before. I'll be very happy if, when you have (a little) time, you can give me your precious feedback. Thanks and "Buona Pasqua" (1) Marco (1) Happy Easter

On Sun, Mar 23, 2008 at 5:49 AM, Marco <mrcekets@gmail.com> wrote:
On Sat, 22 Mar 2008 21:17:00 +0100, Dean Michael Berris <mikhailberis@gmail.com> wrote:
How about overwriting what's in the sandbox instead of posting it to the vault?
I'm glad that you've moved forward with the overload implementation -- should it be time to update the documentation as well?
Hi Dean, maybe there is a misunderstanding :-) If you remind there were two Marco working on different overload implementation. I didn't work anymore on Boost.Overload, I'm sorry but I had been really busy. I hope to have time for working on the library in May. So be patient.
Oh dear, yes I have misunderstood! I'm sorry for the confusion. :D It's alright, I understand the being busy part. :) -- Dean Michael C. Berris Software Engineer, Friendster, Inc. [http://blog.cplusplus-soup.com] [mikhailberis@gmail.com] [+63 928 7291459] [+1 408 4049523]

On Sat, Mar 22, 2008 at 8:49 PM, Marco Costalba <mcostalba@gmail.com> wrote:
I plan to post an update with exception's support (I have already implemented it in the meantime ;-) just after Easter holidays (Monday evening), so to leave some time for other suggestions.
Ok, here we are. This will be hopefully the last version released. New in this release: - Overload now throws an exception instead of crashing when an empty function is called (mimics boost.function) - Modified our little and simple home-grown 'function' class (*) to reduce code duplication. - Updated docs and tests. - Compiles with no warnings under gcc 3.4, gcc 4.2 and MSVC 2008 You can download from boost Vault, file name is overload_24_3_2008.zip Have fun Marco (*) Overload aims to be self contained, BTW only standard library is needed.

On Thu, Mar 20, 2008 at 2:44 PM, Marco Costalba <mcostalba@gmail.com> wrote:
I have upload in Vault an updated version of the multi-signature function wrapper aka "overload"
File is called overload_20_3_2008.zip
Due to a critical bug I was forced to update the file that now is called overload_22_3_2008.zip I'm very sorry for this :< the bug it's not easy to trigger but anyway it's a bug and, what's worst, is due to a mis-design of operator() member functions, so that the library fails it's primary goal that is to give an example of use of templates in C++. As a small bonus I have added copy semantic support to the overload class that is now copy constructible and assignable and I have improved the docs according to the feedback I have received. Thanks and sorry again for this Marco
participants (5)
-
Dean Michael Berris
-
Kevin Scarr
-
Marco
-
Marco Costalba
-
Mathias Gaunard