I can't find a nice way to define generic higher-order functions taking generic functions as arguments. For example, take this attempt at one of the simplest such functions out there:
template<typename F, typename A>
auto apply(F f, const A& a) -> decltype(f(a)){return f(a);}
Of course it works as intended when used with non-template functions. But if I have, for instance
template<typename A>
A id(const A& a){return a;}
then
int a = 10;
int b = apply(id, a);
will not work, since id
expects a template parameter. I could just write id<int>
to make it work, but that sort of defeats the purpose (as I see it, it implies that if I wanted to write "filter" I'd have to write a separate definition for each generic predicate function). Using std::function
or function pointers did not help. Also, I tried to make a "template template" version of apply
, but I get various compiler errors when I try to use it:
template<template<typename> class F, typename A>
auto apply2(F<A> f, const A& a)-> decltype(f(a)){return f(a);}
The best I came up with was the following:
struct Id{
template<typename A>
static A func(const A& a){return a;}
};
template<typename F, typename A>
auto apply(A a)-> decltype(F::func(a)){return F::func(a);}
It's a bit ugly, but now at least I can actually parameterize by the function.
So, is there a better way to do generic functions taking generic functions as arguments?