mirror of
https://gitlab.com/fbb-git/cppannotations
synced 2024-11-16 07:48:44 +01:00
43df12533c
git-svn-id: https://cppannotations.svn.sourceforge.net/svnroot/cppannotations/trunk@581 f6dd340e-d3f9-0310-b409-bdd246841980
59 lines
2.8 KiB
Text
59 lines
2.8 KiB
Text
In chapter ref(IOStreams) we saw constructions like tt(cout) lshift() tt(hex)
|
|
lshift() tt(13) lshift() to display the value 13 in hexadecimal format. One
|
|
may wonder by what magic the tt(hex) i(manipulator) accomplishes this. In this
|
|
section the construction of manipulators like tt(hex) is covered.
|
|
|
|
Actually the construction of a manipulator is rather simple. To start, a
|
|
definition of the manipulator is needed. Let's assume we want to create a
|
|
manipulator tt(w10) which sets the i(field width) of the next field to be
|
|
written by the tt(ostream) object to 10. This manipulator is constructed as a
|
|
function. The tt(w10) function needs to know about the tt(ostream) object
|
|
in which the width must be set. By providing the function with an tt(ostream
|
|
&) parameter, it obtains this knowledge. Now that the function knows about the
|
|
tt(ostream) object we're referring to, it can set the width in that object.
|
|
|
|
Next, it must be possible to use the manipulator in an insertion
|
|
sequence. This implies that the i(return value) of the manipulator must be
|
|
a i(reference) to an ti(ostream) object also.
|
|
|
|
From the above considerations we're now able to construct our tt(w10)
|
|
function:
|
|
verbinclude(examples/w10.cc)
|
|
The tt(w10) function can of course be used in a `stand alone' mode, but it
|
|
can also be used as a manipulator. E.g.,
|
|
verbinclude(examples/w10use.cc)
|
|
The tt(w10) function can be used as a manipulator because the tt(class
|
|
ostream) has an overloaded oplshift() accepting a i(pointer to a function)
|
|
expecting an tt(ostream &) and returning an tt(ostream &). Its definition is:
|
|
verb(
|
|
ostream& operator<<(ostream &(*func)(ostream &str))
|
|
{
|
|
return (*func)(*this);
|
|
}
|
|
)
|
|
In addition to the above overloaded oplshift() another one is defined
|
|
verb(
|
|
ostream &operator<<(ios_base &(*func)(ios_base &base))
|
|
{
|
|
(*func)(*this);
|
|
return *this;
|
|
}
|
|
)
|
|
This latter function is used when inserting, e.g., tt(hex) or
|
|
tt(internal).
|
|
|
|
The above procedure does not work for manipulators requiring arguments.
|
|
It is of course possible to overload oplshift() to accept an tt(ostream)
|
|
reference and the address of a function expecting an tt(ostream &) and, e.g.,
|
|
an tt(int), but while the address of such a function may be specified with the
|
|
lshift()-operator, the arguments itself cannot be specified. So, one wonders
|
|
how the following construction has been implemented:
|
|
verb(
|
|
cout << setprecision(3)
|
|
)
|
|
In this case the manipulator is defined as a i(macro). Macro's, however,
|
|
are the realm of the i(preprocessor), and may easily suffer from unwelcome
|
|
side-effects. In bf(C++) programs they should be avoided whenever
|
|
possible. The following section introduces a way to implement manipulators
|
|
requiring arguments without resorting to macros, but using
|
|
hi(manipulator: as objects) anonymous objects.
|