I have some function templates, for example
template <typename T>
void foo(T);
template <typename T>
void bar(T);
// others
and I need to pass each one to an algorithm that will call it with various types, e.g.
template <typename F>
void some_algorithm(F f)
{
// call f with argument of type int
// call f with argument of type SomeClass
// etc.
}
I can't pass in my function template uninstantiated, but I can't instantiate it with any specific type either because some_algorithm
will need to call it with arguments of several different types.
I could adapt my function templates to be polymorphic function objects, e.g.
struct foo_polymorphic
{
template <typename T>
void operator()(T t)
{
foo(t);
}
};
and then pass it as some_algorithm(foo_polymorphic())
. But this requires writing a separate adapter for each of my function templates.
Is there a generic way of adapting a function template to be a polymorphic function object, i.e. some mechanism that I can re-use for each of the function templates I need to adapt, without having to declare something separately for each one?
The short version of the problem is given an overloaded name f
, how to concisely write an object ff
such that ff(a0, a1, a2, ...)
ultimately calls f(a0, a1, a2, ...)
.
A polymorphic functor, how you point out yourself, is the usual solution. But it must be defined out of line (since it has a template member), so I'll consder that not concise enough for the purposes of my answer.
Currently lambda expressions yield a monomorphic functor, so they're close but not quite there.
// set of functions overloaded on int and double
void f(int);
void f(double);
auto ff = [](int i) { return f(i); };
As GMan pointed out in the comments polymorphic lambdas would (should?) be the solution to concisely write polymorphic functors inline.
In the meantime, it is possible to write a make_overload
helper that combines multiple functors into one, such that
auto ff = make_overload(
[](int arg0) { return f(arg0); }
, [](double arg0) { return f(arg0); } );
would 'capture' the whole overload set. Perhaps a Boost.Preprocessor macro could help here, so that auto ff = POLYMORPHIC_LAMBDA( 1, (int)(double), { return f(arg0); } );
be used inline. I suspect there are arity restrictions however (hence the first macro argument), unlike the usual out-of-line hand-written polymorphic functor solution; so this wouldn't help with e.g. variadic function templates.
Why couldn't you use template template parameters? You said you can't pass your template uninstantiated, but I'm not sure if you've heard of this before, tell me if you have and it won't work.
I don't know what your code structure looks like, but can you do something like
I know this works, don't know if it's what yo uwant though:
template<typename T>
T some_algorithm(T data) { return T(); } // just returning nothing for example
template<typename T, T(*Something)(T)>
class FuncClass {
public:
T run(T data) { return Something(data); }
};
template<typename T, typename Functor>
void apply_algorithm(T data) {
Functor F;
F.run(data);
}
int main() {
int mydata = 4;
apply_algorithm<int, FuncClass<int, some_algorithm<int> > >(mydata);
cin.get();
}