不适用于标准机械手。但在实践中,你可能
不应该使用标准的操纵器(除了可能作为
例子);它们对应于物理标记,在应用程序中,您
想使用逻辑标记。你想写类似的东西
cout << temperature << roomTemperature;
,其中温度是特定于应用程序的操纵器,定义
(全球)温度应该如何输出。这样,如果
规格发生变化,并且需要不同的温度格式,
你只需要在一个地方改变它。调试输出有点
这里有一个例外,但即使在那里,写起来也容易得多
类似:
cout << HexFmt( 4 ) << var;
比
cout << hex << setfill( '0' ) << setw( 4 ) << var;
(而且你可能会经常使用像HexFmt 这样的东西来
证明把它放在你的工具箱里是合理的。)
你自己写的操纵器可以用来恢复
先前的状态,至少在完整表达式的末尾。我的所有
操纵器派生自以下类:
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 );
}
这允许一些简单的事情,例如:
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 )
{
}
};