Topic: stream: overriding the endl manipulator ??


Author: Hyman Rosen <hymie@prolifics.com>
Date: 1999/08/04
Raw View
see.below@ibm.net (David Ward) writes:
> My motivation is .....
> I want code like:
> fred << "Hi there" << endl;
> to work when fred is a derived class (derived from say strstream). I
> need the endl manipulator to do something specific to the derived
> class.
> Let's say that fred is a derived stream class that writes to the Unix
> syslog. You might want to collect one entire line of data into a
> strstram buffer, and then use endl to actually do the syslog write
> call.
> Using endl, instread of a new manipulator, minimises changes to the
> code.

When you want to do something like that, your best bet is to create a
new streambuf class and do your special work in its overflow member
function. Instead of making endl do something special, just do it when
a '\n' is written.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "Darin Adler" <darin@bentspoon.com>
Date: 1999/08/04
Raw View
Jim Barry <jim.barry@bigfoot.com> wrote:

> Huh? As far as I know, anything without a copyright notice is in the public
> domain.

Absolutely not. But this is not the newsgroup to discuss this.

Use "copyright law" in your favorite search engine to find more on this
topic.

A page from one of the many sites that touch on this topic:

    http://www.benedict.com/basic/public.htm

    -- Darin
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "Jim Barry" <jim.barry@bigfoot.com>
Date: 1999/08/04
Raw View
Matt Seitz wrote:

> Technically, no.  According to "Circular 1 - Copyright Basics"
> by the Copyright Office of the Library of Congress (available at
> http://lcweb.loc.gov/copyright/circs/circ01.pdf):

Well, things have certainly changed since I last read about copyright.
It's a funny old world.




[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: brahms@mindspring.com (Stan Brown)
Date: 1999/08/06
Raw View
[This followup was also e-mailed to the cited author for speed -- please
follow up in the newsgroup.]

[Moderator note: please don't followup at all in comp.std.c++
 about copyright issues; this is the last message in this thread
 that I let pass. --vb]

jim.barry@bigfoot.com (Jim Barry) wrote in comp.std.c++:
>Huh? As far as I know, anything without a copyright notice is in the public
>domain.

That's one of the 10 Big Copyright Myths.
 http://www.templetons.com/brad/copymyths.html

Even without a copyright notice (which my copy bears), the standard would
still be copyright -- it's an interesting question who would own the
copyright in that case, though perhaps that question is too hypothetical
for this newsgroup.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "Jim Barry" <jim.barry@bigfoot.com>
Date: 1999/08/02
Raw View
Dietmar Kuehl wrote:
> Jim Barry (jim.barry@bigfoot.com) wrote:
> : Sometimes people need to output "\r\n" for a new line.
>
> On systems where this is necessary, the class 'filebuf' should take
> care of this conversion. If you want to write a corresponding file on
> a system where it is not necessary (eg. you want to write an MS-DOS
> text file on a UNIX machine), the easiest approach would be the use of
> a filtering stream buffer to do this.

The example I had in mind was a program that works with protocols that
require "\r\n" (HTTP/SMTP/NNTP etc.), probably via standard input and
output.

> - You cannot "override" normal functions, you can only override
virtual
>   member functions. 'std::endl' is not a member function and thus also
>   not virtual.

Why do you say this? I did not suggest that endl is a virtual function.

> - If the user writes a '\n' without using 'std::endl' (which is very
>   resonable because 'std::endl' forces a synchronization which is
often
>   not necessary and which might introduce a performance problem), this
>   does not beceom translated.

This is true enough, but the scenario that I am considering is the where
the user defines his or her own 'endl' in some locality of the program
and is careful not to write literal '\n' characters into the stream.
Incidentally, the user might elect not to call 'flush' in the custom
'endl', in order to avoid the performance problem that you mention.

> I don't think so: It takes only a few lines (maybe 20) for a simple
> start (just override 'overflow()' to do the proper conversion)  and
> it can easily be improved if it turns out that it is a performance
> problem.

But that is quite a bit more work than the half dozen lines needed for a
custom 'endl'. I am not insisting that writing a manipulator called
'endl' is the only possibility. If you said that it makes you queasy and
that it should be called e.g. 'crlf' then I would not have a big problem
with that.




[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: kuehl@horn.fmi.uni-konstanz.de (Dietmar Kuehl)
Date: 1999/08/02
Raw View
Hi,
Jim Barry (jim.barry@bigfoot.com) wrote:
: Dietmar Kuehl wrote:
: > Jim Barry (jim.barry@bigfoot.com) wrote:
: > : Sometimes people need to output "\r\n" for a new line.
: >
: > On systems where this is necessary, the class 'filebuf' should take
: > care of this conversion. If you want to write a corresponding file on
: > a system where it is not necessary (eg. you want to write an MS-DOS
: > text file on a UNIX machine), the easiest approach would be the use of
: > a filtering stream buffer to do this.

: The example I had in mind was a program that works with protocols that
: require "\r\n" (HTTP/SMTP/NNTP etc.), probably via standard input and
: output.

I'd expect to run such protocols over a socket and in this case the
stream buffer handling the socket and potentially portions of the
protocol would be the right place to handle eg. the CR/LF -> LF
translation. Of course, this is just what I would use and there are
other alternatives: If you are using standard input/output anyway, it
might also be reasonable to have the corresponding processing in some
external program.

: > - You cannot "override" normal functions, you can only override
: virtual
: >   member functions. 'std::endl' is not a member function and thus also
: >   not virtual.

: Why do you say this? I did not suggest that endl is a virtual function.

I didn't claim you did. However, somebody was using the term
"overriding" in conjunction with 'endl' and I just explained why you
cannot "override" it using the normal C++ overriding mechanism. Also,
this is part of the analysis of the design space: We cannot simply
replace 'endl' so we have to look for another solution.

: > - If the user writes a '\n' without using 'std::endl' (which is very
: >   resonable because 'std::endl' forces a synchronization which is
: often
: >   not necessary and which might introduce a performance problem), this
: >   does not beceom translated.

: This is true enough, but the scenario that I am considering is the where
: the user defines his or her own 'endl' in some locality of the program
: and is careful not to write literal '\n' characters into the stream.

OK. In this case it might be reasonable to use a special manipulator,
say 'crlf', to insert the CR/LF sequence on systems where it is
necessary and just LF on systems where it is not (I don't think the
standard mandates any specific behavior for the standard stream, ie.
'cin', 'cout', etc.  and only specifies something for file streams with
respect to LF -> CR/LF translation).

: Incidentally, the user might elect not to call 'flush' in the custom
: 'endl', in order to avoid the performance problem that you mention.

Yup. However, I think this is a viable approach but I would consider
the other one, ie. creating a special stream buffer, to be more solid
and in total be cheaper although the initial overhead of writing a
stream buffer might seem to inidcate that this approach is more
expensive. In return for the initial overhead, the uer can be rather
careless about writing to the stream. If the programmer has to hunt
down the first accidentally inserted plain '\n' with the manipulator
approach, the stream buffer approach would have paid off. Since the
necessite to use a manipulator rather than plain inserting a '\n' is
uncommon and some people, like eg. me, are arguing against very liberal
use of 'std::endl' I would expect that sometime theere will be the
error made if not during program development then during maintainance.
Thus, I'm leaning towards solid interface rather than relying on the
programmer to be careful. Only if the differing costs indicate that the
cleaner interface does probably not pay off, I would accept usage of
some easily breakable interface. In this case, I see no justification
not to use a stream buffer.

: > I don't think so: It takes only a few lines (maybe 20) for a simple
: > start (just override 'overflow()' to do the proper conversion)  and
: > it can easily be improved if it turns out that it is a performance
: > problem.

: But that is quite a bit more work than the half dozen lines needed for a
: custom 'endl'. I am not insisting that writing a manipulator called
: 'endl' is the only possibility. If you said that it makes you queasy and
: that it should be called e.g. 'crlf' then I would not have a big problem
: with that.

Here is a simple stream buffer which should do the trick (for output;
input is slightly more only complicated):

  template <class cT, class Tr = std::char_traits<cT> >
  class basic_crlfbuf: public std::basic_streambuf<cT, Tr>
  {
  public:
    typedef typename Tr::int_type int_type;
    basic_crlfbuf(std::basic_streambuf<cT, Tr>* sbuf): m_sbuf(sbuf) {}

  private:
    int_type overflow(int_type c)
    {
      if (Tr::eq_int_type(c, Tr::to_int_type(Tr::widen('\n'))))
 if (Tr::eq_int_type(m_sbuf.sputc(Tr::widen('\r'), Tr::eof())))
   return Tr::eof();
      return m_sbuf.sputc(Tr::to_char_type(c));
    }
    std::basic_streambuf<cT, Tr>* m_sbuf;
  };

This doesn't look too complex to me and this is already the templatized
version! The only logic which can get messed up is the body of the
'overflow()' function, everything else is basically verified by the
compiler. The cost of writing this code is less than the cost of
writing an article like this one (obviously, since this article already
includes the code :-) and relieves the programmer from having to care
about a certain nit in the programming style.

PS: I haven't tested the code yet, not even if it compiles. If you are
interested in using it, just sent me an e-mail and I will sent you a
version with a copyright suitable for any use (since this article does
not have a copyright notice, the code is implicitly basically protected
from any use; thus, a proper copyright can only be more liberal).
--
<mailto:dietmar.kuehl@claas-solutions.de>
<http://www.informatik.uni-konstanz.de/~kuehl/>
I am a realistic optimist - that's why I appear to be slightly pessimistic


[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Jim Barry" <jim.barry@bigfoot.com>
Date: 1999/08/03
Raw View
Dietmar Kuehl <kuehl@horn.fmi.uni-konstanz.de> wrote:

> PS: I haven't tested the code yet, not even if it compiles.
> If you are interested in using it, just sent me an e-mail

Thanks, but I have already written streambuf derivations (e.g. a stringbuf
derivation that writes the stream into a multiple-line edit control).

> (since this article does not have a copyright notice, the code
> is implicitly basically protected from any use; thus, a proper
> copyright can only be more liberal).

Huh? As far as I know, anything without a copyright notice is in the public
domain.




[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: see.below@ibm.net (David Ward)
Date: 1999/08/03
Raw View
Thomas_Matthews@tecmar.com wrote:

>
>What does your manipulator do differently?
>The endl manipulator appends a '\n' to the stream, then flushes the
>stream.  This manipulator can be replaced by the following line:
>  stream << '\n';
>  stream.flush();
>
>I suggest that you create a new manipulator with a different name, if
>you want something different to happen.  The other idea is to change how
>flush() works with your stream implementation.

My motivation is .....

I want code like:

fred << "Hi there" << endl;

to work when fred is a derived class (derived from say strstream). I
need the endl manipulator to do something specific to the derived
class.

Let's say that fred is a derived stream class that writes to the Unix
syslog. You might want to collect one entire line of data into a
strstram buffer, and then use endl to actually do the syslog write
call.

Using endl, instread of a new manipulator, minimises changes to the
code.

Any way, that's reason I asked ...
Regards
Dave W




Anti-spam: to reply change see.below to davidw


[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: kuehl@horn.fmi.uni-konstanz.de (Dietmar Kuehl)
Date: 1999/08/03
Raw View
Hi,
David Ward (see.below@ibm.net) wrote:
: I want code like:

: fred << "Hi there" << endl;

: to work when fred is a derived class (derived from say strstream). I
: need the endl manipulator to do something specific to the derived
: class.

: Let's say that fred is a derived stream class that writes to the Unix
: syslog. You might want to collect one entire line of data into a
: strstram buffer, and then use endl to actually do the syslog write
: call.

The "correct" solution to this problem is indeed to write a new stream
buffer, say 'syslogbuf', which collects the line and sends it if a
newline is encountered. Except for the handling of the syslog functions
as easy as the stream buffer I posted yesterday.
--
<mailto:dietmar.kuehl@claas-solutions.de>
<http://www.informatik.uni-konstanz.de/~kuehl/>
I am a realistic optimist - that's why I appear to be slightly pessimistic


[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Matt Seitz" <mseitz@meridian-data.com>
Date: 1999/08/03
Raw View

Jim Barry <jim.barry@bigfoot.com> wrote in message
news:newscache$l91wff$1rd$1@firewall.thermoteknix.co.uk...
> Huh? As far as I know, anything without a copyright notice is in the
public
> domain.

Technically, no.  According to "Circular 1 - Copyright Basics" by the
Copyright Office of the Library of Congress (available at
http://lcweb.loc.gov/copyright/circs/circ01.pdf):

WHO CAN CLAIM COPYRIGHT?
Copyright protection subsists from the time the work is
created in fixed form. The copyright in the work of authorship
immediately becomes the property of the author who
created the work.

Copyright Secured Automatically Upon Creation
The way in which copyright protection is secured is frequently
misunderstood. No publication or registration or
other action in the Copyright Office is required to secure
copyright.

NOTICE OF COPYRIGHT
The use of a copyright notice is no longer required under
U.S. law, although it is often beneficial.




[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: kuehl@horn.fmi.uni-konstanz.de (Dietmar Kuehl)
Date: 1999/08/01
Raw View
Hi,
Jim Barry (jim.barry@bigfoot.com) wrote:
: Sometimes people need to output "\r\n" for a new line.

On systems where this is necessary, the class 'filebuf' should take
care of this conversion. If you want to write a corresponding file on
a system where it is not necessary (eg. you want to write an MS-DOS
text file on a UNIX machine), the easiest approach would be the use of
a filtering stream buffer to do this. Overriding 'std::endl' does not
work for two reasons:
- You cannot "override" normal functions, you can only override virtual
  member functions. 'std::endl' is not a member function and thus also
  not virtual.
- If the user writes a '\n' without using 'std::endl' (which is very
  resonable because 'std::endl' forces a synchronization which is often
  not necessary and which might introduce a performance problem), this
  does not beceom translated.

: Selecting an
: alternative endl is a way to do it while keeping the code looking
: "normal". Creating a custom buffer would probably be overkill.

I don't think so: It takes only a few lines (maybe 20) for a simple
start (just override 'overflow()' to do the proper conversion)  and
it can easily be improved if it turns out that it is a performance
problem.
--
<mailto:dietmar.kuehl@claas-solutions.de>
<http://www.informatik.uni-konstanz.de/~kuehl/>
I am a realistic optimist - that's why I appear to be slightly pessimistic
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "Jim Barry" <jim.barry@bigfoot.com>
Date: 1999/07/30
Raw View
David Ward <see.below@ibm.net> wrote in message
news:37a1169b.509823@news.supernews.com...
>
> I'm curious whether there is an elegant (simple) way to override the
> std::endl manipulator so that it does my bidding ....

The std::endl manipulator is (obviously) in the 'std' namespace, so you can
select a different version like this:

  namespace notstd
  {
    std::ostream& endl(std::ostream& os)
    {
      // ...
      return os;
    }
  }
  using notstd::endl;

This doesn't coexist too well with "using namespace std" directives though.
In particular, MSVC throws out some very bizarre error messages.




[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Thomas_Matthews@tecmar.com
Date: 1999/07/30
Raw View
In article <37a1169b.509823@news.supernews.com>,
  see.below@ibm.net (David Ward) wrote:
> Hi there,
>
> I'm curious whether there is an elegant (simple) way to override the
> std::endl manipulator so that it does my bidding ....
>
> I know how to create a new manipulator, but I'd like code such as:
>
> mystream << "hi there" << endl;
>
> to still compile. don't mind mystream being a specialization of
> ostream if necessary.
>
> Of course, I'd like all the other formatting std:: manipulators to
> still work.
>
> Hoping there's a way to do this ...
>
> Thanks
> Dave W

What does your manipulator do differently?
The endl manipulator appends a '\n' to the stream, then flushes the
stream.  This manipulator can be replaced by the following line:
  stream << '\n';
  stream.flush();

I suggest that you create a new manipulator with a different name, if
you want something different to happen.  The other idea is to change how
flush() works with your stream implementation.

-- Thomas Matthews



Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.


[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Hyman Rosen <hymie@prolifics.com>
Date: 1999/07/30
Raw View
see.below@ibm.net (David Ward) writes:
> I'm curious whether there is an elegant (simple) way to override the
> std::endl manipulator so that it does my bidding ....
> I know how to create a new manipulator, but I'd like code such as:
> mystream << "hi there" << endl;
> to still compile. don't mind mystream being a specialization of
> ostream if necessary.
> Of course, I'd like all the other formatting std:: manipulators to
> still work.

This might work -

class forwarding_ostream
{
 std::ostream &out;
public:
 forwarding_ostream(std::ostream &out = std::cout) : out(out) { }
 template <typename T> forwarding_ostream &operator<<(const T &value)
 {
  out << value;
  return *this;
 }
 forwarding_ostream &operator<<(ostream &(*manip)(ostream &))
 {
  if (manip == std::endl)
  {
   // handle endl here
  }
  else
  {
   out << manip;
  }
  return *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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Jim Barry" <jim.barry@bigfoot.com>
Date: 1999/07/31
Raw View
Thomas Matthews wrote:

> What does your manipulator do differently?

Sometimes people need to output "\r\n" for a new line. Selecting an
alternative endl is a way to do it while keeping the code looking
"normal". Creating a custom buffer would probably be overkill.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "Jim Barry" <jim.barry@bigfoot.com>
Date: 1999/07/31
Raw View
Hyman Rosen wrote:

> This might work -
>
> class forwarding_ostream
> {
> public:
> template <typename T> forwarding_ostream &operator<<(const T &value)
> {
> out << value;
> return *this;
> }
[snip]

Heh, I tried this a while ago too. Doesn't work too well on MSVC. I
tried to feign surprise, but just couldn't manage it.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: see.below@ibm.net (David Ward)
Date: 1999/07/30
Raw View
Hi there,

I'm curious whether there is an elegant (simple) way to override the
std::endl manipulator so that it does my bidding ....

I know how to create a new manipulator, but I'd like code such as:

mystream << "hi there" << endl;

to still compile. don't mind mystream being a specialization of
ostream if necessary.

Of course, I'd like all the other formatting std:: manipulators to
still work.

Hoping there's a way to do this ...

Thanks
Dave W
Anti-spam: to reply change see.below to davidw
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]