Topic: why stringstream?


Author: James Kanze <James.Kanze@dresdner-bank.com>
Date: 25 Jan 01 05:00:03 GMT
Raw View
Dietmar Kuehl wrote:

> wroot@my-deja.com wrote:
> : operators >> and << are free functions, aren't they? They don't even
> : have to be in <string>. As a hack, one could just add something like
> : this to <sstream>:

> You are not allowed to anything to <sstream> and I think the
> definition of operators you defined result in undefined behavior
> because only the implementation is allowed to define operators which
> only take standard types (ie. types from the library and built-in
> types) as argument.

I don't think so.  The requirement is that at least one of the operand
types have class or enum type.  Other than that, I don't think that
there is a standard problem.

That doesn't mean it is a good idea.  For one thing, your operator
cannot be in std, which means that it won't be found by Koenig look
up.  And since most people are (presumably) familiar with the
operators on std::string, it will cause no end of confusion to the
reader.

> Thus, you would need to define your own class
> doing something like this.

> A simple argument why the standard does not define this operators is
> also simple: They are grossly inefficient and almost certainly not
> what you want!  Construction of a stream is a pretty heavy-weight
> operation.  Thus, you want to keep your string stream around and use
> it for formatting this like this in "normal" programs.

Are you sure?  Making sure that the string steam object is in its
"initial" state isn't necessarily trival or cheap either.  For that
matter, how DO you ensure the initial state of extended flags
allocated with xalloc?

> In multi-threaded programs you might want to accept the construction
> of the stream object because sharing stream objects involves extra
> complexity.

And probably run-time costs.

I generally just construct a new stringstream, multi-threaded or not.
That way, I'm sure it is in a known state, regardless of how the
program later evolves.

--
James Kanze                               mailto:kanze@gabi-soft.de
Conseils en informatique orient   e objet/
                   Beratung in objektorientierter Datenverarbeitung
Ziegelh   ttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627


      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]




Author: kuehl@ramsen.informatik.uni-konstanz.de (Dietmar Kuehl)
Date: 25 Jan 2001 23:49:31 -0500
Raw View
Hi,
James Kanze (James.Kanze@dresdner-bank.com) wrote:
: > Thus, you want to keep your string stream around and use
: > it for formatting this like this in "normal" programs.

: Are you sure?  Making sure that the string steam object is in its
: "initial" state isn't necessarily trival or cheap either.  For that
: matter, how DO you ensure the initial state of extended flags
: allocated with xalloc?

  template <typename T, typename S>
  T stream_cast(S const& obj) {
    static std::stringstream stream;
    stream << obj;
    T rc;
    if (stream >> rc)
      return rc;
    else
    {
      stream.clear();
      throw "some error indication...";
    }
  }

How would set the state flags in the first place? Sure, you can play
tricks with manipulators etc. but these would only apply to the stream
in the manipulator template. If I were to keep just one stream for all
types, I would just 'copyfmt()' from a private stream to set the
flags:

  std::ostream& get_stream() {
    static std::ostringstream rc;
    static std::ostring       flags(rc.rdbuf());
    rc.copyfmt(flags);
    return rc;
  }

The cost of 'copyfmt()' is at most the cost of normal destruction plus
the cost of normal construction. In most cases it will actually be
cheaper...

: I generally just construct a new stringstream, multi-threaded or not.
: That way, I'm sure it is in a known state, regardless of how the
: program later evolves.

... and if it is a bottleneck, it is easy to change anyway.
--
<mailto:dietmar_kuehl@yahoo.com> <http://www.dietmar-kuehl.de/>
Phaidros eaSE - Easy Software Engineering: <http://www.phaidros.com/>
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: James Kanze <James.Kanze@dresdner-bank.com>
Date: 27 Jan 01 14:32:54 GMT
Raw View
Dietmar Kuehl wrote:

> James Kanze (James.Kanze@dresdner-bank.com) wrote:
> > > Thus, you want to keep your string stream around and use it for
> > > formatting this like this in "normal" programs.

> > Are you sure?  Making sure that the string steam object is in its
> > "initial" state isn't necessarily trival or cheap either.  For
> > that matter, how DO you ensure the initial state of extended flags
> > allocated with xalloc?

>   template <typename T, typename S>
>   T stream_cast(S const& obj) {
>     static std::stringstream stream;
>     stream << obj;
>     T rc;
>     if (stream >> rc)
>       return rc;
>     else
>     {
>       stream.clear();
>       throw "some error indication...";
>     }
>   }

> How would set the state flags in the first place? Sure, you can play
> tricks with manipulators etc. but these would only apply to the stream
> in the manipulator template.

I don't think using manipulators is "playing tricks".  I don't see
much interest in a template like the above -- it's almost never that I
want the default formatting for floats, for example.  And how do I use
the template to get the hex value of an int?

> If I were to keep just one stream for all
> types, I would just 'copyfmt()' from a private stream to set the
> flags:

>   std::ostream& get_stream() {
>     static std::ostringstream rc;
>     static std::ostring       flags(rc.rdbuf());
>     rc.copyfmt(flags);
>     return rc;
>   }

This is what I thought you were recommending.  My main reason for
posting, in fact, was that I think most people would forget the
reinitialization of the flags.

> The cost of 'copyfmt()' is at most the cost of normal destruction
> plus the cost of normal construction. In most cases it will actually
> be cheaper...

memcpy cheaper than memset?

Seriously, I imagine that most of the time, you will be able to find a
solution that is cheaper that new constructing.  I doubt that it will
be significantly cheaper, however, and it is a bitch to get right.  In
your case, for example, consider the following:

    void
    f()
    {
        std::ostream& dst = get_stream() ;
        dst.setf( std::ios::fixed , std::ios::floatfield ) ;
        for ( ... ) {
            dst << ...
        }
    }

A reasonable use.  Now what happens if f() calls another function in
the for loop which uses get_stream?

I'm not saying that your solution is never justified.  I'm just saying
that there is more to it that first seems, and the simplest solution
is to just create a new stringstream each time around.

> > I generally just construct a new stringstream, multi-threaded or
> > not.  That way, I'm sure it is in a known state, regardless of how
> > the program later evolves.

> ... and if it is a bottleneck, it is easy to change anyway.

And that it may be worth keeping the alternative in mind, to avoid
doing anything that will make it hard to change.  Just in case.

--
James Kanze                               mailto:kanze@gabi-soft.de
Conseils en informatique orient   e objet/
                   Beratung in objektorientierter Datenverarbeitung
Ziegelh   ttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627


      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]




Author: wroot@my-deja.com
Date: 22 Jan 01 14:43:28 GMT
Raw View
In article <94db46$fho$1@news6.svr.pol.co.uk>,
  "Martin Aspeli (Optilude)" <optilude@killthis.gmx.net> wrote:

> Wroot wrote (regarding simplification of the syntax of string
> operations):

> > Integer >> String;
> > or
> > String << Integer;


> Well, you *could* define operator << in string, but that would make it
> rather heavy, and would require string to be dependent on the
iostreams
> library (and vice-versa), which would make the string class a whole
lot
> heavier dependency-wise and probably also efficiency-wise.

<snipped>

operators >> and << are free functions, aren't they? They don't even
have to be in <string>. As a hack, one could just add something like
this to <sstream>:

template<typename T>
std::string& operator<<(std::string& s, const T& a)
{
    ostringstream out;
    out << a;
    s += out.str();
    return s;
}


template<typename T>
std::string& operator>>(std::string& s, T& a)
{
    istringstream in(s);
    in >> a;
    return s;
}

and get simpler syntax for string operations. Correct me if I'm wrong,
please.

Wroot


Sent via Deja.com
http://www.deja.com/

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]




Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: 23 Jan 01 00:05:50 GMT
Raw View
In article <94gmjm$u5s$1@nnrp1.deja.com>, wroot@my-deja.com writes
>Correct me if I'm wrong,
>please.
I think that you are not allowed to add functions to namespace std::
other than template specialisations for non-Standard types.

--
Francis Glassborow
See http:\\www.accu.org for details of The ACCU Spring Conference, 2001
(includes many regular participants to C & C++ newsgroups)

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]




Author: kuehl@ramsen.informatik.uni-konstanz.de (Dietmar Kuehl)
Date: 23 Jan 2001 07:44:15 -0500
Raw View
Hi,
wroot@my-deja.com wrote:
: operators >> and << are free functions, aren't they? They don't even
: have to be in <string>. As a hack, one could just add something like
: this to <sstream>:

You are not allowed to anything to <sstream> and I think the definition
of operators you defined result in undefined behavior because only the
implementation is allowed to define operators which only take standard
types (ie. types from the library and built-in types) as argument. Thus,
you would need to define your own class doing something like this.

A simple argument why the standard does not define this operators is
also simple: They are grossly inefficient and almost certainly not what
you want!  Construction of a stream is a pretty heavy-weight
operation.  Thus, you want to keep your string stream around and use it
for formatting this like this in "normal" programs. In multi-threaded
programs you might want to accept the construction of the stream object
because sharing stream objects involves extra complexity.
--
<mailto:dietmar_kuehl@yahoo.com> <http://www.dietmar-kuehl.de/>
Phaidros eaSE - Easy Software Engineering: <http://www.phaidros.com/>
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]