Which iomanip manipulators are 'sticky'?
Important notes from the comments below:
By Martin:
@Chareles: Then by this requirement all manipulators are sticky. Except setw which seems to be reset after use.
By Charles:
Exactly! and the only reason that setw appears to behave differently is because there are requirements on formatted output operations to explicitly .width(0) the output stream.
The following is the discussion that lead to the above conclusion:
Looking at the code the following manipulators return an object rather than a stream:
setiosflags
resetiosflags
setbase
setfill
setprecision
setw
This is a common technique to apply an operation to only the next object that is applied to the stream. Unfortunately this does not preclude them from being sticky. Tests indicate that all of them except setw
are sticky.
setiosflags: Sticky
resetiosflags:Sticky
setbase: Sticky
setfill: Sticky
setprecision: Sticky
All the other manipulators return a stream object. Thus any state information they change must be recorded in the stream object and is thus permanent (until another manipulator changes the state). Thus the following manipulators must be Sticky manipulators.
[no]boolalpha
[no]showbase
[no]showpoint
[no]showpos
[no]skipws
[no]unitbuf
[no]uppercase
dec/ hex/ oct
fixed/ scientific
internal/ left/ right
These manipulators actually perform an operation on the stream itself rather than the stream object (Though technically the stream is part of the stream objects state). But I do not believe they affect any other part of the stream objects state.
ws/ endl/ ends/ flush
The conclusion is that setw seems to be the only manipulator on my version that is not sticky.
For Charles a simple trick to affect only the next item in the chain:
Here is an Example how an object can be used to temporaily change the state then put it back by the use of an object:
#include <iostream>
#include <iomanip>
// Private object constructed by the format object PutSquareBracket
struct SquareBracktAroundNextItem
{
SquareBracktAroundNextItem(std::ostream& str)
:m_str(str)
{}
std::ostream& m_str;
};
// New Format Object
struct PutSquareBracket
{};
// Format object passed to stream.
// All it does is return an object that can maintain state away from the
// stream object (so that it is not STICKY)
SquareBracktAroundNextItem operator<<(std::ostream& str,PutSquareBracket const& data)
{
return SquareBracktAroundNextItem(str);
}
// The Non Sticky formatting.
// Here we temporariy set formating to fixed with a precision of 10.
// After the next value is printed we return the stream to the original state
// Then return the stream for normal processing.
template<typename T>
std::ostream& operator<<(SquareBracktAroundNextItem const& bracket,T const& data)
{
std::ios_base::fmtflags flags = bracket.m_str.flags();
std::streamsize currentPrecision = bracket.m_str.precision();
bracket.m_str << '[' << std::fixed << std::setprecision(10) << data << std::setprecision(currentPrecision) << ']';
bracket.m_str.flags(flags);
return bracket.m_str;
}
int main()
{
std::cout << 5.34 << "\n" // Before
<< PutSquareBracket() << 5.34 << "\n" // Temp change settings.
<< 5.34 << "\n"; // After
}
> ./a.out
5.34
[5.3400000000]
5.34
Is There an Official Resource for Sticky Manipulators
Not "official", but cppreference.com says, in std::setw
The width property of the stream will be reset to zero (meaning "unspecified") if any of the following functions are called:
Input
operator>>(basic_istream&, basic_string&)
operator>>(basic_istream&, char*)
Output
Overloads 1-7 of
basic_ostream::operator<<()
(at Stage 3 ofnum_put::put()
) (1-7 are the integer, boolean, and pointer overloads)
operator<<(basic_ostream&, char)
andoperator<<(basic_ostream&, char*)
operator<<(basic_ostream&, basic_string&)
std::put_money
(insidemoney_put::put()
)
std::quoted
(when used with an output stream)
As the edit history in cppreference says, this list was compiled by grepping the standard draft for "width"
All other manipulators are "sticky", as in, the stream state changes they perform persist until explicitly changed again.
How can I make my function sticky for overloaded iostream extraction operators
The width is handled specially: all of the built-in operators will reset the width after outputting an object. The fact that you don't see a corresponding call to width(0)
in the code or the debugger doesn't mean it isn't there! It may be inlined and not hit a breakpoint, for exampke. With respect to the code you'd need to look, e.g., in the implementation of std::num_put<...>
: the actual output operator doesn't include the code but the do_put()
functions do.
To reset other formatting flags you'd need to hook into some operation called after each output operation. There isn't much opportunity, though: the streams din't support generic customization after each object. Below are things which can be done but I would recomment leaving formatting flags sticky. It is arguably a mistake to make the width special:
The numeric formatting is done via the
do_put()
virtual functions instd::num_put<cT>
. These functiins can be overridden and, e.g., do the normal formatting by delegating to the base class implementation, followed by something else.The key problem with this approach in your setting is that it does not work with non-numeric output. For example, outputting strings wouldn't reset anything.
It is possible to set the formatting flag
std::unitbuf
causing a flush after each [correctly written] output operator. The flush is translated into a call ofpubsync()
and eventuallysync()
on the streamsstd::basic_streambuf<cT>
. Thesync()
function can be overridden. That is, the approach would be installing a custom stream buffer and the flagstd::ios_base::unitbuf
when setting up sone flags which sends output to the original stream and on call tosync()
resets flags.Aside from being a bit contrived it has the problem that you can't distinguish a genuine flush from the automatic flush (the primary purpose of
srd::ios_base::unitbuf
is to getstd::cerr
flushed). Also, the reset happens on the firststd::ostream::sentry
being destroyed. For composite values that is most likely after the first portion being formatted.The colour formatter uses a temporary object anyway. The dstructor of this object could be used to reset some fornatting flags. The output operator would set the necessary stream information on the corresponding object when it get "formatted" (probably using a
mutable
member). Of course, this means that setting the format and output need to be done from the same statement. Also, all output on the same statement receives the same format.
I'm not aware of any other approach to deal with formatting after some output. None of the approaches works particular well. I'd rather use a guard-like approach to set/unset flags than trying to be clever.
iomanip / fixed width persistence
Unfortunately you've wandered into one of the areas of the standard that's a little archaic and seemingly without any overarching design goals.
This is undoubtedly historic as the iostreams library AFAIAA, was not originally part of the STL which is what became the standard library.
It's worth reading the notes on all std::ios_base
members and the associated manipulators.
For example:
http://en.cppreference.com/w/cpp/io/ios_base/width
Some I/O functions call width(0) before returning, see std::setw (this results in this field having effect on the next I/O function only, and not on any subsequent I/O)
The exact effects this modifier has on the input and output vary between the individual I/O functions and are described at each operator<< and operator>> overload page individually.
Anticipating:
But that's just <insert expletive>!!!
A: yup.
CPP Setfill() repeats itself in second and other steps of for loop
std::setfill
is a "sticky" manipulator: it will change the state of the ostream
until it is reverted.
If you revert it after you print your first number, you will get the expected output:
for (i; i < 10; i++) {
for (j = 1; j < 10; j++)
cout << setw(3) << i*j << setfill(' ');
cout << endl << setw(3) << setfill('x');
}
live example on wandbox.org
Having trouble with iomanip, columns not lining up the way I expect
It doesn't work as you think. std::setw
sets the width of the field only for the next insertion (i.e., it is not "sticky").
Try something like this instead:
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
cout << "Student Grade Summary\n";
cout << "---------------------\n\n";
cout << "BIOLOGY CLASS\n\n";
cout << left << setw(42) << "Student" // left is a sticky manipulator
<< setw(8) << "Final" << setw(6) << "Final"
<< "Letter" << "\n";
cout << setw(42) << "Name"
<< setw(8) << "Exam" << setw(6) << "Avg"
<< "Grade" << "\n";
cout << setw(62) << setfill('-') << "";
cout << setfill(' ') << "\n";
cout << setw(42) << "bill joeyyyyyyy"
<< setw(8) << "89" << setw(6) << "21.00"
<< "43" << "\n";
cout << setw(42) << "Bob James"
<< setw(8) << "89" << setw(6) << "21.00"
<< "43" << "\n";
}
Also related: What's the deal with setw()?
C++ setiosflags function manipulator - undetermined indentation
std::ios::left
tells to add fill characters to the right, i.e. it adds few characters to first string, so "Mathieu\n"
"becomes" "Mathieu\n "
. There is new line character at the end ('\n'
), so added spaces are moved to next line (Gauthier
). So it's not indentation of second line, those are trailing characters from first.
Related Topics
How to Iterate Through Every File/Directory Recursively in Standard C++
How to Debug Heap Corruption Errors
Why Does a Large Local Array Crash My Program, But a Global One Doesn'T
Why Does Subtracting '0' in C Result in the Number That the Char Is Representing
To_String Is Not a Member of Std, Says G++ (Mingw)
How to Specify a Pointer to an Overloaded Function
Difference Between Char A[] = String; and Char *P = String;
How to Use Cout ≪≪ Myclass
How to Mix Swift With C++? Like the Objective-C .Mm Files
C++ Cross-Platform High-Resolution Timer
How to Convert an Enum Type Variable to a String
Splitting Templated C++ Classes into .Hpp/.Cpp Files - Is It Possible
How Are Virtual Functions and Vtable Implemented
Why Does Rand() Yield the Same Sequence of Numbers on Every Run