|
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