Link to home
Start Free TrialLog in
Avatar of jdpipe
jdpipeFlag for Australia

asked on

Adding new flags to control an ostream

Hi all

I have a nice class for tracking units-of-measure along with numerical values.

I have a simple output method accompanying this class which I can use to make the units show whenever a value is outputted to an ostream, as shown below.

My question: instead of using the ios_base::showbase flag (which is really intended for something completely different), can I create a new flag that is guaranteed to work on all platforms, that won't clash with existing flags, and which can safely be set with the 'stream.flags()' method?

What would be the model approach here?

Any suggestions appreciated.

JP

---------------------8<------------------

#define DEFINE_OUTPUT_METHOD(MM,LL,TT,KK,II,UNITS) \
            inline \
            std::ostream& operator <<(std::ostream &os,const Units<MM,LL,TT,KK,II> &u){ \
                  double d = *reinterpret_cast<const double*>(&u); \
                  os << d; \
                  os.flags() & std::ios_base::showbase && os << " " << UNITS; \
                  return os; \
            }

DEFINE_OUTPUT_METHOD(0, 1, 0, 0, 0, "m");
DEFINE_OUTPUT_METHOD(0, 0, 1, 0, 0, "s");
DEFINE_OUTPUT_METHOD(0, 1, -1, 0, 0, "m/s");
Avatar of jdpipe
jdpipe
Flag of Australia image

ASKER

To clarify, this is how I use the above:

  Length L=5 * metre;
  cerr.flags(ios_base::showbase);
  cerr << "The car's length is "  << L << endl;

This would output:

  The car's length is 5 m
Avatar of Member_2_1001466
Member_2_1001466

My approach would be to control the output of that class. Set a flag of that class and overwrite the <<operator () of that class to modify the oputput to your needs. Don't touch the well tested stream classes.
So your code should look like
Length L = 5, "metre";
L.flag (showunit);
cout << The car's length is " << L << endl;
ASKER CERTIFIED SOLUTION
Avatar of rstaveley
rstaveley
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of jdpipe

ASKER

Thanks for the tips you guys...

STeH, this units class which I have needs to add zero overhead to storage and arithmetic operations, so I don't think that I can use a flag on top of the Units class, unless you had some clever way of doing it with static variables or something... But even then, I might want units being output in one stream, but not in another. For example, if I have a console window with some live results, showing units, but also afile with some tab-separated values. I would want both streams to keep their correct settings.

rstaveley, that stuff looks pretty good. I'm not familiar with xalloc and iword, I'll read up on those, check out your code, and get back to you.

Thanks again
JP
> // A manipulator to set the verbosity level

That stray comment, which shouldn't be there, was left over from the facility for which I last used xalloc/iword. I had a flag which I put into the output stream to specify the verbosity of my debug.

I dug this stuff out of Standard C++ IOStreams and Locales by Langer and Kreft, which is worth flipping through, if you've got access to a library.
Actuall, i don't know why you are using 'showbase' flag:

I compiled using

#define DEFINE_OUTPUT_METHOD(MM,LL,TT,KK,II,UNITS) \
          inline \
          std::ostream& operator <<(std::ostream &os,const Units<MM,LL,TT,KK,II> &u){ \
               double d = *reinterpret_cast<const double*>(&u); \
               os << d; \
               /*os.flags() & std::ios_base::showbase && */os << " " << UNITS; \
               return os; \
          }

DEFINE_OUTPUT_METHOD(0, 1, 0, 0, 0, "m");
DEFINE_OUTPUT_METHOD(0, 0, 1, 0, 0, "s");
DEFINE_OUTPUT_METHOD(0, 1, -1, 0, 0, "m/s");

          Velocity v = 60. * kilometre / hour;
         
          Length x = 250. * kilometre;
         
          Time t = x / v;
          Length z = metre + metre;
          Units<0, 0, 0, 0, 0> unitless = 123.4;
          z = unitless * z;

          cerr << "The time taken to travel " << x << " at speed " << v << " is " << t << endl;
            // cerr.flags(ios_base::showbase);
            cerr << "The car's length is "  << z << endl;

not using any flag, and the output was fine:

The time taken to travel 250000 m at speed 16.6667 m/s is 15000 s
The car's length is 2 m

Regards, Alex
Avatar of jdpipe

ASKER

The idea here is to be able to safely define a flag which can be used to turn on and off the display of units. I originally thought I would dodgily re-use the 'showbase' flag usually reserved (I think) for showing 0x (or whatever it is) at the start of binary values.

I think rstaveley's approach with 'iword' is going to be the right one.

JP
I vote for rstaveley's approach too ;-)
I also, though that below looks simpler and runs on my VC6 system:

enum { showunit = ios_base::showbase };

#define DEFINE_OUTPUT_METHOD(MM,LL,TT,KK,II,UNITS) \
          inline \
          std::ostream& operator <<(std::ostream &os,const Units<MM,LL,TT,KK,II> &u){ \
               double d = *reinterpret_cast<const double*>(&u); \
               os << d; \
               os.flags() & showunit && os << " " << UNITS; \
               return os; \
          }

DEFINE_OUTPUT_METHOD(0, 1, 0, 0, 0, "m");
DEFINE_OUTPUT_METHOD(0, 0, 1, 0, 0, "s");
DEFINE_OUTPUT_METHOD(0, 1, -1, 0, 0, "m/s");


int main(int argc, char *argv[]){
   
     Velocity v = 60. * kilometre / hour;
     Length x = 250. * kilometre;
     Time t = x / v;
     Length z = metre + metre;
     Units<0, 0, 0, 0, 0> unitless = 123.4;
     z = unitless * z;
     cerr << "The time taken to travel " << x << " at speed " << v << " is " << t << endl;
 
     cerr.flags(showunit);
     cerr << "The car's length is "  << z << endl;
         
     return 0;
}

Regards, Alex
The reason why the above works is:

// extract from xiosbase header

        enum _Fmtflags {skipws = 0x0001, unitbuf = 0x0002,
                uppercase = 0x0004, showbase = 0x0008,
                showpoint = 0x0010, showpos = 0x0020,
                left = 0x0040, right = 0x0080, internal = 0x0100,
                dec = 0x0200, oct = 0x0400, hex = 0x0800,
                scientific = 0x1000, fixed = 0x2000, boolalpha = 0x4000,
                adjustfield = 0x01c0, basefield = 0x0e00,
                floatfield = 0x3000, _Fmtmask = 0x7fff, _Fmtzero = 0};
         ...
        _BITMASK(_Fmtflags, fmtflags);  // ==> typedef int fmtflags;
         ...
         fmtflags flags(fmtflags _Nf)
         {fmtflags _Of = _Fmtfl;
           _Fmtfl = _Nf & _Fmtmask;
           return (_Of); }


By switching on and off just before and after Units elements, you could avoid influences on other output elements:

      cerr << "The time taken to travel " 
            << setiosflags(showunit) << x  << resetiosflags(showunit)
           << " at speed " << v << " is " << t << endl;

gives the following output:

The time taken to travel 250000 m at speed 16.6667 is 15000

Regards, Alex
Why not derive yourself a class from ostream, add the new flag in the derived class, and let everything else pass-through to the base class?
Avatar of jdpipe

ASKER

Would that work, guitaristx?

I don't want to have to change the stream I'm outputting to; I want to be able to write

stringstream s;
s << displayunits << length << endl;

and

cerr << displayunits << speed << endl;

So I wouldn't have thought I'd want to overload the stream classes...

JP
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
If it was me implementing it, I would:

create a function:

void displayunits(void)
{
     if(app_globals::disp_units == true) app_globals::disp_units = false;
     else app_globals::disp_units == true;
}

And another so that you can use it:

ostream& operator <<(ostream& out, void (*func)(void) )
{
     func();
     return out;
}

Then, create output operators for all the types that you want to assign units to:

ostream& operator<<(ostream& out, const myType&obj)
{
     if(app_globals::disp_units)
     {
            //display with units
            out << obj.value << " " << obj.units;
     }
      else
      {
            //display without units
            out << obj.value;
      }

       return out;
}

There are some assumptions; one being that you've created an output operator for your "units" type.  This would be the easiest way, IMHO.  You might create disp_units as a public static member of your units class.
Avatar of jdpipe

ASKER

Guitaristx

The units class I'm using here is one modified from http://www.embedded.com/shared/printableArticle.jhtml?articleID=9900094
you can see the code in current form at

http://cvs.sourceforge.net/viewcvs.py/freesteam/freesteam/units.h?rev=1.9&view=markup

The aim is to have zero runtime overhead on the units class. It's purely template related stuff which creates the output operator. Therefore there is no 'obj.units'.

Also, I want the display of units to be individually switched per stream. So I can have one stream open with units being written out, and another with no units being written.

JP
Wow....

Okay, after looking at your code, I'm going to recommend my original suggestion - overload the ostream class.  However, you may run into problems, since by overloading the class, you're making a subclass of ostream.  This being said, most people don't use ostream, they use subclasses of it (ofstream, ostringstream, etc).

What I'm thinking is something like this (and, unfortunately, you'll have to make overloads for all of the ostream-derived classes that you want to use, unless you want to get into multiple-inheritance):

class myofstream : public ofstream
{
protected:
     bool showunits;
public:
     void setShowUnits(bool set);
}

Now, make sure that you have overloaded output operators for your derived stream class(es).

Now, check out this URL:
http://www.informit.com/articles/article.asp?p=171014&seqNum=2
for instructions on how to implement a stream manipulator.  Manipulators are functions that operate on streams using the stream insertion operator (<<).  Now, you should be able to set this up so you can do this:

myofstream str("myfile.txt");
Units x = /*some value*/;
str << showunits(true) << x << endl;
str << showunits(false) << x << endl;

Is this the end result you're looking for?
Avatar of jdpipe

ASKER

Yeah except I don't want to overload the stream classes, seems like a lot of clutter.

What about rstaverley's xalloc and iword suggestions?

JP
Do you need any help with xalloc/iword, JP?
Avatar of jdpipe

ASKER

Not abandoned, just a work in progress... I am interested in the answer but I haven't had a chance to test this xalloc/iword stuff