|
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