Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do stream manipulators with arguments work?

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;
like image 943
ubbdd Avatar asked Oct 28 '11 21:10

ubbdd


People also ask

What are stream manipulators used for?

Manipulators are special functions that can be included in the I/O statement to alter the format parameters of a stream. Manipulators are operators that are used to format the data display. To access manipulators, the file iomanip.

What is a parameterized stream manipulator?

A manipulator with a parameter is an object that can be inserted into or extracted from a stream in an expression like: std::cout << Manip(x); std::cin >> Manip(x); Manip(x) must be an object of type manipT , for which the shift operators are overloaded.

What is stream manipulation?

Streaming fraud (also known as streaming manipulation, abnormal store-end behavior, fraudulent store-end behavior, or store-end fraud) is the act of artificially inflating your views, streams, follows, and sales, in order to generate revenue or manipulate your release's popularity in the charts, on playlists, or in ...

Is Setfill a parameterized stream manipulator?

setfill (near the bottom of the iomanip. h header file) is an example of a parameterized manipulator. You can create your own parameterized manipulators and your own simple manipulators.


1 Answers

setprecision(4)

calls

inline smanip setprecision(int n){
    return smanip(set_precision,n);
}

Which creates an smanip from a pointer to the set_precision function, and n.

struct smanip{
    ios_base& (*f) (ios_base&, int);
    int i;
    smanip(ios_base& (*ff)(ios_base&, int), int ii) : f(ff), i(ii){}
};

smanip is a struct that holds a pointer to a function, and an integer. That function takes an ios_base by reference and an int, and returns the ios_base by reference.

At this point the line is effectively like this:

smanip m(&setprecision, 4);
cout << m << (otherstuff);

which matches this template:

template<class Ch, class Tr>
ostream<Ch, Tr>& operator<<(ostream<Ch, Tr>& os, smanip& m){
    return m.f(os, m.i);
}

And the compiler can deduce Ch, and Tr from the stream on the left side. In this case, std::cout. The code executes m.f(os, m.i). This calls the function pointer held by the smanip, passing it the stream and the integer held by smanip.

ios_base& set_precision(ios_base& s, int n){
    return s.setprecision(n); // call the member function
}

This calls cout.setprecision(n).

So the line translates to:

std::cout.setprecision(4) << angle;
like image 134
Mooing Duck Avatar answered Oct 11 '22 05:10

Mooing Duck