jdpipe
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");
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
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");
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;
Length L = 5, "metre";
L.flag (showunit);
cout << The car's length is " << L << endl;
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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
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.
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::showb ase);
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
I compiled using
#define DEFINE_OUTPUT_METHOD(MM,LL
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::showb
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
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 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
enum { showunit = ios_base::showbase };
#define DEFINE_OUTPUT_METHOD(MM,LL
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
// 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?
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
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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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.
create a function:
void displayunits(void)
{
if(app_globals::disp_units
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.
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
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?
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?
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
What about rstaverley's xalloc and iword suggestions?
JP
Do you need any help with xalloc/iword, JP?
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
ASKER
Length L=5 * metre;
cerr.flags(ios_base::showb
cerr << "The car's length is " << L << endl;
This would output:
The car's length is 5 m