
On 10/1/07, Joel de Guzman <joel@boost-consulting.com> wrote:
Marco Costalba wrote:
On 10/1/07, Marco Costalba <mcostalba@gmail.com> wrote:
On 10/1/07, Joel de Guzman <joel@boost-consulting.com> wrote:
Joel de Guzman wrote:
Hence, I'd like to propose an extension (or a separate library) for allowing overloads for boost.function. The example above can be declared as:
[snip]
A little bit more complex but works for any number of arguments (sigantures).
Smart, Marco! You know fusion well :-)
Well, not so well, it doesn't compile...but I've looked also at tuples in the meantime and this one actually works: Sorry to post the file but I have no access to my host: /*============================================================================= Copyright (c) 2006 Joel de Guzman Use, modification and distribution is subject to the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ==============================================================================*/ #if !defined(BOOST_OVERLOAD_06162006_2345) #define BOOST_OVERLOAD_06162006_2345 #include <boost/function.hpp> #include <boost/tuple/tuple.hpp> namespace boost { template <int size> struct final_overload_function { struct final; static int const index = size; void operator()(final*) const {} }; template <typename Base, typename Derived, typename Sig> struct overload_function; template <typename Base, typename Derived, typename R> struct overload_function<Base, Derived, R()> : Base { using Base::operator(); static int const index = Base::index - 1; R operator()() const { return get<index>(static_cast<Derived const*>(this)->functions)(); } }; template <typename Base, typename Derived, typename R, typename A0> struct overload_function<Base, Derived, R(A0)> : Base { using Base::operator(); static int const index = Base::index - 1; R operator()(A0 a0) const { return get<index>(static_cast<Derived const*>(this)->functions)(a0); } }; template <typename Base, typename Derived, typename R, typename A0, typename A1> struct overload_function<Base, Derived, R(A0, A1)> : Base { using Base::operator(); static int const index = Base::index - 1; R operator()(A0 a0, A1 a1) const { return get<index>(static_cast<Derived const*>(this)->functions)(a0, a1); } }; template <typename Base, typename Derived, typename R, typename A0, typename A1, typename A2> struct overload_function<Base, Derived, R(A0, A1, A2)> : Base { using Base::operator(); static int const index = Base::index - 1; R operator()(A0 a0, A1 a1, A2 a2) const { return get<index>(static_cast<Derived const*>(this)->functions)(a0, a1, a2); } }; template <typename Seq> struct overload; namespace detail { template <typename Seq, typename derived, int n, int size> struct do_compose { typedef typename Seq::head_type head; typedef typename Seq::tail_type tail; typedef typename do_compose<tail, derived, n - 1, size>::type ov; typedef overload_function<ov, derived, head> type; }; template <typename Seq, typename derived, int size> struct do_compose<Seq, derived, 1, size> { typedef typename Seq::head_type head; typedef overload_function<final_overload_function<size>, derived, head> type; }; template <typename Seq> struct compose_overload_base { enum { n = tuples::length<Seq>::value }; typedef overload<Seq> derived; typedef typename do_compose<Seq, derived, n, n>::type type; }; } template <typename Seq> struct overload : detail::compose_overload_base<Seq>::type { typedef typename tuples::element<0, Seq>::type Sig0; typedef typename tuples::element<1, Seq>::type Sig1; typedef typename tuples::element<2, Seq>::type Sig2; typedef typename tuples::element<3, Seq>::type Sig3; typedef tuple< boost::function<Sig0> , boost::function<Sig1> , boost::function<Sig2> , boost::function<Sig3> > functions_type; template <int N, typename F> void set(F const& f) { get<N>(functions) = f; } functions_type functions; }; } #endif And the test is: /*============================================================================= Copyright (c) 2006 Joel de Guzman Use, modification and distribution is subject to the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ==============================================================================*/ #include <string> #include <iostream> #include "overload.hpp" #include <boost/detail/lightweight_test.hpp> int foo1(char) { return 123; } double foo2(int, char) { return 123.456; } char foo3(std::string) { return 'x'; } void foo4(std::string s1, std::string s2, std::string s3) { std::cout << s1 << s2 << s3 << std::endl; } int main() { typedef boost::tuple< int(char) , double(int, char) , char(std::string) , void(std::string, std::string, std::string) > Signatures; boost::overload<Signatures> f; f.set<0>(&foo1); f.set<1>(&foo2); f.set<2>(&foo3); f.set<3>(&foo4); int i = f('x'); double d = f(123, 'x'); char c = f("hello"); f("Hello", ", World", ", I'm Joel"); BOOST_ASSERT(i == 123); BOOST_ASSERT(d > 123.455 && d < 123.457); BOOST_ASSERT(c == 'x'); return boost::report_errors(); } It compiles and works for me. Thanks Marco