//  File: fptr4.C
//
//  Exploring function pointers.

#include <iostream.h>
#include <iomanip.h>

// Define a type for pointers to functions that take a void * ptr 
// and returns nothing.

typedef void (* FPTR_TYPE) (void *) ;

// some simple functions

void add3(int *iptr) {
   *iptr = *iptr + 3 ;
}


void add5(double *dptr) {
   *dptr = *dptr + 5.0 ;
}


// Takes a function parameter

void apply (FPTR_TYPE addx, void *rptr) {
   
  addx(rptr) ;
}


main() {
   int m = 2, n = 4 ;
   double x = 5.0 ;
   FPTR_TYPE fptr ;

   cout << "&x = " << &x << endl ;
   cout << "&m = " << &m << endl ;
   cout << "&n = " << &n << endl ;
   cout << endl ;

   add3(&m) ;
   cout << "After add3(&m), m = " << m << endl ;
   add5(&x) ;
   cout << "After add5(&x), x = " << x << endl ;
   cout << endl ;

   apply((FPTR_TYPE) &add3, &m) ; // typecast &add3
   cout << "Applying add3 to m, m = " << m << endl ; 
   apply((FPTR_TYPE) &add5, &x) ;
   cout << "Applying add5 to x, x = " << x << endl ; 
   cout << endl ;

   fptr = (FPTR_TYPE) &add3 ;
   (*fptr) (&m) ; 
   cout << "Applying fptr to m, m = " << m << endl ;
   fptr = (FPTR_TYPE) &add5 ;
   (*fptr) (&x) ; 
   cout << "Applying fptr to x, x = " << x << endl ;

   (*fptr) (&m) ;
   cout << "Applying fptr to m, m = " << m << endl ;
   cout << "n = " << n << endl ;
}
