Question

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?

Was it helpful?

Solution

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.

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top