Reputation: 175
It seems an insertion causes a stream to reset its width to 0. In other words, you need to repeatedly call the width() whenever you want to align your output, which makes me wonder why. I've looked over the c++11 standard and I found a partial answer, which suggests that width(0) is called inside character inserters according to the ISO C++ standard §27.7.3.6.4.1. However, they are just a subset of the inserters, which is not a complete answer. Then, what about arithmetic inserters? I couldn't find any other references that can explain the behavior of streams.
Upvotes: 3
Views: 122
Reputation: 153977
Because that's the way the streams were specified. In an <<
operator,
width
should be reset, the other formatting options no. I can only
guess as to why: presumably, for things like:
std::cout << std::setw(8) << someValue << " cm";
You wouldn't want the width to apply to the string " cm"
, for example.
But you would want to be able to write:
std::cout << std::setw(8) << price << " | " << setw(20) << article;
where article
is a string.
Except that, of course, for that to work, you'd have to also change the justification before the string, and the change in justification would be sticky, affecting the next numeric output.
In practice, of course, experienced programmers don't write this sort of code. They'd use something like:
std::cout << price(column1Width) << article.price
<< " | " << label(column2Width) << article.name;
(supposing that they still had to generate tables using a fixed width
font). Where price
and label
were manipulators which set any number
of format flags, and restored them in their destructor. (Since they are
temporaries, their destructor will be called at the end of the full
expression.) This way, this particular line of code doesn't say
anything about the physical formatting, but rather that the first value
should be formatted as a price, and the second as a label. (And of
course, if someone higher up later decides that prices or labels should
be formatted differently, you just change the manipulators, rather than
searching all of the output statements, and trying to figure out which
are prices, and which aren't.)
EDIT (added references to the standard):
It's important to note that the standard cannot cover everything here,
since most of the time, you'll be using custom operator<<
, written by
the author of the class you're outputting. Most of the built-in
operator<<
are covered by §22.4.2.2.2, in its description of stage 3:
If
str.width()
is nonzero and the number of charT’s in the sequence after stage 2 is less thanstr.width()
, then enough fill characters are added to the sequence at the position indicated for padding to bring the length of the sequence tostr.width()
.
str.width(0)
is called.
For characters and C style strings, this is specified (in much the same
way) in §27.7.3.6.4. For std::string
, see §21.4.8.8.
For std::complex
: the standard defines insertion in terms of other
insertion operators. Any setting of width
will thus affect only the
real element. (Practically speaking, I think we can consider this
broken. When I implemented a pre-standard complex class, my <<
checked the width, and if it was non-zero, subtracted 3 for the
non-numeric fields, then divided by 2 and set it before outputting each
double. I"m not sure that this is right, but it's certainly better than
what the standard specifies. And I also used a semi-colon as separator
if the decimal was a comma, as it is in most places I've lived.)
The fact that the other formatting options remain unchanged is because the standard doesn't specify anything, and additional side effects, other than those specified, are assumed to be forbidden.
In all cases, the specification says that stream.width(0)
is called.
But in the standard, each case is specified separately. There is no
specification (even for intent) of any general rule that I can find.
Traditionally, however, the rule has always been: reset width, and leave
the others unchanged. The principle of least surprise says that you
should do this for user defined <<
(and >>
) as well.
Upvotes: 2