This constructor of the x template prints a multiplication table of six rows and six columns, for example:
0 0 0 0 0 0
0 1 2 3 4 5
0 2 4 6 8 10
0 3 6 9 12 15
0 4 8 12 16 20
0 5 10 15 20 25
To understand how this works, we'll first examine the template function g(size,op,sep). op is a function object. The function object is "called" with the first size integers (starting at 0) and the results printed (separated by the string specified by the optional sep argument). We use this function twice.
The first call is in the template function x. It calls g, passing size and an object of type w<op,size>. For our example, this will call g(6,w<multiplies<int>,6>,""), which will cause the following invocations to occur:
w<'multiplies<int>,6>::operator()(0); //rownum = 0
w<multiplies<int>,6>::operator()(1); //rownum = 1
w<multiplies<int>,6>::operator()(5); //rownum = 5
Each of these constructors prints a single row of the table. It does this by creating a new function object
where rownum is the row being printed. This binder1st object is passed to g(), which invokes operator() on the object for each of the integers from 0 to size-1. This prints a single row of the table, using a tab as the separator argument.
binder1st is a standard template class defined in the <functional> header. It takes a binary function object (in this case, multiplies<int>) and a single operand, and creates a new unary function object that "binds" the operand as the first operand of the binary function. This resulting object is invoked by calling operator(), passing a single operand. operator() returns the result of applying the original binary function to the "bound" operand and the operand supplied at the call.
In our example, the row index is "bound" as the first operand. For each column, the invocation of the binder1st object invokes multiplies<int>(int,int), passing the row and column indices respectively; the result is printed by g.
For bonus credit: Explain how the newline at the end of each row is printed.
Parameterizing the operation as a function object allows us to generate tables for other operations. For instance, x<plus<int>,4>() gives us:
0 1 2 3
1 2 3 4
2 3 4 5
3 4 5 6