2

How can i make use of flags in c++ streams? I know of ios_base::flags(), but when i cout them or compare them, they dont change values even with a new flag. a simple program:

#include <iostream>
using namespace std;

int main(){
     cout << cout.flags() << endl;//4098
     cout << std::hex << cout.flags() << endl;// 0x1002
     return 0;
}

doesnt change the outputted default value (at least for me) of 4098.

my ultimate goal is to compare the stream to flags to see which are set, NOT TO SET NEW ONES. can anyone show me an example of how to do this?

cppnoob
  • 21
  • 2
  • 3
    I believe this is our old friend [Undefined Behavior and Sequence Points](http://stackoverflow.com/questions/4638364/undefined-behavior-and-sequence-points-reloaded) again. Can someone smart concur? – Benjamin Lindley Jun 09 '11 at 01:04
  • i am not asking why this is happening. i am asking about how to compare flags in cout so that i can use the comparisons in conditions – cppnoob Jun 09 '11 at 01:06
  • @BenjaminLindley: It's not undefined behavior; see my answer. – Fred Nurk Jun 09 '11 at 01:43
  • @Fred Nurk: But it is unspecified, right? – Benjamin Lindley Jun 09 '11 at 01:52
  • 1
    @BenjaminLindley: Yes, and remember unspecified means the implementation doesn't have to either document the behavior or be consistent. – Fred Nurk Jun 09 '11 at 02:27

1 Answers1

2

With this code:

cout << std::hex << cout.flags() << endl;

The compiler is allowed to evaluate it in this order:

ios_base::fmtflags f = cout.flags();  // store value before applying std::hex
cout << hex;
cout << f;
cout << endl;

So you're not guaranteed to "see" flag changes this way. However, it is not Undefined Behavior.

The flags are a "bitmask type", which is defined to have certain properties – the actual type used is implementation-defined, but integers, enums, and std::bitsets are possibilities. You can use the normal bit-manipulation operators: ^, &, |, and ~:

bool is_hex(std::ios_base &s) {
  return (s.flags() & s.basefield) == s.hex;
}
// is_oct is identical, except with s.oct

// Nothing set in basefield means "determine base from input" for istreams,
// and ostreams use base 10.  This makes is_dec harder to write.

bool is_anybase(std::istream &s) {
  return (s.flags() & s.basefield) == 0;
}

bool is_dec(std::istream &s) {
  std::ios_base::fmtflags base = s.flags() & s.basefield;
  return base == dec;
}
bool is_dec(std::ostream &s) {
  std::ios_base::fmtflags base = s.flags() & s.basefield;
  return (base == dec) || (base == 0);
}
// Purposeful overload ambiguity on std::iostream.
// In 0x, we could write:
bool is_dec(std::iostream &s) = delete;

For an example, this is how std::hex works:

std::ios_base& hex(std::ios_base &s) {
  s.setf(s.hex, s.basefield);
  return s;
}

Where setf does:

ios_base::fmtflags fmtflags = s.hex;    // first parameter
ios_base::fmtflags mask = s.basefield;  // second parameter
s.flags((s.flags() & ~mask) | (fmtflags & mask));
Fred Nurk
  • 13,952
  • 4
  • 37
  • 63
  • I think the function only works if *only* the hexflag is set. – Xeo Jun 09 '11 at 01:33
  • @Xeo: That's right, my is_hex gives true if only hex is set, which is how streams work (using the num_get/put facets). – Fred Nurk Jun 09 '11 at 01:35
  • My bad, I didn't exactly know what `basefield` is. :) I thought it's how all the flags are set at default... – Xeo Jun 09 '11 at 01:44
  • 1
    @Xeo there is no hexflag. Unlike most of the values in `fmtflags`, `hex` is a value in a multibit (at least 2) field. – James Kanze Jun 09 '11 at 07:43