#include <iostream>

double foo( double d ) { return d*2 ; }
double bar( double d ) { return d/2 ; }

int main()
{
    typedef double F(double); // F is an alias for double(double)
    // ie. a unary function taking a double and returning a double}

    F& fn1 = foo ; // type of 'fn1' is reference to F
    // ie. a reference to a unary function taking a double and returning a double}
    // and it is initialized to refer to foo

    std::cout << fn1(1.234) << '\n' ; // foo(1.234)

    F& fn2 = bar ; // type of 'fn2' is reference to F
    // ie. a reference to a unary function taking a double and returning a double}
    // and it is initialized to refer to bar

    std::cout << fn2(1.234) << '\n' ; // bar(1.234)

    F* pfn = nullptr ; // type of 'pfn' is pointer to F
    // ie. a pointer to a unary function taking a double and returning a double}
    // and it is initialized to be a null pointer

    pfn = &foo ; // pfn now points to foo
    std::cout << (*pfn)(1.234) << '\n' ; // foo(1.234)

    pfn = &bar ; // pfn now points to bar
    std::cout << (*pfn)(1.234) << '\n' ; // bar(1.234)

    // the above two lines can also be written as:
    pfn = bar ; // pfn now points to bar - address of is implied
    std::cout << pfn(1.234) << '\n' ; // bar(1.234) - dereference of pointer is implied
}
