Fixing the Problem

The function wrapper lets you rewrite the program so that it uses just one instantiation of use_f() instead of five. Note that the function pointers, function objects, and lambda expressions in Listing 18.7 share a common behavior—each takes one type double argument and each returns a type double value. We can say that each has the same call signature, which is described by the return type followed by a comma-separated list of parameter types enclosed in a pair of parentheses. Thus, these six examples all have double(double) as the call signature.

The function template, declared in the functional header file, specifies an object in terms of a call signature, and it can be used to wrap a function pointer, function object, or lambda expression having the same call signature. For example, the following declaration creates a function object fdci that takes a char and an int argument and returns type double:

std::function<double(char, int)> fdci;

You can then assign to fdci any function pointer, function object, or lambda expression that takes type char and int arguments and returns type double.

The various callable arguments in Listing 18.7 all have the same call signature – double(double). So to fix Listing 18.7 and reduce the number of instantiations, we can use function<double(double)> to create six wrappers for the six functions, functors, and lambdas. Then all six calls to use_f() can be made with the same type (function<double(double)>) for F, resulting in just one instantiation. Listing 18.8 shows the result.

Listing 18.8. wrapped.cpp


//wrapped.cpp -- using a function wrapper as an argument
#include "somedefs.h"
#include <iostream>
#include <functional>

double dub(double x) {return 2.0*x;}
double square(double x) {return x*x;}

int main()
{
    using std::cout;
    using std::endl;
    using std::function;

    double y = 1.21;
    function<double(double)> ef1 = dub;
    function<double(double)> ef2 = square;
    function<double(double)> ef3 = Fq(10.0);
    function<double(double)> ef4 = Fp(10.0);
    function<double(double)> ef5 =  [](double u) {return u*u;};
    function<double(double)> ef6 =  [](double u) {return u+u/2.0;};
    cout << "Function pointer dub: ";
    cout << "  " << use_f(y, ef1) << endl;
    cout << "Function pointer square: ";
    cout << "  " << use_f(y, ef2) << endl;
    cout << "Function object Fp: ";
    cout << "  " << use_f(y, ef3) << endl;
    cout << "Function object Fq: ";
    cout << "  " << use_f(y, ef4) << endl;
    cout << "Lambda expression 1: ";
    cout << "  " << use_f(y, ef5) << endl;
    cout << "Lambda expression 2: ";
    cout << "  " << use_f(y,ef6) << endl;
    return 0;
}


Here is a sample output:

Function pointer dub:
  use_f count = 1, &count = 0x404020
  2.42
Function pointer sqrt:
  use_f count = 2, &count = 0x404020
  1.1
Function object Fp:
  use_f count = 3, &count = 0x404020
  11.21
Function object Fq:
  use_f count = 4, &count = 0x404020
  12.1
Lambda expression 1:
  use_f count = 5, &count = 0x404020
  1.4641
Lambda expression 2:
  use_f count = 6, &count = 0x404020
  1.815

As you can see from the output, there is just one address for count, and the value of count shows use_f() has been called six times. So we now have just one instantiation invoked six times, reducing the size of the executable code.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.12.232