MANIP(3CC4)MANIP(3CC4)NAMEmanip - iostream manipulators
SYNOPSIS
#include <iostream.h>
#include <iomanip.h>
#define IOMANIPdeclare(typ) expands to the following definitions ...
class SMANIP(typ) {
public:
SMANIP(typ)(ios& (*)(ios&, typ), typ);
friend istream& operator>>(istream&, SMANIP(typ)&);
friend ostream& operator<<(ostream&, SMANIP(typ)&);
};
class SAPP(typ) {
public:
SAPP(typ)(ios& (*)(ios&, typ));
SMANIP(typ)operator()(typ);
};
class IMANIP(typ) {
public:
IMANIP(typ)(istream& (*)(istream&, typ), typ);
friend istream& operator>>(istream&, IMANIP(typ)&);
};
class IAPP(typ) {
public:
IAPP(typ)(istream& (*)(istream&, typ));
IMANIP(typ)operator()(typ);
};
class OMANIP(typ) {
public:
OMANIP(typ)(ostream& (*)(ostream&, typ), typ);
friend ostream& operator<<(ostream&, OMANIP(typ)&);
};
class OAPP(typ) {
public:
OAPP(typ)(ostream& (*)(ostream&, typ));
OMANIP(typ)operator()(typ);
};
class IOMANIP(typ) {
public:
IOMANIP(typ)(iostream& (*)(iostream&, typ), typ);
friend istream& operator>>(iostream&, IOMANIP(typ)&);
friend ostream& operator<<(iostream&, IOMANIP(typ)&);
};
class IOAPP(typ) {
public:
IOAPP(typ)(iostream& (*)(iostream&, typ));
IOMANIP(typ)operator()(typ);
};
IOMANIPdeclare(int);
IOMANIPdeclare(long);
smanip_long resetiosflags(long);
smanip_int setbase(int);
smanip_int setfill(int);
smanip_long setiosflags(long);
smanip_int setprecision(int);
smanip_int setw(int);
DESCRIPTION
A manipulator appears to be an object inserted or extracted into a
stream, but many only change the state of the stream. Their purpose is
to embed what is really a function call into a sequence of insertions
or extractions as a convenience. For example, instead of writing:
cout.width(8);
cout << val1 << " ";
cout.width(4);
cout << val2 << '\n';
cout.flush();
we can write:
cout << setw(8) << val1 << " " << setw(4) << val2 << endl;
There are several predefined manipulators described in ios(3CC4),
istream(3CC4), and ostream(3CC4). These are simple, taking no argu‐
ments, such as endl as used above, or flush. Manipulators may also
take arguments, such as setw as used above, or setfill. The header
file <iomanip.h> defines some of these manipulators, and also provides
the definitions necessary for you to create your own.
Manipulators are logically defined as templates, but were introduced
before templates were available in the C++ language. They are accord‐
ingly defined as macros simulating templates. The macro IOMANIPde‐
clare(typ) expands to a complete set of definitions for a manipulator
taking one parameter of type typ. Due to the nature of the macros, the
type parameter must be a simple type name (just an identifier). The
header provides the expanded definitions for types int and long.
Simple manipulators
A manipulator without arguments is a function with one parameter of
type reference to stream, and which returns the same type. The streams
have predefined overloaded operators which take such a function as a
parameter. The manipulator performs whatever operations are necessary
on the stream argument, then returns the same stream. For example,
here is code for a tab manipulator:
ostream& tab(ostream& s)
{
s << '\t';
return s;
}
In the expression cout<<tab, the overloaded operator
ostream& operator<< (ostream& (*)(ostream&))
is selected, which just calls the manipulator function. The resulting
call inserts a tab character into the ostream.
Parameterized manipulators
A manipulator with a parameter has two parts:
- a manip part: a function taking a stream and a typ argument and
returning the stream;
- an apply part: the function invoked by the manip part which applies
state changes or other operations.
For a given type typ, all the parts are declared by the IOMANIPdeclare
macro. These are described below.
In the following discussions, assume the following declarations:
typ - some type name
n - an int
l - a long
s - an ios
i - an istream
o - an ostream
io - an iostream
f - an ios& (*) (ios&)
if - an istream& (*) (istream&)
of - an ostream& (*) (ostream&)
iof - an iostream& (*) (iostream&)
s << SMANIP(typ)(f, t)
s << SAPP(typ)(f)(t)
s >> SMANIP(typ)(f, t)
s >> SAPP(typ)(f)(t)
Returns f(s,t). The stream s could also be any of the other
stream types i, o, or io.
i >> IMANIP(typ)(if, t)
i >> IAPP(typ)(if)(t)
Returns if(i,t).
o << OMANIP(typ)(of, t)
o << OAPP(typ)(of)(t)
Returns of(o,t).
io << IOMANIP(typ)(iof, t)
io << IOAPP(typ)(iof)(t)
io >> IOMANIP(typ)(iof, t)
io >> IOAPP(typ)(iof)(t)
Returns iof(io,t).
The <iomanip.h> header contains declarations for manipulators taking an
int or a long argument (typ in the above presentation). The predefined
manipulators are all used for changing the state of a stream, as fol‐
lows:
o << setw(n)
i >> setw(n)
Sets the field width of stream i or o to n. Note: the next for‐
matted insertion or extraction resets the width to 0.
o << setfill(n)
i >> setfill(n)
Sets the fill character of stream i or o to n.
o << setprecision(n)
i >> setprecision(n)
Sets the precision variable of stream i or o to n.
o << setiosflags(l)
i >> setiosflags(l)
Turns on the ios flags of stream i or o which are set in l.
o << resetiosflags(l)
i >> resetiosflags(l)
Turns off the ios flags of stream i or o which are set in l.
To write your own parameterized manipulator you need to declare the
manip function, then implement both the manip and apply functions. If
the manipulator is to take an argument of type typ, declare the manip
function to take one argument of that type, and to return an object of
type Xmanip_typ. Replace X with one of s, i, o, or io, if it is
intended to manipulate objects of type ios, istream, ostream, or
iostream, respectively. Replace typ with the actual type name. For
types int and long, all the declarations are already in place. For
other types, you need to invoke the ``template'' IOMANIPdeclare(typ).
The apply function is usually static, since it is only called by the
manip function. Define it to return a reference to the type of stream
to be manipulated, to have a first parameter of that same type, and a
second of type typ.
For example, consider the setiosflags manipulator. The manipulator
operates on an ios, and takes a long parameter, so it is declared to
return type smanip_long. If it operated on an ostream and took an int
parameter, it would be declared to return type omanip_int. The manipu‐
lator (the manip function) is therefore declared in the header like
this:
smanip_long setiosflags(long);
The apply function does not appear in the header, since it is never
called directly by user code. The code for both functions appears in
the implementation module:
// set the flags bitvector according to the bits set in b
static ios& sios(ios& i, long b) // private apply function
{
i.setf(b);
return i;
}
smanip_long setiosflags(long b) // public manip function
{
return smanip_long(sios, b);
}
SEE ALSOios.intro(3CC4), ios(3CC4), istream(3CC4), ostream(3CC4)
C++ Library Reference
Chapter 3, "The Classic iostream Library."