Boost logo

Boost :

Subject: Re: [boost] [functional] adding overload
From: Lorenzo Caminiti (lorcaminiti_at_[hidden])
Date: 2012-01-16 17:08:38


On Mon, Jan 16, 2012 at 9:11 AM, Roman Perepelitsa
<roman.perepelitsa_at_[hidden]> wrote:
> 2012/1/16 Lorenzo Caminiti <lorcaminiti_at_[hidden]>
>
>> On Sun, Jan 15, 2012 at 9:06 PM, Nathan Ridge <zeratul976_at_[hidden]>
>> 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


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