Callback

Callbacks appear frequently in some problem domains. Some typical examples are:

In C, this is usually done with a pointer-to-function argument.

double Integrate(double a, double b, int numSamplePoints,
                 double (*Function)(double) )
{
  double delta = (b-a) / (numSamplePoints - 1);
  double sum = 0.0;
  for (int i=0; i<numSamplePoints; i++)
    sum += Function(a + i*delta);
  return sum * (b-a) / numSamplePoints;
}
This approach works fine, except for performance: the function calls in the inner loop cause poor performance. Some optimizing compilers may perform inter-procedural and points-to analysis to determine the exact function which f points to, but most compilers do not.

In C++, callbacks were mostly replaced by virtual functions. The newer style is to have a base class, such as Integrator, with the function to be integrated supplied by subclassing and defining a virtual function.

class Integrator {
public:
  double integrate(double a, double b, int numSamplePoints) {
    double delta = (b-a) / (numSamplePoints - 1);
    double sum = 0.0;
    for (int i=0; i<numSamplePoints; i++)
      sum += FunctionToIntegrate(a + i*delta);
    return sum * (b-a) / numSamplePoints;
  }
  virtual double FunctionToIntegrate(double x) = 0;
};

class IntegrateMyFunction : public Integrator {
public:
  virtual double FunctionToIntegrate(double x) {
    return cos(x);
  }
};

As with C, the virtual function dispatch in the inner loop will cause poor performance. (An exception is if evaluating FunctionToIntegrate() is very expensive, then the overhead of the virtual function dispatch is negligible.) For good performance, it is necessary to inline the callback function into the integration routine.

Pointer-to-function as a template parameter
double Function(double x)
{
  return 1.0 / (1.0 + x);
}

template<double TFunction(double)>
double Integrate(double a, double b, int numSamplePoints)
{
  double delta = (b-a) / (numSamplePoints - 1);
  double sum = 0.0;
  for (int i=0; i<numSamplePoints; i++)
    sum += TFunction(a + i*delta);
  return sum * (b-a) / numSamplePoints;
}

// usage in application
Integrate<Function>(1.0, 2.0, 100);
Index