I want to pass a function value as a template parameter to a function. Currently the best I managed to do is :
template< typename F, F f >
It's now possible in C++17 with template<auto>
:
template<auto Func>
struct FuncWrapper final
{
template<typename... Args>
auto operator()(Args &&... args) const
{
return Func(std::forward<Args>(args)...);
}
};
int add(int a, int b)
{
return a + b;
}
int main()
{
FuncWrapper<add> wrapper;
return wrapper(12, 34);
}
Demo: https://godbolt.org/g/B7W56t
You can use #ifdef __cpp_nontype_template_parameter_auto
to detect compiler support for this in your code.
If you are able to use C++20 and you want better error messages, you can also use concepts:
template<typename T>
concept CanAddTwoNumbers = std::is_invocable_r_v<int, T, int, int>;
template<auto Func>
requires CanAddTwoNumbers<decltype(Func)>
struct AddTwoNumbersWrapper final
{
auto operator()(int a, int b) const
-> int
{
return std::invoke(Func, a, b);
}
};
int add(int a, int b)
{
return a + b;
}
int main()
{
AddTwoNumbersWrapper<add> wrapper;
return wrapper(12, 34);
AddTwoNumbersWrapper<123> bad; //error: constraint failure
}
Demo: https://gcc.godbolt.org/z/ai3WGH
I believe shortening this is currently impossible. A year ago, the C++ committee looked at http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3601.html to fix this, and they encouraged the authors to pursue it further after C++14 was released.
You need to make a typedef for whatever function type you want to pass as a pointer, like this:
typedef int (*MyFunctionType)(int);
template <typename FunctionTypedef, typename ReturnType, typename ParameterType>
ReturnType callFunction(FunctionTypedef functionPointer, ParameterType i)
{
static MyFunctionType myFunctionPointer = functionPointer;
return (*functionPointer)(i);
}
int myFunction(int i)
{
}
int main()
{
int i = 7;
MyFunctionType myFunctionPointer = myFunction;
return callFunction<MyFunctionType, int, int>(myFunctionPointer, i);
}
Edit: If you want to store these arbitrarily typed function pointers, then make a base class with a virtual "call function" function, and a templated derived class that implements this function.