NAME
manip - 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 conveni-
ence. 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 sim-
ple, taking no arguments, 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 accordingly defined as macros simulating
templates. The macro IOMANIPdeclare(typ) expands to a com-
plete set of definitions for a manipulator taking one param-
eter 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 argu-
ment 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 declara-
tions:
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 manipula-
tors 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 follows:
o << setw(n)
i >> setw(n)
Sets the field width of stream i or o to n. Note: the
next formatted 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 argu-
ment 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 declara-
tions 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 refer-
ence 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 manipulator (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 ALSO
ios.intro(3CC4), ios(3CC4), istream(3CC4), ostream(3CC4)
C++ Library Reference
Chapter 3, "The Classic iostream Library."