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 );
}
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 );