Reputation: 30103
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?
Upvotes: 1
Views: 104
Reputation: 153955
In C++11 the best you can do is to use a struct
with a templatized function call operator:
struct ID {
template <typename T>
void operator()(T arg) const {
...
}
};
The reason this is preferrable to a function [pointer] because it more likely to be inlined. With C++14 you could use lambdas:
[](auto arg){ ... }
which is just a cute version to write the struct
above.
Upvotes: 1
Reputation: 217850
This 'functor' works with your first version of apply.
struct id
{
template<typename A>
A operator ()(const A& a) {return a;}
};
later
int b = apply(id(), a); // with extra parenthesis to construct the struct.
Upvotes: 3