Home > Blockchain >  Is there a way to pass a function template into a function?
Is there a way to pass a function template into a function?

Time:09-27

I have some template code that takes a function as an argument. I'd like to extend it to use a function template as an argument.

The existing code is:

int add1( int i ) { return i 1; }

template <typename Func, typename Integer>
Integer call_func( Func f, Integer i ) { return f(i); }

// Usage is
auto four = call_func( add1, 3 );

It works fine. If I add a version of add1 that takes a template parameter, I get:

template <typename Integer>
Integer add1_t( Integer i ) { return i 1; }

// Usage is
auto four = call_func( add1_t<int>, 3 );

What I would really like to do, however, is to not specify the full type of the function, only the template, as in:

auto four = call_func( add1_t, 3 );

and let call_func apply the template argument. Is there a way to do that?

My best guess is:

template <template <typename> typename Func, typename Integer>
Integer call_func( Func<Integer> f, Integer i ) { return f(i); }

but the type of f cannot be deduced when I do that. Even if I wanted to supply an explicit "type" at the call-site, I'm not sure what that would be.

CodePudding user response:

From your comment:

I was just hoping to avoid the syntax of wrapping functions in structs

Making functors (basically wrapping functions in classes) is a pretty common solution to things that involve passing functions around.

Here is one way to do that in your case:

template <typename Integer>
struct add1_t {
    Integer operator()( Integer i ) { return i 1; }
};

template <template <typename> class F, typename Integer>
Integer call_func( Integer i ) { return F<Integer>{}(i); }

int main() {
    auto four = call_func<add1_t>( 3 );
}

Demo

CodePudding user response:

You cannot pass template function. but you can pass functor with template operator().

Lambda does that job easily, keep your original call_func, and change call to:

auto four = call_func([](auto arg){ return add1_t(arg)], 3 );

MACRO can also help:

#define OVERLOAD_SET(FUNC_NAME) [](auto&&... args){ return FUNC_NAME(decltype(args)(args)...); }
// Can be improved with noexcept, and SFINAE friendly

auto four = call_func(OVERLOAD_SET(add1_t), 3 );
  • Related