0

Possible Duplicate:
“Roll-Back” or Undo Any Manipulators Applied To A Stream Without Knowing What The Manipulators Were

Consider the following code

int temp=256;
cout<<temp<<endl;
cout<<hex<<temp<<endl;
cout<<temp<<endl;

The output is "256","100" and "100" respectively. Is it possible to make the 'hex' flag non-binding?

I do not wish to write 'dec' explicitly.

Community
  • 1
  • 1
kshenoy
  • 1,726
  • 17
  • 31
  • @MSalters: Only sort of. This one wants it to be done implicitly to save typing; that one wanted _lots_ of stuff to be done and didn't really care about saving typing. Indeed, the solutions to that question are quite elaborate. What I'm saying is, the answers to that question are not appropriate to this question, so can it really be a duplicate? In fact I wish I could take back my closevote now. – Lightness Races in Orbit Sep 15 '11 at 09:10
  • @Tomalak: Naveen's answer there (Boost state saver) is probably as close as you can get. Also, there's an implicit assumption here that he wants the old state back, but what if the old state was `oct` ? That state must be saved to restore it. – MSalters Sep 15 '11 at 09:15
  • @MSalters: The correct answer is "no", and none of those answers say no. These questions are different. – Lightness Races in Orbit Sep 15 '11 at 09:21
  • @Tomalak: If you vote to re-open, I've found its often followed by a bunch of me-too votes to re-open. I can see how this may not be a dup of my question from before. Only Ronin420 can tell us for sure. – John Dibling Sep 15 '11 at 16:40
  • To be honest, I myself had no idea of how huge the scope of this question could be. While the question I had in mind was not similar to the one in the link, most likely due to my lack of knowledge of C++, it has been answered. It's fine to let it remain closed. – kshenoy Sep 16 '11 at 01:55

3 Answers3

2

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 )
    {
    }
};
James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • +1: James, could you please elaborate on why using the standard manipulators is ill-advised in production code? – John Dibling Sep 15 '11 at 16:35
  • @John Dibling I thought I had. Manipulators implement markup; their role is much like that of tags in HTML. And the standard manipulators implement physical markup. Whereas in general, what you want is logical markup: you don't want to specify the precision each time you output, you want to specify the logical role of what you are outputting, and specify the precision for that logical role in one place (and only one place) in your code. – James Kanze Sep 15 '11 at 16:43
1

Use the Boost I/O Streams-State Saver Library:

int temp=256;
cout<<temp<<endl;
{
    boost::io::ios_flags_saver saveflags(cout);
    cout<<hex<<temp<<endl;
}
cout<<temp<<endl;
Fred Foo
  • 355,277
  • 75
  • 744
  • 836
  • 1
    Sure, but if he doesn't want to write `dec` explicitly then I'm sure he doesn't want to do this! – Lightness Races in Orbit Sep 15 '11 at 09:15
  • Well, it makes the `hex` non-binding and there's no explicit `dec`, so I say it fits the spec. Besides, I love this little lib and I promote it at every occasion ;) – Fred Foo Sep 15 '11 at 09:17
  • It fits the word of the question but not the spirit, I'd say ;) – Lightness Races in Orbit Sep 15 '11 at 09:21
  • 1
    Doesn't need the {} : `boost::io::ios_flags_saver(cout), cout< – MSalters Sep 15 '11 at 09:24
  • @MSalters: Ooh that's better. That might actually be considered close to an answer to this question now (though I still think that the spirit of the question is that the OP wants to change how `hex` works to avoid `dec`, not add more complexity to his code). – Lightness Races in Orbit Sep 15 '11 at 09:36
  • @MSalters: nice trick, but I do prefer braces around objects to signify an object is going to be destroyed (and to keep each statement on a line of its own). – Fred Foo Sep 15 '11 at 10:08
0

No. No, it's not. hex sticks.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055