Boost logo

Boost :

Subject: Re: [boost] [functional] [overloaded_function] polymorphic functions?
From: Lorenzo Caminiti (lorcaminiti_at_[hidden])
Date: 2012-02-17 22:26:48


On Fri, Feb 17, 2012 at 10:16 PM, Lorenzo Caminiti
<lorcaminiti_at_[hidden]> wrote:
> Hello all,
>
> I spent some time trying to make overloaded_function support
> polymorphic functions but I had little success :(
>
> 1) I was able to do this (see code below):
>
>    overloaded_function<
>          void (int)
>        , functor<poly, void (generic)>
>    > o(f, p);
>    o(321);
>    o(3.21);
>    o("cba");
>
> But I don't like it because I explicitly have to pass the functor type
> poly. I wanted instead to only use generic to tag the template
> parameters in the signature:
>
>    overloaded_function<
>          void (int)
>        , void (generic)
>    > o(f, p);
>    o(321);
>    o(3.21);
>    o("cba");
>
> I'd consider this acceptable but I wasn't able to program this because
> I loose p's type (poly) in base so base cannot hold a reference to the
> functor p... Is there a way around this? (Some type-erasure magic
> maybe??)

Actually, with the small change base<R (Ftor::*)(generic)> I can do this:

    overloaded_function<
          void (int)
        , void (poly::*)(generic)
> o(f, p);
    o(321);
    o(3.21);
    o("cba");

Which looks better to me than using functor<poly, void (generic)> but
still: Is there any way I can get rid of specifying the functor type
poly completely?

> 2) I don't think this can work with function templates because in
> order to get a pointer to a function template you have to instantiate
> it:
>
>    g<char*>
>
> Now I can get the function pointer but it's not polymorphic anymore...
>
> 3) I don't think there is any way to implement
> make_overloaded_function with polymorphic types because I can't
> re-construct the function signature from the functor given that its
> operator contains template parameters... I have no idea on how to work
> around this...
>
> If you have suggestions for 1, 2, or 3), they are welcome. Otherwise,
> it seems that supporting polymorphic functions in overloaded_function
> is not really feasible...
>
> The little I got so far:
>
> #include <boost/function.hpp>
> #include <boost/type_traits/function_traits.hpp>
> #include <iostream>
>
> void f(int x) { std::cout << x << std::endl; }
>
> template<typename T>
> void g(T x) { std::cout << x << std::endl; }
>
> struct poly {
>    template<typename T>
>    void operator()(T x) { std::cout << x << std::endl; }
> };
>
> template<typename F>
> struct base {
>    template<typename G>
>    base(G g) : f_(g) {}
>
>    typename boost::function_traits<F>::result_type operator()(
>        typename boost::function_traits<F>::arg1_type arg1
>    ) {
>        return f_(arg1);
>    }
>
> private:
>    boost::function<F> f_;
> };
>
> struct generic;
>
> template<typename Ftor, typename F>
> struct functor;
>
> template<typename Ftor, typename R>
> struct base< functor<Ftor, R (generic)> > {
>    base(Ftor& ftor) : ftor_(ftor) {}
>
>    template<typename Arg1>
>    R operator()(Arg1 arg1) { return ftor_(arg1); }
> private:
>    Ftor& ftor_;
> };
>
> template<typename F1, typename F2>
> struct overloaded_function : base<F1>, base<F2> {
>    template<typename G1, typename G2>
>    overloaded_function(G1 g1, G2 g2) : base<F1>(g1), base<F2>(g2) {}
>
>    using base<F1>::operator();
>    using base<F2>::operator();
> };
>
> int main() {
>    f(123);
>    g("xyz");
>    boost::function<void (char*)> gg = g<char*>;
>
>    poly p;
>    p(1.23);
>    p("abc");
>
>    overloaded_function<
>          void (int)
>        , functor<poly, void (generic)>
>    > o(f, p);
>    o(321);
>    o(3.21);
>    o("cba");
>
>    return 0;
> }

--Lorenzo


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