[functional] adding overload

Hello all, During Boost.Local review, it was proposed to move the overload template out of Local and in Boost.Functional. What would the best name for it? 1) boost::overload_function (my preference) 2) boost::overloaded_function 3) boost::function_overload 4) boost::functional::overload (Boost.Functional seems to use boost:: directly and not boost::functional-- to mimic C++11 <functional>). For example: void print_text(char const* text) { std::cout << text << std::endl; } void print_add(int x, int y = 10) { std::cout << (x + y) << std::endl; } boost::function<void (int, int)> f = print_add; boost::overload_function< void (char const*) , void (int, int) , void (int)
print(print_text, f, print_add);
print("abc"); // abc print(1, 2); // 3 print(1); // 11 Docs: https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/boost/loca... Thanks. --Lorenzo

On Sun, 15 Jan 2012 13:53:24 -0800, Lorenzo Caminiti <lorcaminiti@gmail.com> wrote:
Hello all,
During Boost.Local review, it was proposed to move the overload template out of Local and in Boost.Functional. What would the best name for it?
1) boost::overload_function (my preference) 2) boost::overloaded_function 3) boost::function_overload 4) boost::functional::overload (Boost.Functional seems to use boost:: directly and not boost::functional-- to mimic C++11 <functional>).
What about boost::multi_function?

On Sun, Jan 15, 2012 at 7:30 PM, Mostafa <mostafa_working_away@yahoo.com> wrote:
On Sun, 15 Jan 2012 13:53:24 -0800, Lorenzo Caminiti <lorcaminiti@gmail.com> wrote:
Hello all,
During Boost.Local review, it was proposed to move the overload template out of Local and in Boost.Functional. What would the best name for it?
1) boost::overload_function (my preference) 2) boost::overloaded_function 3) boost::function_overload 4) boost::functional::overload (Boost.Functional seems to use boost:: directly and not boost::functional-- to mimic C++11 <functional>).
What about boost::multi_function?
IMO, overload (somewhere) is a good name because it expresses the fact that the resulting functor overloads all the specified functors. Thanks. --Lorenzo

During Boost.Local review, it was proposed to move the overload template out of Local and in Boost.Functional. What would the best name for it?
1) boost::overload_function (my preference) 2) boost::overloaded_function 3) boost::function_overload 4) boost::functional::overload (Boost.Functional seems to use boost:: directly and not boost::functional-- to mimic C++11 ).
I like boost::functional::overload. You can then add a convenience function make_overload() with creates one without having to specify the template parameters, and it will be at once intuitive-sounding and consistent with Boost naming conventions. Regards, Nate

On Sun, Jan 15, 2012 at 9:06 PM, Nathan Ridge <zeratul976@hotmail.com> wrote:
During Boost.Local review, it was proposed to move the overload template out of Local and in Boost.Functional. What would the best name for it?
1) boost::overload_function (my preference) 2) boost::overloaded_function 3) boost::function_overload 4) boost::functional::overload (Boost.Functional seems to use boost:: directly and not boost::functional-- to mimic C++11 ).
I like boost::functional::overload. You can then add a convenience function make_overload() with creates one without having to specify
Yes, I will add boost::functional::make_overload as well.
the template parameters, and it will be at once intuitive-sounding and consistent with Boost naming conventions.
Reading the Functional docs: ``The header functional.hpp provides enhancements to the function object adapters specified in the C++ Standard Library (sections 20.3.5, through to 20.3.8). // (1) Using these adapters should be pretty much the same as using the standard function object adapters; the only differences are that you need to write boost:: instead of std::, and that you will get fewer headaches.'' Now boost/functional/overload.hpp instead will not match anything that is in the C++ Standard Library... is that an issue for adding overload to functional? I don't think so because overload is still within Functional's stated purpose: ``The Boost.Function library contains a family of class templates that are function object wrappers.'' Plus overload will not be in the functional.hpp header so (1) will still be true for stuff that is in functional.hpp. However, I'd like Functional's authors to comment if they have any concern with adding overload to Functional. Thanks. --Lorenzo

2012/1/16 Lorenzo Caminiti <lorcaminiti@gmail.com>
On Sun, Jan 15, 2012 at 9:06 PM, Nathan Ridge <zeratul976@hotmail.com> wrote:
I like boost::functional::overload. You can then add a convenience function make_overload() with creates one without having to specify
Yes, I will add boost::functional::make_overload as well.
I don't think it can be implemented in general case. What signature will it have? Roman Perepelitsa.

On Mon, Jan 16, 2012 at 9:11 AM, Roman Perepelitsa <roman.perepelitsa@gmail.com> wrote:
2012/1/16 Lorenzo Caminiti <lorcaminiti@gmail.com>
On Sun, Jan 15, 2012 at 9:06 PM, Nathan Ridge <zeratul976@hotmail.com> wrote:
I like boost::functional::overload. You can then add a convenience function make_overload() with creates one without having to specify
Yes, I will add boost::functional::make_overload as well.
I don't think it can be implemented in general case. What signature will it have?
It was suggested during Boost.Local review to use make_overload with auto (or BOOST_AUTO): auto f = make_overload(f1, f2, f3); For example: void print_s(const std::string& s) { std::cout << s << std::endl; } void print_i(int i) { std::cout << i << std::endl; } void print_d(double d) { std::cout << d << std::endl; } int main(void) { boost::function<void (double)> pd = print_d; print_s("abc"); print_i(123); pd(1.23); std::cout << std::endl; boost::functional::overload< void (const std::string&) , void (int) , void (double) > print(print_s, print_i, pd); print("abc"); print(123); print(1.23); std::cout << std::endl; BOOST_AUTO(p, boost::functional::make_overload(&print_s, &print_i, pd)); p("abc"); p(123); p(1.23); std::cout << std::endl; return 0; } This can be implemented using a suitable function_type that returns the function type result_type (arg1_type, ...) from a function type, function pointer, function reference, or from a functor which defines the types result_type, arg1_type, ... (as for example boost::function does). I don't think such implementation of function_types exists... IMO, I'd be nice to make boost::function_types::function_type (that right now only accepts a mpl sequence) to also accept function types, function pointer, function references, and functor types defining result_type, arg1_type, etc. I'd implement function_type for functors like this: #include <boost/functional/overload.hpp> #include <boost/function.hpp> #include <boost/function_types/is_function.hpp> #include <boost/function_types/is_function_pointer.hpp> #include <boost/function_types/is_function_reference.hpp> #include <boost/type_traits.hpp> #include <boost/mpl/apply.hpp> #include <boost/mpl/if.hpp> #include <boost/mpl/identity.hpp> #include <boost/mpl/lambda.hpp> #include <boost/mpl/placeholders.hpp> #include <iostream> #include <string> #include <typeinfo> namespace boost { namespace functional { namespace detail { template<typename F, int Arity = -1> struct functor_type { typedef typename functor_type<F, F::arity>::type type; }; template<typename F> struct functor_type<F, 0> { typedef typename F::result_type (type)( ); }; template<typename F> struct functor_type<F, 1> { typedef typename F::result_type (type)( typename F::arg1_type ); }; template<typename F> struct functor_type<F, 2> { typedef typename F::result_type (type)( typename F::arg1_type , typename F::arg2_type ); }; } // namespace detail template<typename F> struct function_type { typedef typename boost::mpl::if_<boost::function_types::is_function<F>, boost::mpl::identity<F> , typename boost::mpl::if_<boost::function_types:: is_function_pointer<F>, boost::remove_pointer<F> , typename boost::mpl::if_<boost::function_types:: is_function_reference<F>, boost::remove_reference<F> , detail::functor_type<F> >::type >::type >::type ::type type; }; template<typename F0, typename F1, typename F2> boost::functional::overload< typename function_type<F0>::type , typename function_type<F1>::type , typename function_type<F2>::type
make_overload(F0 f0, F1 f1, F2 f2) { return boost::functional::overload< typename function_type<F0>::type , typename function_type<F1>::type , typename function_type<F2>::type >(f0, f1, f2); } } } // namespace --Lorenzo

2012/1/16 Lorenzo Caminiti <lorcaminiti@gmail.com>
On Mon, Jan 16, 2012 at 9:11 AM, Roman Perepelitsa <roman.perepelitsa@gmail.com> wrote:
2012/1/16 Lorenzo Caminiti <lorcaminiti@gmail.com>
On Sun, Jan 15, 2012 at 9:06 PM, Nathan Ridge <zeratul976@hotmail.com> wrote:
I like boost::functional::overload. You can then add a convenience function make_overload() with creates one without having to specify
Yes, I will add boost::functional::make_overload as well.
I don't think it can be implemented in general case. What signature will it have?
It was suggested during Boost.Local review to use make_overload with auto (or BOOST_AUTO):
auto f = make_overload(f1, f2, f3);
Right, but there is no way to make it work for any function object, unless make_overload returns a proxy object with conversion operator to boost::functional::overload<...>. I'm not sure if such a thing would be useful, but it may be. Roman Perepelitsa.

This can be implemented using a suitable function_type that returns the function type result_type (arg1_type, ...) from a function type, function pointer, function reference, or from a functor which defines the types result_type, arg1_type, ... (as for example boost::function does).
You can also implement it for any function object with a nontemplated operator() even if it doesn't provide arg1_type etc. typedefs, by examining the signature of its operator(). Regards, Nate

On Mon, Jan 16, 2012 at 5:34 PM, Nathan Ridge <zeratul976@hotmail.com> wrote:
This can be implemented using a suitable function_type that returns the function type result_type (arg1_type, ...) from a function type, function pointer, function reference, or from a functor which defines the types result_type, arg1_type, ... (as for example boost::function does).
You can also implement it for any function object with a nontemplated operator() even if it doesn't provide arg1_type etc. typedefs, by examining the signature of its operator().
Right! Below I'm wrapping function types, pointers, and references inside a functor type boost::function; if F is instead already a functor, I leave it unchanged (see functor_wrap). Then I manipulate the type of the functor operator() to generate the function type (see functor_unwrap). That allows me to pass any function type, pointer, reference, or any functor (which defines an operator()) to make_overload (without requiring the functor to typedef result_type, arg1_type, etc) :) One question: Can I do this even without the TYPEOFs inside deduce_type below? I was not able to generate the make_overload result type without the TYPEOF (I can instead generate the overload type within the make_overload function body even without the TYPEOF using another function template to let the template system deduce the types). That is probably not a big deal because make_overload is useful when you can use it with AUTO and TYPEOF will always work in these cases. #include <boost/functional/overload.hpp> #include <boost/function.hpp> #include <boost/function_types/is_function.hpp> #include <boost/function_types/is_function_pointer.hpp> #include <boost/function_types/is_function_reference.hpp> #include <boost/function_types/function_type.hpp> #include <boost/function_types/parameter_types.hpp> #include <boost/function_types/result_type.hpp> #include <boost/type_traits/remove_pointer.hpp> #include <boost/type_traits/remove_reference.hpp> #include <boost/mpl/if.hpp> #include <boost/mpl/identity.hpp> #include <boost/mpl/pop_front.hpp> #include <boost/mpl/push_front.hpp> #include <boost/typeof/typeof.hpp> #include <iostream> #include <string> namespace boost { namespace functional { namespace detail { namespace overload { // Transform a function F into a functor type. // Precondition: F is a function type, a function pointer, a function // reference, or already a functor. template<typename F> class functor_wrap { template<typename MetaF> struct functor { typedef typename boost::function< typename MetaF::type > type; }; public: typedef typename boost::mpl::if_< boost::function_types::is_function<F>, functor< boost::mpl::identity<F> > , typename boost::mpl::if_< boost::function_types:: is_function_pointer< F >, functor< boost::remove_pointer< F > > , typename boost::mpl::if_< boost::function_types:: is_function_reference< F >, functor< boost::remove_reference< F > > , // Requires: It's already a functor. boost::mpl::identity< F > >::type >::type >::type ::type type; }; // Transform a functor F into a function type. template<typename F> struct functor_unwrap { typedef typename boost::function_types::function_type< typename boost::mpl::push_front< typename boost::mpl::pop_front< // Remove functor type (1st). typename boost::function_types::parameter_types<F>::type >::type , typename boost::function_types::result_type<F>::type >::type >::type type; }; template<typename F0, typename F1, typename F2> struct deduce_type { typedef boost::functional::overload< typename functor_unwrap< BOOST_TYPEOF_TPL(&(functor_wrap<F0>::type::operator())) >::type , typename functor_unwrap< BOOST_TYPEOF_TPL(&(functor_wrap<F1>::type::operator())) >::type , typename functor_unwrap< BOOST_TYPEOF_TPL(&(functor_wrap<F2>::type::operator())) >::type > type; }; } } // namespace detail::overload template<typename F0, typename F1, typename F2> typename detail::overload::deduce_type<F0, F1, F2>::type make_overload(F0 f0, F1 f1, F2 f2) { return typename detail::overload::deduce_type<F0, F1, F2>::type(f0, f1, f2); } } } // namespace boost::functional void print_s(const std::string& s) { std::cout << s << std::endl; } void print_i(int i) { std::cout << i << std::endl; } void print_d(double d) { std::cout << d << std::endl; } int main(void) { boost::function<void (double)> pd = print_d; print_s("abc"); print_i(123); pd(1.23); std::cout << std::endl; boost::functional::overload< void (const std::string&) , void (int) , void (double) > print(print_s, print_i, pd); print("abc"); print(123); print(1.23); std::cout << std::endl; BOOST_AUTO(p, boost::functional::make_overload(&print_s, &print_i, pd)); p("abc"); p(123); p(1.23); std::cout << std::endl; return 0; } Thanks! --Lorenzo

On Tue, Jan 17, 2012 at 5:25 AM, Lorenzo Caminiti <lorcaminiti@gmail.com> wrote:
On Mon, Jan 16, 2012 at 5:34 PM, Nathan Ridge <zeratul976@hotmail.com> wrote:
This can be implemented using a suitable function_type that returns the function type result_type (arg1_type, ...) from a function type, function pointer, function reference, or from a functor which defines the types result_type, arg1_type, ... (as for example boost::function does).
You can also implement it for any function object with a nontemplated operator() even if it doesn't provide arg1_type etc. typedefs, by examining the signature of its operator().
Right! Below I'm wrapping function types, pointers, and references inside a functor type boost::function; if F is instead already a functor, I leave it unchanged (see functor_wrap). Then I manipulate the type of the functor operator() to generate the function type (see functor_unwrap). That allows me to pass any function type, pointer, reference, or any functor (which defines an operator()) to make_overload (without requiring the functor to typedef result_type, arg1_type, etc) :)
One question: Can I do this even without the TYPEOFs inside deduce_type below?
Simplifying things a bit... but the typeof is still hanging in there :( namespace boost { namespace functional { namespace detail { // Precondition: F is a functor. template<typename F> class functor_type { typedef BOOST_TYPEOF_TPL(&(F::operator())) call_ptr; public: typedef typename boost::function_types::function_type< typename boost::mpl::push_front< typename boost::mpl::pop_front< // Remove functor type (1st). typename boost::function_types::parameter_types< call_ptr>::type >::type , typename boost::function_types::result_type<call_ptr>::type >::type >::type type; }; // Precondition: F is a function type, pointer, reference, or functor. template<typename F> struct function_type { typedef typename boost::mpl::if_<boost::function_types::is_function<F>, boost::mpl::identity<F> , typename boost::mpl::if_<boost::function_types:: is_function_pointer<F>, boost::remove_pointer<F> , typename boost::mpl::if_<boost::function_types:: is_function_reference<F>, boost::remove_reference<F> , // Requires, it's a functor. functor_type<F> >::type >::type >::type ::type type; }; } // namespace detail template<typename F0, typename F1, typename F2> overload< typename detail::function_type<F0>::type , typename detail::function_type<F1>::type , typename detail::function_type<F2>::type
make_overload(F0 f0, F1 f1, F2 f2) { return overload< typename detail::function_type<F0>::type , typename detail::function_type<F1>::type , typename detail::function_type<F2>::type >(f0, f1, f2); }
} } // namespace boost::functional --Lorenzo

Nathan Ridge wrote:
Lorenzo Caminiti wrote:
During Boost.Local review, it was proposed to move the overload template out of Local and in Boost.Functional. What would the best name for it?
1) boost::overload_function (my preference) 2) boost::overloaded_function 3) boost::function_overload 4) boost::functional::overload (Boost.Functional seems to use boost:: directly and not boost::functional-- to mimic C++11 ).
I like boost::functional::overload. You can then add a convenience function make_overload() with creates one without having to specify the template parameters, and it will be at once intuitive-sounding and consistent with Boost naming conventions.
An overload is a function with a signature differing from others of the same name. What's being created here is a function object that represents an overload set. It's a collection of overloaded functions. "overload" is not correct as you're using it. "overloaded_function" is closer to correct, but I think that "overload_set" is the right term. You create an overload_set object and call it. When called, it does something like overload resolution, and forwards to the appropriate callable in the set. Thus, I suggest boost::function_overload_set and boost::make_function_overload_set, if you want to avoid the nested namespace (and permit s/boost/std/ for the future), and boost::functional::overload_set and boost::functional::make_overload_set, otherwise. _____ Rob Stewart robert.stewart@sig.com Software Engineer using std::disclaimer; Dev Tools & Components Susquehanna International Group, LLP http://www.sig.com ________________________________ IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

On Tue, Jan 17, 2012 at 10:32 AM, Stewart, Robert <Robert.Stewart@sig.com> wrote:
Nathan Ridge wrote:
Lorenzo Caminiti wrote:
During Boost.Local review, it was proposed to move the overload template out of Local and in Boost.Functional. What would the best name for it?
1) boost::overload_function (my preference) 2) boost::overloaded_function 3) boost::function_overload 4) boost::functional::overload (Boost.Functional seems to use boost:: directly and not boost::functional-- to mimic C++11 ).
I like boost::functional::overload. You can then add a convenience function make_overload() with creates one without having to specify the template parameters, and it will be at once intuitive-sounding and consistent with Boost naming conventions.
An overload is a function with a signature differing from others of the same name. What's being created here is a function object that represents an overload set. It's a collection of overloaded functions. "overload" is not correct as you're using it. "overloaded_function" is closer to correct, but I think that "overload_set" is the right term. You create an overload_set object and call it. When called, it does something like overload resolution, and forwards to the appropriate callable in the set.
I don't like the _set postfix- even if correct, I'd find it confusing as a user. I picked overloaded_function. Here's a first draft for the docs: https://svn.boost.org/svn/boost/sandbox/closure/libs/functional/overloaded_f... Comments welcome. Thanks. --Lorenzo

on Tue Jan 17 2012, Lorenzo Caminiti <lorcaminiti-AT-gmail.com> wrote:
as a user. I picked overloaded_function.
Here's a first draft for the docs:
https://svn.boost.org/svn/boost/sandbox/closure/libs/functional/overloaded_f...
Comments welcome.
What are the use-cases for such a beast? -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On Mon, Jan 30, 2012 at 1:34 PM, Dave Abrahams <dave@boostpro.com> wrote:
on Tue Jan 17 2012, Lorenzo Caminiti <lorcaminiti-AT-gmail.com> wrote:
as a user. I picked overloaded_function.
Here's a first draft for the docs:
https://svn.boost.org/svn/boost/sandbox/closure/libs/functional/overloaded_f...
Comments welcome.
What are the use-cases for such a beast?
Just the case that you have a bunch of functions (function pointers, function references, and monomorphic functors) with different names and you want to combine them into an API with a single overloaded function name. History: The idea was originally raised as a side discussion on the limitation that local functions cannot be polymorphic http://lists.boost.org/Archives/boost/2011/05/181501.php . No Boost.Local reviewer raised concerns on adding overloaded_function and the consensus was to potentially add it under Boost.Functional. However, my impression was that all reviewers saw this as a "nice to have" (so no object but not strong preference for addition either). I since then asked Boost.Functional authors (and Boosters in general) if there is any concern with adding this functionality but I didn't get much of a reply :( Do you have any concern? Thanks. --Lorenzo

On Jan 31, 2012, at 7:23 PM, Lorenzo Caminiti <lorcaminiti@gmail.com> wrote:
Just the case that you have a bunch of functions (function pointers, function references, and monomorphic functors) with different names and you want to combine them into an API with a single overloaded function name.
I think this will be generally useful. I wonder if you have thought about the case where the source funcs are polymorphic? Can this be supported using the same technique or does it require some metaprogramming magic? Cheers, Gordon

Gordon Woodhull wrote
On Jan 31, 2012, at 7:23 PM, Lorenzo Caminiti <lorcaminiti@> wrote:
Just the case that you have a bunch of functions (function pointers, function references, and monomorphic functors) with different names and you want to combine them into an API with a single overloaded function name.
I think this will be generally useful.
I wonder if you have thought about the case where the source funcs are polymorphic? Can this be supported using the same technique or does it require some metaprogramming magic?
I don't think it is possible to handle polymorphic functions because overloaded_function keeps a copy of the function (pointer, reference, or object) into a member of type boost::function<signature> (then boost::function is called within the overloaded_function operator() ). If `signature` contains a generic template parameter type T, I can't form a proper boost::function<signature> type to hold a copy of the function when overloaded_function is constructed... I will spend more time thinking and experimenting with this. I will post a code example illustrating the exact issue if indeed I cannot support polymorphic functions. Thanks. --Lorenzo -- View this message in context: http://boost.2283326.n4.nabble.com/functional-adding-overload-tp4297850p4361... Sent from the Boost - Dev mailing list archive at Nabble.com.

On Tue, 17 Jan 2012 14:37:10 -0800, Lorenzo Caminiti <lorcaminiti@gmail.com> wrote:
On Tue, Jan 17, 2012 at 10:32 AM, Stewart, Robert <Robert.Stewart@sig.com> wrote:
Nathan Ridge wrote:
Lorenzo Caminiti wrote:
During Boost.Local review, it was proposed to move the overload template out of Local and in Boost.Functional. What would the best name for it?
1) boost::overload_function (my preference) 2) boost::overloaded_function 3) boost::function_overload 4) boost::functional::overload (Boost.Functional seems to use boost:: directly and not boost::functional-- to mimic C++11 ).
I like boost::functional::overload. You can then add a convenience function make_overload() with creates one without having to specify the template parameters, and it will be at once intuitive-sounding and consistent with Boost naming conventions.
An overload is a function with a signature differing from others of the same name. What's being created here is a function object that represents an overload set. It's a collection of overloaded functions. "overload" is not correct as you're using it. "overloaded_function" is closer to correct, but I think that "overload_set" is the right term. You create an overload_set object and call it. When called, it does something like overload resolution, and forwards to the appropriate callable in the set.
I don't like the _set postfix- even if correct, I'd find it confusing as a user. I picked overloaded_function.
Here's a first draft for the docs:
https://svn.boost.org/svn/boost/sandbox/closure/libs/functional/overloaded_f...
Comments welcome.
Didn't Boost.Interface, something that was worked on a while back but never made it into Boost proper, capture this functionality, but more comprehensively? BTW, in the url above "closure" should be replaced by "local_function".

Mostafa-6 wrote
https://svn.boost.org/svn/boost/sandbox/closure/libs/functional/overloaded_f...
Comments welcome.
Didn't Boost.Interface, something that was worked on a while back but never made it into Boost proper, capture this functionality, but more comprehensively?
I don't think so... but I don't really remember so I will double check.
BTW, in the url above "closure" should be replaced by "local_function".
Yes, I changed the library name. Ultimatelly, overloaded_function will be moved from LocalFunction into Functional/OverloadedFunction when I move code from local_function sandbox into trunk. Thanks. --Lorenzo -- View this message in context: http://boost.2283326.n4.nabble.com/functional-adding-overload-tp4297850p4361... Sent from the Boost - Dev mailing list archive at Nabble.com.
participants (8)
-
Dave Abrahams
-
Gordon Woodhull
-
lcaminiti
-
Lorenzo Caminiti
-
Mostafa
-
Nathan Ridge
-
Roman Perepelitsa
-
Stewart, Robert