In Stroustrup's C++ book, there is an example of a custom manipulator taking an argument (pls see the attached code). I am confused about how the struct is created. In particular, it looks like there are two int arguments for the constructor of "smanip", one for the function pointer "ff", one for "ii". I don't understand how the int argument is passed to create the structure by using:
cout << setprecision(4) << angle;
In addition, what is the order these functions get called, and how the the type arguments Ch and Tr are determined? Thanks a lot.
// manipulator taking arguments
struct smanip{
iso_base& (*f) (ios_base&, int);
int i;
smanip(ios_base& (*ff)(ios_base&, int), int ii) : f(ff), i(ii){}
};
template<cladd Ch, class Tr>
ostream<Ch, Tr>& operator<<(ostream<Ch, Tr>& os, smanip& m){
return m.f(os, m.i);
}
ios_base& set_precision(ios_base& s, int n){
return s.setprecision(n); // call the member function
}
inline smanip setprecision(int n){
return smanip(set_precision,n);
}
// usage:
cout << setprecision(4) << angle;
The manipulator functor takes a function pointer and an int as arguments, and it stores both internally for later use. The signature of the constructor can be split in this two declarations for readability:
That is, the first argument is the function pointer and the second is the value.
As of the order of execution in the example code, first the function
setprecision
is called, that function stores the function pointer and value inside thesmanip
object and returns it. The object is passed to the appropriateoperator<<
, that extracts and executes the stored function pointer on the current stream passing the argument.calls
Which creates an
smanip
from a pointer to theset_precision
function, andn
.smanip
is a struct that holds a pointer to a function, and an integer. That function takes anios_base
by reference and anint
, and returns theios_base
by reference.At this point the line is effectively like this:
which matches this template:
And the compiler can deduce
Ch
, andTr
from the stream on the left side. In this case,std::cout
. The code executesm.f(os, m.i)
. This calls the function pointer held by thesmanip
, passing it the stream and the integer held bysmanip
.This calls
cout.setprecision(n)
.So the line translates to: