MANIP(3C++)

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 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(3C++), istream(3C++), and ostream(3C++). These are simple, 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 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 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 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 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(3C++), ios(3C++), istream(3C++), ostream(3C++)

C++ 4.1 Library Reference Manual:

Chapter 4, "The Iostream Library."