A manipulator is a function object that can be used as an operand to an
input or output operator to manipulate the stream. Manipulators can send
additional output to a stream, read input from a stream, set flags, and
more. For example, to output a zero-padded, hexadecimal integer, you can
use an ostream
's member functions or
manipulators, whichever you prefer. Example 9-7 shows both ways.
Example 9-7. Manipulating an output stream to format a number
using namespace std; // Output a value using ostream's member functions. cout.fill('0'); cout.width(8); cout.setf(ios_base::internal, ios_base::adjustfield); cout.setf(ios_base::hex, ios_base::basefield); cout << value; // Output the same value using manipulators. cout << setfill('0') << setw(8) << hex << internal << value;
The standard library defines several manipulators for setting formatting flags, setting other formatting parameters, skipping whitespace, flushing output, and more. The following is a list of all the standard manipulators, grouped by header:
<ios>
Declares the manipulators that set the formatting flags:
boolalpha
, dec
, fixed
, hex
, internal
, left
, noboolalpha
, noshowbase
, noshowpoint
, noshowpos
, noskipws
, nouppercase
, nounitbuf
, oct
, right
, scientific
, showbase
, showpoint
, showpos
, skipws
, uppercase
, and unitbuf
<istream>
<ostream>
<iomanip>
Declares several additional manipulators: resetioflags
, setioflags
, setbase
, setfill
, setprecision
, and setw
Most manipulators are declared in the same header as the stream
type they manipulate. The only time you need to #include
an additional header is when you
use a manipulator that takes an argument. These manipulators are in
the <iomanip>
header.
To write your own manipulator, use the standard
manipulators as patterns. The easiest to use are manipulators that
take no arguments. A manipulator is simply a function that takes a
stream as an argument and returns the same stream. The standard
streams overload operator<<
and operator>>
to take a
pointer to such a function as an operand.
Suppose you want to write an input manipulator that skips all
characters up to and including a newline. (Perhaps this manipulator is
used by a command processor after reading a //
comment sequence.) Example 9-8 shows one way to write
the skipline
manipulator.
Example 9-8. Skipping a line in an input stream
template<typename charT, typename traits> std::basic_istream<charT,traits>& skipline(std::basic_istream<charT,traits>& in) { charT c; while (in.get(c) && c != '\n') ; return in; } ... int x; std::string next; std::cin >> x >> skipline >> next;
Manipulators that take arguments are harder to write, but only
slightly. You need to write some supporting infrastructure, such as
additional overloaded operator>>
or operator<<
functions.
For example, suppose you want to parameterize your input
skipline
manipulator so it skips
everything up to a caller-supplied character. This manipulator is
defined as a class template, in which the constructor takes the
manipulator's argument, that is, the delimiter character. You must
overload operator>>
so it
recognizes your manipulator as an operand and invokes the
manipulator's operator( )
. You
don't need to use operator( )
, but
this is a good choice when building a reusable infrastructure for
manipulators. Example 9-9
shows the new skip
manipulator.
Example 9-9. Writing a manipulator that takes an argument
template<typename charT> class skipper { public: typedef charT char_type; skipper(char_type delim) : delim_(delim) {} template<typename traits> void operator( )(std::basic_istream<charT,traits>&) const; private: char_type delim_; }; // Skip the rest of the line. The compiler deduces the traits type from the // stream argument. template<typename charT> template<typename traits> void skipper<charT>::operator( )(std::basic_istream<charT,traits>& stream) const { char_type c; while (stream.get(c) && c != delim_) ; } // Invoke the skipper manipulator. template<typename charT, typename traits> std::basic_istream<charT,traits>& const skipper<charT>& f) { f(stream); return stream; } // Let the compiler deduce the character type. template<typename charT> skipper<charT> skip(charT c) { return skipper<charT>(c); } ... int x; std::string next; std::cin >> x >> skip('\n') >> next;