Reputation: 1155
int f1(int a, int b) { return a+b; }
int f2(int a, int b) { return a*b; }
template <typename F> void foo(int i, int j)
{
// do some processing before
F(i,j);
// do some processing after
}
I want to make an alias to a specialization of foo like this:
constexpr auto foo1 = &foo<f1>;
constexpr auto foo2 = &foo<f2>;
and call the function like this: foo1(1,2);foo2(1,2);
Any way to achieve this in C++? Thanks!
Edit: foo() is not a wrapper of f1, it is a function that calls f1 or f2. I need to do something extra before and after the call. F is a functor and I want a 'short cut' to the specialization of foo. The code above is kind of psuedo code.
Upvotes: 5
Views: 3000
Reputation: 73176
The accepted answer is spot-on for the OP's request. To complement that answer: an alternative method could be letting the int(int, int)
function pointer be an additional argument to the function (in which case we needn't use template techniques), and use std::bind
to set up the different default case functions to be used.
#include <iostream>
#include <functional>
int f1(int a, int b) { return a+b; }
int f2(int a, int b) { return a*b; }
int f3(int a, int b) { return a-b; }
void foo(int i, int j, int (*f)(int, int)) {
// do some processing before
std::cout << f(i, j) << std::endl;
// do some processing after
}
int main()
{
const auto foo1 = std::bind(foo, std::placeholders::_1, std::placeholders::_2, &f1);
const auto foo2 = std::bind(foo, std::placeholders::_1, std::placeholders::_2, &f2);
foo1(5, 5); // 10
foo2(5, 5); // 25
foo(5, 5, &f3); // 0
return 0;
}
A variation of the above could allow using function wrappers (std::function
) to store the help functions as values, in cases these would, for some reason, risk going out of scope prior to the caller objects (foo1
, foo2
, ...).
void foo(int i, int j, const std::function<int(int, int)> f) { /* ... */ }
// ...
const auto foo1 = std::bind(foo, std::placeholders::_1, std::placeholders::_2, f1);
const auto foo2 = std::bind(foo, std::placeholders::_1, std::placeholders::_2, f2);
Upvotes: 1
Reputation: 41092
There are some good approaches in the comments: std::bind, using a lambda, passing an instance of F
into the function, so I'll provide an alternative.
If the function type that you will pass into foo
will always be int(int, int)
, then you make the template parameter be a non-type template parameter, and then instantiate it with one of your functions:
int f1(int a, int b) { std::cout<<"f1\n"; return a+b; }
int f2(int a, int b) { std::cout<<"f2\n"; return a*b; }
template <int(*F)(int, int)>
void foo(int i, int j)
{
F(i,j);
}
And then call it like so:
int main()
{
constexpr auto foo1 = foo<f1>;
constexpr auto foo2 = foo<f2>;
foo1(1,2);
foo2(1,2);
}
Output:
f1
f2
The trick we're doing here is that we're making the template parameter be a reference to a function, which is hacky but legal AFAIK.
Upvotes: 6