a question about overloading operator<<

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • JustSomeGuy

    #1

    a question about overloading operator<<

    I have a double that I want to output as: (depending on its value)

    1000 Bytes
    1.6 Kilobyte
    2.5 Megabytes
    ..5 Terabytes

    can I do this with...

    ostream & operator<<(ostr eam & o, double n)


    How would you recommend going about outputting this?


  • Vyacheslav Kononenko

    #2
    Re: a question about overloading operator&lt;&lt ;

    JustSomeGuy wrote:
    [color=blue]
    > I have a double that I want to output as: (depending on its value)
    >
    > 1000 Bytes
    > 1.6 Kilobyte
    > 2.5 Megabytes
    > .5 Terabytes
    >
    > can I do this with...
    >
    > ostream & operator<<(ostr eam & o, double n)
    >[/color]
    No you cannot. Operators for standard types have been already defined.
    [color=blue]
    >
    > How would you recommend going about outputting this?
    >
    >[/color]
    Just make a wrapper around double:

    class BytesFormat {
    public:
    BytesFormat( double d_ ) : d( d_ ) {}
    friend std::ostream &operator<<( std::ostream &os, const BytesFormat
    &bt );
    private:
    double d;
    };

    void foo()
    {
    double bytes;
    // ...

    std::cout << BytesFormat( bytes );
    }


    std::ostream &operator<<( std::ostream &os, const BytesFormat &bt )
    {
    if( bt.d < 1000.0 ) os << d << " Bytes";
    // ...
    return os;
    }

    --
    Regards,
    Slava

    Comment

    • Dietmar Kuehl

      #3
      Re: a question about overloading operator&lt;&lt ;

      Vyacheslav Kononenko wrote:[color=blue]
      > JustSomeGuy wrote:[color=green]
      > > I have a double that I want to output as: (depending on its value)
      > >
      > > 1000 Bytes
      > > 1.6 Kilobyte
      > > 2.5 Megabytes
      > > .5 Terabytes
      > >
      > > can I do this with...
      > >
      > > ostream & operator<<(ostr eam & o, double n)[/color][/color]
      [color=blue]
      > No you cannot. Operators for standard types have been already[/color]
      defined.

      .... but still you can achieve the above goal! All you need to do is
      to create a new "num_put" facet (i.e. a class derived from
      'std::num_put<c har>'), install this facet into a 'std::locale' object,
      and 'imbue()' the stream with the resulting object. There is no need
      for falling back to ill-advised techniques.
      --
      <mailto:dietmar _kuehl@yahoo.co m> <http://www.dietmar-kuehl.de/>
      <http://www.contendix.c om> - Software Development & Consulting

      Comment

      • Vyacheslav Kononenko

        #4
        Re: a question about overloading operator&lt;&lt ;

        Dietmar Kuehl wrote:
        [color=blue]
        > Vyacheslav Kononenko wrote:
        >[color=green]
        >>JustSomeGuy wrote:
        >>[color=darkred]
        >>>I have a double that I want to output as: (depending on its value)
        >>>
        >>>1000 Bytes
        >>>1.6 Kilobyte
        >>>2.5 Megabytes
        >>>.5 Terabytes
        >>>
        >>>can I do this with...
        >>>
        >>>ostream & operator<<(ostr eam & o, double n)[/color][/color]
        >
        >[color=green]
        >>No you cannot. Operators for standard types have been already[/color]
        >
        > defined.
        >
        > ... but still you can achieve the above goal! All you need to do is
        > to create a new "num_put" facet (i.e. a class derived from
        > 'std::num_put<c har>'), install this facet into a 'std::locale' object,
        > and 'imbue()' the stream with the resulting object. There is no need
        > for falling back to ill-advised techniques.[/color]

        Cool. How about to print regular doubles and kilobytes at the same time?[color=blue]
        > --
        > <mailto:dietmar _kuehl@yahoo.co m> <http://www.dietmar-kuehl.de/>
        > <http://www.contendix.c om> - Software Development & Consulting
        >[/color]


        --
        Regards,
        Slava

        Comment

        • Tom Widmer

          #5
          Re: a question about overloading operator&lt;&lt ;

          On Tue, 09 Nov 2004 09:46:56 -0500, Vyacheslav Kononenko
          <vyacheslav@NOk ononenkoSPAM.ne t> wrote:
          [color=blue]
          >Dietmar Kuehl wrote:
          >[color=green]
          >> Vyacheslav Kononenko wrote:
          >>[color=darkred]
          >>>JustSomeGu y wrote:
          >>>
          >>>>I have a double that I want to output as: (depending on its value)
          >>>>
          >>>>1000 Bytes
          >>>>1.6 Kilobyte
          >>>>2.5 Megabytes
          >>>>.5 Terabytes
          >>>>
          >>>>can I do this with...
          >>>>
          >>>>ostream & operator<<(ostr eam & o, double n)[/color]
          >>
          >>[color=darkred]
          >>>No you cannot. Operators for standard types have been already[/color]
          >>
          >> defined.
          >>
          >> ... but still you can achieve the above goal! All you need to do is
          >> to create a new "num_put" facet (i.e. a class derived from
          >> 'std::num_put<c har>'), install this facet into a 'std::locale' object,
          >> and 'imbue()' the stream with the resulting object. There is no need
          >> for falling back to ill-advised techniques.[/color]
          >
          >Cool. How about to print regular doubles and kilobytes at the same time?[/color]

          You'd have to also write a manipulator to set a custom flag on the
          stream and have the num_put facet obtain the formatting information
          from the stream (in the ios_base& parameter) before deciding how to
          output the number.

          This is all a little involved, but you could write a reusable
          framework to make it easier (and boost may have one already, just not
          in a released version).

          Tom

          Comment

          • Old Wolf

            #6
            Re: a question about overloading operator&lt;&lt ;

            "Dietmar Kuehl" <dietmar_kuehl@ yahoo.com> wrote:[color=blue]
            > Vyacheslav Kononenko wrote:[color=green]
            > > JustSomeGuy wrote:[color=darkred]
            > > > I have a double that I want to output as: (depending on its value)
            > > >
            > > > 1000 Bytes
            > > > 1.6 Kilobyte
            > > > 2.5 Megabytes
            > > > .5 Terabytes
            > > >
            > > > can I do this with...
            > > >
            > > > ostream & operator<<(ostr eam & o, double n)[/color][/color]
            >[color=green]
            > > No you cannot. Operators for standard types have been already[/color]
            > defined.
            >
            > ... but still you can achieve the above goal! All you need to do is
            > to create a new "num_put" facet (i.e. a class derived from
            > 'std::num_put<c har>'), install this facet into a 'std::locale' object,
            > and 'imbue()' the stream with the resulting object.[/color]

            You make it sound so easy :)

            Comment

            • Tom Widmer

              #7
              Re: a question about overloading operator&lt;&lt ;

              On 9 Nov 2004 11:41:24 -0800, oldwolf@inspire .net.nz (Old Wolf) wrote:
              [color=blue]
              >"Dietmar Kuehl" <dietmar_kuehl@ yahoo.com> wrote:[color=green]
              >> Vyacheslav Kononenko wrote:[color=darkred]
              >> > JustSomeGuy wrote:
              >> > > I have a double that I want to output as: (depending on its value)
              >> > >
              >> > > 1000 Bytes
              >> > > 1.6 Kilobyte
              >> > > 2.5 Megabytes
              >> > > .5 Terabytes
              >> > >
              >> > > can I do this with...
              >> > >
              >> > > ostream & operator<<(ostr eam & o, double n)[/color]
              >>[color=darkred]
              >> > No you cannot. Operators for standard types have been already[/color]
              >> defined.
              >>
              >> ... but still you can achieve the above goal! All you need to do is
              >> to create a new "num_put" facet (i.e. a class derived from
              >> 'std::num_put<c har>'), install this facet into a 'std::locale' object,
              >> and 'imbue()' the stream with the resulting object.[/color]
              >
              >You make it sound so easy :)[/color]

              There's definitely room for a boost library to make it easier, so that
              you can, for example, just change the formatting of double without
              having to worry about the other numeric types or formatting options,
              etc.

              Tom

              Comment

              • Dietmar Kuehl

                #8
                Re: a question about overloading operator&lt;&lt ;

                Old Wolf wrote:[color=blue]
                > You make it sound so easy :)[/color]

                That would be because it actually *is* easy! The only tricky part is
                the actual formatting since the above is hardly a specification. Here
                is some sample code:

                | #include <locale>
                | #include <iostream>
                | #include <sstream>
                | #include <algorithm>
                |
                | struct my_num_put:
                | std::num_put<ch ar>
                | {
                | iter_type do_put(iter_typ e to, std::ios_base& fmt,
                | char fill, long double d) const
                | {
                | std::ostringstr eam out;
                | out.precision(1 );
                | out << std::fixed;
                | if (d < 1024.0)
                | out << d << " Bytes";
                | else if (d < 1024.0 * 1024.0)
                | out << (d / 1024.0) << " Kilobytes";
                | else if (d < 1024.0 * 1024.0 * 1024.0)
                | out << (d / (1024.0 * 1024.0)) << " Megabytes";
                | else if (d < 0.5 * 1024.0 * 1024.0 * 1024.0 * 1024.0)
                | out << (d / (1024.0 * 1024.0 * 1024.0)) << " Gigabytes";
                | else
                | out << (d / (1024.0 * 1024.0 * 1024.0 * 1024.0))
                | << " Terabytes";
                |
                | std::string const& s = out.str();
                | return std::copy(s.beg in(), s.end(), to);
                | }
                | iter_type do_put(iter_typ e to, std::ios_base& fmt,
                | char fill, double d) const
                | {
                | return do_put(to, fmt, fill, static_cast<lon g double>(d));
                | }
                | };
                |
                | int main()
                | {
                | std::locale loc;
                | std::locale my_loc(loc, new my_num_put);
                | std::cout.imbue (my_loc);
                |
                | std::cout << 1000.0 << "\n";
                | std::cout << 1600.0 << "\n";
                | std::cout << 2500000.0 << "\n";
                | std::cout << 550000000000.0 << "\n";
                | }

                This is hardly rocket science...

                Note a. that this code does indeed just what I decribed before and b.
                most of the work goes into actually figuring out the right format. But
                even then, it is no big deal.

                BTW, if you want to have something like this which you could turn
                on/off
                at will, you would have to set formatting flags in the stream object to
                tell the stream when you want which formatting. The location to store
                e.g. a flag is in an 'int' object accessed using the stream's 'iword()'
                object. However, this is no big deal either...
                --
                <mailto:dietmar _kuehl@yahoo.co m> <http://www.dietmar-kuehl.de/>
                <http://www.contendix.c om> - Software Development & Consulting

                Comment

                Working...