
On Sun, May 8, 2011 at 11:22 AM, Mathias Gaunard <mathias.gaunard@ens-lyon.org> wrote:
On 08/05/2011 16:04, Lorenzo Caminiti wrote:
auto /* or the real type */ l = overload(l1, l2);
Does Boost already have a functor overloader like overload() above?
I do not think so.
template<typename F0, typename F1, typename F2 = void, typename F3 = void> struct overload { };
template<typename F0R, typename F0A0, typename F1R, typename F1A0> struct overload<F0R (F0A0), F1R (F1A0)> { overload(boost::function<F0R (F0A0)> f0, boost::function<F1R (F1A0)> f1): f0_(f0), f1_(f1) {} F0R operator()(F0A0 a0) const { return f0_(a0); } F1R operator()(F1A0 a0) const { return f1_(a0); } private: boost::function<F0R (F0A0)> f0_; boost::function<F1R (F1A0)> f1_; };
// More specializations to overload also with F2, F3, etc.
The type erasure appear unnecessary, and this implementation has big forwarding problems.
What about
template<typename F0, typename F1> struct overload_t : F0, F1 { overload_t(F0 const& f0, F1 const& f1) : F0(f0), F1(f1) { }
using F0::operator(); using F1::operator(); };
template<typename F0, typename F1> overload_t<F0, F1> overload(F0 const& f0, F1 const& f1) { return overload_t<F0, F1>(f0, f1); }
Yes, makes sense. Using your suggestion: #include <boost/local/function.hpp> #include <boost/function.hpp> #include <vector> #include <algorithm> #include <iostream> #include <string> namespace boost { namespace local { namespace function { template<typename F0, typename F1, typename F2 = void, typename F3 = void> struct overloaded {}; // Specialization for 2 functions. template<typename F0, typename F1> struct overloaded<F0, F1>: F0, F1 { overloaded(F0 const& f0, F1 const& f1): F0(f0), F1(f1) {} using F0::operator(); using F1::operator(); }; template<typename F0, typename F1> overloaded< boost::function<F0>, boost::function<F1> > overload( boost::local::aux::function<F0> const& f0 , boost::local::aux::function<F1> const& f1 ) { return overloaded< boost::function<F0>, boost::function<F1> >(f0, f1); } // Specialization for 3 functions. template<typename F0, typename F1, typename F2> struct overloaded<F0, F1, F2>: F0, F1, F2 { overloaded(F0 const& f0, F1 const& f1, F2 const& f2): F0(f0), F1(f1), F2(f2) {} using F0::operator(); using F1::operator(); using F2::operator(); }; template<typename F0, typename F1, typename F2> overloaded< boost::function<F0>, boost::function<F1>, boost::function<F2> > overload( boost::local::aux::function<F0> const& f0 , boost::local::aux::function<F1> const& f1 , boost::local::aux::function<F2> const& f2 ) { return overloaded< boost::function<F0>, boost::function<F1>, boost::function<F2> >(f0, f1, f2); } // More specializations for more functions... }}} // namespace boost::local::function // More specializations to overload also with F2, F3, etc. int main() { char sep = '\n'; void BOOST_LOCAL_FUNCTION_PARAMS(const double& item, const bind& sep) { std::cout << item << sep; } BOOST_LOCAL_FUNCTION_NAME(print_double) void BOOST_LOCAL_FUNCTION_PARAMS(const std::string& item, const bind& sep) { std::cout << item << sep; } BOOST_LOCAL_FUNCTION_NAME(print_string) void BOOST_LOCAL_FUNCTION_PARAMS(const char& item, const bind& sep) { std::cout << item << sep; } BOOST_LOCAL_FUNCTION_NAME(print_char) boost::local::function::overloaded< boost::function< void (const double&) > , boost::function< void (const std::string&) > , boost::function< void (const char&) > > print = boost::local::function::overload( print_double, print_string, print_char); std::vector<double> d(2); d[0] = 1.2; d[1] = 3.4; std::for_each(d.begin(), d.end(), print); std::vector<std::string> s(3); s[0] = "ab"; s[1] = "cd"; s[2] = "ef"; std::for_each(s.begin(), s.end(), print); char c[4] = {'x', 'y', 'z', 'w'}; std::for_each(c, c + 4, print); return 0; }
Function pointers will have to be dealt with specially, though.
This is not an issue for Boost.Local. If overload() and overloaded<> where to be added to Boost.Function instead, this case should be handled. I will make a note of this in Boost.Local docs rationale. Thanks a lot. On a separate note, Boost.Local does not allow to name a local function after an operator. Would that ever be useful? -- Lorenzo