One the second ISO C++ 11 standard (ISO/IEC 14882-2011(E)), section 27.5.3.1.2, we have the description of the streams formatting flags type, std::ios_base::fmtflags, which builds on a bitmask type (section 17.5.2.13), which is an enumerated type (section 7.2), which is a compound type (section 3.9.2), and so on...
Among other things, this means that, as a bitmask, it has most (if not all) the well-defined bit operations one might expect. But the problem is that this not speak aloud as it should be, which may cause some confusion or obfuscation, resulting in much less than optimal utilization of the feature. This is one is just one out of several other similar situation appearing to establish a mild kind of obscurantism that do not help in getting the most out of the streams framework, which is very nice, flexible and powerful.
So the formatting flags are just a bunch of bits each of which signaling a certain formatting behavior on a corresponding stream. Although defined on a "primarily" base type, those bits could be better perceived as a formatting state attribute of each stream instance. The bits (which I do not repeat the well-known meanings) are (alphabetically, per column):
boolalpha left showpoint
dec oct showpos
fixed right skipws
hex scientific unitbuf
internal showbase uppercase
As a kind of state, they can be "queried", "saved", "set" and "reset" and that's the point on getting the most out of them. Unfortunately, it's not very clearly stated how to make a "master reset" (revert to defaults), but from inspecting the fragments of documentation and examples excerpts one could infer that the default seems to be an "all clear", that is, all bits set to 0 (zero), or yet, more precisely, the value std::ios_base::fmtflags(0). But that's not actually the case! On the standard, table 128, among other things, the effects of std::basic_ios::init() sets up the following:
skipws | dec
Another point to note is that some of these bits are grouped according to mutually exclusive functionality bits. This "grouping" (called a field) is nothing more than referring to them as a whole by means of a predefined (bit) mask which ORes each bit value that is to comprise the mask. The masks are:
adjustfield meaning left | right | internal
basefield meaning dec | oct | hex
floatfield meaning scientific | fixed
The manipulation of these flags can be grouped into 2 main scenarios:
- Directly, by calling a stream member function;
- Indirectly, by using manipulators on a "flow statement".
The second scenario above is by far the most usual as it's more intuitive and "right-to-the-point". But due to the intrinsic behavior of the formatting flags in the stream framework, the first scenario is crucial to internationalization, house-keeping, clean-coding and reassuring expected and bug-free behavior.
The member functions for the first scenario (defined in std::ios_base, section 27.5.3) are:
fmtflags flags () const;
fmtflags flags ( fmtflags fmtfl ); // Replaces ALL
fmtflags setf ( fmtflags fmtfl ); // Sets SOME
fmtflags setf ( fmtflags fmtfl, fmtflags mask );
void unsetf ( fmtflags mask ); // Clears MASK
In the above declarations, strictly speaking, fmtfl in fact is also a mask of flags to be set. It's important to note how each of these member functions does one or more of the following operations (and in what order):
- Replaces all flags (with "mask" of flags)
- Sets some flags (adds a "mask" of flags)
- Clears (unsets) the flags in a mask (but may keep some)
In particular, the second (overloaded) setf() starts by unconditionally clearing the flags comprising mask and then sets the flags in fmtfl but only if they correspond to some position in mask. This effectively means that the fmtfl "mask" may include some flags to be kept from clearing after all.
The stream manipulators for the second scenario have differentiated implementations for the case when they belong to a group (field) of mutually exclusive members, in that enabling one bit member automatically disables all other bit members. Those bits that don't belong to any group (field) have both a set and a corresponding unset (no) manipulator. Here are they all:
(no)boolalpha (no)showpos (no)uppercase (no)showbase (no)skipws (no)showpoint (no)unitbuf
Typically implemented as:
boolalpha translating to setf( boolalpha )
noboolalpha translating to unsetf( boolalpha )
...
And the group (field) related ones:
adjustfield basefield floatfield
left dec scientific
right oct fixed
internal hex hexfloat ( scientific | fixed )
Typically implemented as:
right translating to setf( right, adjustfield )
...
Interestingly, there is one extra manipulator for handling the basefield. It takes 1 (one) parameter, and the problem is that an invalid parameter sets all bits in the group (field) to 0 (zero) which may be unexpected. It is the:
setbase ()
Furthermore, there are two more manipulators supposed to more freely manage (set or clear) any flags (individually or combined on any "mask") independently of any grouping. They are:
setiosflags ()
resetiosflags ()
One other important point to note is that the formatting flags do not control some formatting details such as width, filling (padding) and float number precision to be used. The filler, for instance, is dependent on the character traits. The member functions that deal with each of these extra formatting options appear in std::basic_ios which is derived from std::ios_base. They (those extra formatting options) also get initial defaults set by std::basic_ios::init() as following:
width () defaults to 0
precision () defaults to 6
fill () defaults to widen( ' ' )
And there are manipulators (taking 1 parameter) for each of the above member functions as well:
setw ()
setprecision ()
setfill ()
For completeness, there's just another member function:
std::basic_ios::copyfmt()This function is very handy in more advanced scenarios for copying the complete set of formatting related options between streams. The more advanced settings are those returned related to tie(), exceptions() and getloc(). The more obvious options are, of course, the ones discussed on this post:
flags ()
width ()
precision ()
fill ()
And there newer manipulators for money (get_money/put_money) and time (get_time/put_time) I won't cover now, as they are relatively more complex for this introduction.
To finish this story I'll show the bit values of the formatting flags under the implementation of GCC 4.8.2 under Solaris 11.3 (X86):
default flags: 0x00001002
boolalpha: 0x00000001
dec: 0x00000002
fixed: 0x00000004
hex: 0x00000008
internal: 0x00000010
left: 0x00000020
oct: 0x00000040
right: 0x00000080
scientific: 0x00000100
showbase: 0x00000200
showpoint: 0x00000400
showpos: 0x00000800
skipws: 0x00001000
unitbuf: 0x00002000
uppercase: 0x00004000
adjustfield: 0x000000B0 = internal | left | right
basefield: 0x0000004A = dec | hex | oct
floatfield: 0x00000104 = fixed | scientific
By the way, in my implementation, assuming the defaults, the lines:
std::cout.unsetf( std::ios_base::dec )will output:
std::cout << 11 << std::end;
B