
On Fri, Feb 17, 2012 at 10:16 PM, Lorenzo Caminiti <lorcaminiti@gmail.com> 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