Function Pointers
Imagine you have a function which takes a number and squares it and returns it. And you have a list whose each member you want squared. How do you do that?
- You either write another function which accepts an array, loops through it and converts every element to its square.
- You have a function which accepts an array and a function which can transform one single element. You apply the function to each element of the array.
Both perform the same task. You might think the previous case is easier to implement. You wont have to deal with function pointers after all.
However what if you have say 20 functions which can double, triple, cube, square, etc. a single parameter passed to them. If you follow the first route, you have to write 20 different functions (with probably different names). However now the latter makes sense. You just declare the individual functions. And call the transformer function by passing the array and any of the 20 functions via pointer to achieve your task.
An example is std::transform
in the C++ STL.
Working stuff :
#include <iostream>
#include <vector>
typedef double (*function)(double);
void transformer(std::vector<double>& to_transform, function f)
{
for(auto it = to_transform.begin(); it != to_transform.end(); ++it)
*it = f(*it);
}
void print(const std::vector<double>& v)
{
std::cout << "[ ";
for(double val : v)
std::cout << val << " ";
std::cout << "]" ;
}
double f1(double a) { return a*2; }
double f2(double a) { return a*3; }
double f3(double a) { return a/2; }
double f4(double a) { return a*a*a; }
int main() {
std::vector<double> array = { 2.3, 5.6, 4.5, 7.8, 2.3 };
std::vector<function> function_ptrs = { &f1, &f2, &f3, &f4 };
std::size_t val ;
std::cout << "The original : " ;
print(array);
std::cout << "\nChoose a function (1-4) : ";
std::cin >> val;
std::cout << "The array after applying function " << val << " is : ";
transformer(array, function_ptrs[(val - 1) % function_ptrs.size()]);
print(array);
return 0;
}
I am assuming you have a C++11 compliant compiler. The above code has 4 functions which take in a double and transform it somehow. The transformer
function applies such a function to a vector of doubles. The function pointers are stored in a vector too - Yes an array of function pointers. The functions can be called as a normal element is accessed via indexing. On choosing an option, the appropriate function is called and executed by transformer
element wise on the vector of doubles.
You can further improve it with templates (instead of fixed doubles) and using std::transform
from STL.
C++11 Lambda Expressions
Also, with C++11, you should prefer lambdas and not function pointers. Lambdas are written as
[ ... capture list ... ] ( params ) -> return_type (optional) { body }
A solution with lambda would be something like this :
#include <iostream>
#include <algorithm>
#include <vector>
template <typename T>
void print(const std::vector<T>& v)
{
std::cout << "[ ";
for(T val : v)
std::cout << val << " ";
std::cout << "]" ;
}
int main() {
std::vector<double> array = { 2.3, 5.6, 4.5, 7.8, 2.3 };
std::cout << "The original : " ;
print(array);
std::cout << "\nThe array after transforming : " ;
std::transform(array.begin(), array.end(), array.begin(),
[](double x) { return x * x; });
print(array);
return 0;
}
Function Objects
You can declare your own class which just overloads the ()
operator (which makes the object callable) and does an identical job as a function pointer (can be passed to a function and called) i.e. in this case the class would look like :
class double_the_value
{
double operator()(double val) const { return val * 2.0 ; }
};
double_the_value f ;
std::cout << f(3.0) ; // outputs 6.0
An actual usage would be the std::unordered_map
container where if you are using your own class types for keys, you will need to provide a key hasher - which can be a function object. This is demonstrated in detail by this answer.