Not for the standard manipulators. But in practice, you probably
shouldn't be using the standard manipulators (other than perhaps as an
example); they correspond to physical markup, and in an application, you
want to use logical markup. You want to write something like
cout << temperature << roomTemperature;
, where temperature is an application specific manipulator, defining
(globally) how temperatures are supposed to be output. That way, if the
specification changes, and requires a different format for temperatures,
you only have to change it in one place. Debugging output is somewhat
of an exception here, but even there, it's much easier to write
something like:
cout << HexFmt( 4 ) << var;
than
cout << hex << setfill( '0' ) << setw( 4 ) << var;
(And you will probably use somthing like HexFmt
often enough to
justify having it in your toolbox.)
Manipulators which you write yourself can be made to restore the
previous state, at least at the end of the full expression. All of my
manipulators derive from the following class:
StateSavingManip.hh:
class StateSavingManip : boost::noncopyable
{
mutable std::ios* myStream;
mutable std::ios::fmtflags
mySavedFlags;
mutable int mySavedPrec;
mutable char mySavedFill;
private:
virtual void setState( std::ios& stream ) const = 0;
protected:
StateSavingManip();
public:
StateSavingManip( StateSavingManip const& other );
virtual ~StateSavingManip();
void operator()( std::ios& stream ) const;
};
inline std::ostream&
operator<<(
std::ostream& out,
StateSavingManip const&
manip )
{
manip( out );
return out;
}
inline std::istream&
operator>>(
std::istream& in,
StateSavingManip const&
manip )
{
manip( in );
return in;
}
StateSavingManip.cc:
namespace {
int getXAlloc();
int ourXAlloc = getXAlloc() + 1;
int
getXAlloc()
{
if ( ourXAlloc == 0 ) {
ourXAlloc = std::ios::xalloc() + 1;
assert( ourXAlloc != 0 );
}
return ourXAlloc - 1;
}
}
StateSavingManip::StateSavingManip()
: myStream( NULL )
{
}
StateSavingManip::StateSavingManip(
StateSavingManip const&
other )
{
assert( other.myStream == NULL );
}
StateSavingManip::~StateSavingManip()
{
if ( myStream != NULL ) {
myStream->flags( mySavedFlags );
myStream->precision( mySavedPrec );
myStream->fill( mySavedFill );
myStream->pword( getXAlloc() ) = NULL;
}
}
void
StateSavingManip::operator()(
std::ios& stream ) const
{
void*& backptr = stream.pword( getXAlloc() );
if ( backptr == NULL ) {
backptr = const_cast< StateSavingManip* >( this );
myStream = &stream;
mySavedFlags = stream.flags();
mySavedPrec = stream.precision();
mySavedFill = stream.fill();
}
setState( stream );
}
Which allows something simple like:
class HexFmt : public StateSavingManip
{
int myWidth;
protected:
virtual void setState( std::ios& targetStream ) const
{
targetStream.flags( std::ios::hex | std::ios::uppercase );
targetStream.width( myWidth );
targetStream.fill( '0' );
}
public:
explicit HexFmt( int width )
: myWidth( width )
{
}
};