Boost logo

Boost :

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


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??)

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;
}

Thanks a lot.
--Lorenzo


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