Boost logo

Boost :

From: Marco Costalba (mcostalba_at_[hidden])
Date: 2007-10-01 11:20:08


On 10/1/07, Joel de Guzman <joel_at_[hidden]> wrote:
> Marco Costalba wrote:
> > On 10/1/07, Marco Costalba <mcostalba_at_[hidden]> wrote:
> >> On 10/1/07, Joel de Guzman <joel_at_[hidden]> 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


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk