overloading operator << design question

Discussion in 'C++' started by Christopher, Sep 9, 2011.

  1. Christopher

    Christopher Guest

    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?
    Christopher, Sep 9, 2011
    #1
    1. Advertising

  2. On 9/9/2011 1:04 PM, Christopher wrote:
    > 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
    --
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Sep 9, 2011
    #2
    1. Advertising

  3. Christopher <> writes:

    > 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.
    Kalle Olavi Niemitalo, Sep 9, 2011
    #3
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. John Smith
    Replies:
    2
    Views:
    414
    Ivan Vecerina
    Oct 6, 2004
  2. Replies:
    11
    Views:
    720
    James Kanze
    May 16, 2007
  3. hurcan solter
    Replies:
    3
    Views:
    713
    Cholo Lennon
    Aug 29, 2007
  4. Replies:
    11
    Views:
    545
  5. Replies:
    2
    Views:
    302
Loading...

Share This Page