overloading operator << design question

C

Christopher

Currently, the code I am fixing seems to have several different global
functions for each type, is written c-style, to convert different
types into 3 different text representations.

ie.
typedef int Distance;
std::string FormatForLogA(Distnace distance);
std::string FormatForLogB(Distance distance);
std::string FormatForLogC(Distance distance);

I like to overload operator << for a type when I am going to be
converting it into a text representation.

Problem here is that there are 3 different text representations for
each type!
Suppose we are dealing with a distance type...
Log A might expect something like "204"
Log B might expect something like "2m"
Log C might expect something like "204 centimeters"

How would you go about diffientatiing which format you want and still
use the idea of overloading op << ?
Can we even do this for those types that are just a typedef of a
primitive without altering the way the primitive type looks in a
stream?
 
V

Victor Bazarov

Currently, the code I am fixing seems to have several different global
functions for each type, is written c-style, to convert different
types into 3 different text representations.

ie.
typedef int Distance;
std::string FormatForLogA(Distnace distance);
std::string FormatForLogB(Distance distance);
std::string FormatForLogC(Distance distance);

I like to overload operator<< for a type when I am going to be
converting it into a text representation.

Problem here is that there are 3 different text representations for
each type!
Suppose we are dealing with a distance type...
Log A might expect something like "204"
Log B might expect something like "2m"
Log C might expect something like "204 centimeters"

It's unclear whether "Log A" and others will be represented by different
types in your program, or they are all serviced by the same type for
which you're overloading the op<<.
How would you go about diffientatiing which format you want and still
use the idea of overloading op<< ?
Can we even do this for those types that are just a typedef of a
primitive without altering the way the primitive type looks in a
stream?

The usual way to go about it, I think, is to have some kind of state in
the stream (or the object for whose type you'll overload the op<<) and
define the manipulators that would set those states. Take a look at the
ostream and its 'fixed' manipulator, for instance.

MyStream streamForLogA;
streamForLogA << useLogA << distance;
MyStream streamForLogB;
streamForLogB << useLogB << distance;

Of course, in that case it would probably be better to set those states
during initialization of the "stream":

MyStream streamForLogA(MyStream::useLogA); // 'useLogA' is an enum

V
 
K

Kalle Olavi Niemitalo

Christopher said:
Log A might expect something like "204"
Log B might expect something like "2m"
Log C might expect something like "204 centimeters"

How would you go about diffientatiing which format you want and still
use the idea of overloading op << ?

Can we even do this for those types that are just a typedef of a
primitive without altering the way the primitive type looks in a
stream?

No, overloading cannot distinguish typedef names of the same type
from each other, and it can't be done at run time either.

If you are going to keep Distance as a typedef for int, you could
wrap the distance in a class for output. For example, define
class Centimeters with a suitable constructor, overload operator
<<(std::eek:stream &, Centimeters), and then use logC <<
Centimeters(distance). This looks much like calling a function
that returns std::string but is in principle more flexible
because the operator << can change the output according to the
properties of the stream. In particular, it could select the
"centimeters" string based on the locale with which the stream
has been imbued.

If you are changing Distance to a struct or class too, then you
can instead store the preferred format in each ostream object.
There are std::ios_base::xalloc, std::ios_base::iword, and
std::ios_base::pword for this purpose. You'd first call
SetDistanceFormat(logC, DistanceFormatCentimetersWithUnit)
and then just write the distances with logC << distance.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,071
Latest member
MetabolicSolutionsKeto

Latest Threads

Top