Topic: Deflecting standard streams


Author: remove.haberg@matematik.su.se (Hans Aberg)
Date: 2000/11/15
Raw View
In article <3A1034E4.18BBB78@evtechnology.com>, James Dennett
<james@evtechnology.com> wrote:
>Rather, I would like to see either (a) a clarification of your claim that
>binding temporaries to non-const references is hard to implement (which seems
>to contradict the fact that it's implemented by at least two compilers (gcc
>and MS) as a trivial if dangerous extension), or (b) a withdrawal of that
>claim.  Just to clean up the misunderstanding.

The point is that when speaking about dynamic bindings, it is implicitly
understood that they should be safe.

In article <8urip1$v3$1@nnrp1.deja.com>, James.Kanze@dresdner-bank.com wrote:
>> I don't see why binding to non-const reference should be harder than
>> binding to const reference (which _is_ allowed).
>
>It's actually easier for the compiler to allow both, as it eliminates
>a special case.
>
>Originally, C++ allowed binding a temporary to any reference, const or
>not.  The rule against binding to a non-const reference was introduced
>because it was found to be too error prone.  People often got
>temporaries when they didn't expect it.  (The result of an implicit
>conversion, for example, is a temporary.)

So this seems saying the same thing as I do, because I assument the
implementation to be safe. Allowing it, there must be some mechanism
keeping track of it, the programmer's failing super-computer or a CGC, but
not C++ scope rules.

  Hans Aberg      * Anti-spam: remove "remove." from email address.
                  * Email: Hans Aberg <remove.haberg@member.ams.org>
                  * Home Page: <http://www.matematik.su.se/~haberg/>
                  * AMS member listing: <http://www.ams.org/cml/>

---
[ 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: James Dennett <james@evtechnology.com>
Date: 2000/11/13
Raw View
Hans Aberg wrote:
>
> In article <3A042983.2A3C9E47@evtechnology.com>, James Dennett
> <james@evtechnology.com> wrote:
> >> >There is a reference (posted elsewhere in this thread) to where the
> >> >Standard bans the binding of temporaries to non-const references.
> >> ...
> >> >It's explicitly disallowed by the Standard, but
> >> >not because it's hard to implement.  Rather because it was viewed as being
> >> >a Bad Thing on balance...
> >>
> >> No, the reason it was banned is not that it was bad, but because it is
> >> hard to implement:
> >
> >So, what is the difference between the case of binding a const reference to
> >a temporary (which *is implemented in Standard C++) and binding a non-const
> >reference?  How can one be easy to implement but not the other?
>
> The way one implement dynamic bindings to a reference is

[ lengthy talk of GC deleted ]

My point was that this is _nothing to do with garbage collection_.

1. It is currently in the C++ Standard for const references.
2. It is not in the Standard, by design, for non-const references.

I believe that GC is unrelated to constness in this area.  To restate myself,
there is a valid (if potentially unsafe) implementation of binding temporaries
to references, and compilers have the code to handle it -- they explicitly
disallow it for non-const references.

Please do not attempt further explanation of garbage collection.  This thread
is not the right place for it.

Rather, I would like to see either (a) a clarification of your claim that
binding temporaries to non-const references is hard to implement (which seems
to contradict the fact that it's implemented by at least two compilers (gcc
and MS) as a trivial if dangerous extension), or (b) a withdrawal of that
claim.  Just to clean up the misunderstanding.

-- James Dennett <jdennett@acm.org>

---
[ 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: James Dennett <james@evtechnology.com>
Date: 2000/11/13
Raw View
Hans Aberg wrote:
>
> In article <3A031BE8.31433C1F@physik.tu-muenchen.de>, Christopher Eltschka
> <celtschk@physik.tu-muenchen.de> wrote:
> >I don't see why binding to non-const reference should be harder
> >than binding to const reference (which _is_ allowed).
>
> Let me try with an example. -- I am myself getting confused as to what the
> actual C++ has to keep track of, because I work more with figuring out how
> to work around the actual workings of the C++ compiler. :-)
>
> So let's view this code:
>   class A;
>   class B;
>
>   A a(B());
>
> Now, if we have declared
>   A::A(const B&);
> then the C++ compiler would invoke the copy constructor of the temporary
> object B()

I don't know why you would say that.

#include <iostream>

class B {
public:
  B() { std::cout << "B default ctor\n"; }
  B(const B&) { std::cout << "B copy ctor\n"; }
  ~B() { std::cout << "B dtor\n"; }
};

class A
{
public:
  A(const B&) {}
};

int main() {
  A a = A(B());
}

Compiles with a recent gcc and writes

B default ctor
B dtor

as would be expected.  There is no call to the copy constructor of B, we
passed only a const reference to the one and only instance of B which was
created by that program.

If we drop the "const" from A's constructor then the program fails to
compile.  If we change it to "A(B) { }" (i.e., pass by value) then a call
to the copy constructor would be expected.

> and it would not make any difference how long the original B()
> lives, as we will work with a copy of it.

There would be little difference.  The temporary survives to the end of
the full expression containing it, which is longer than the lifetime of
any copy which might be passed to A's constructor.

(Very old or very bad compilers might not implement the correct rules for
lifetimes of temporaries, but that's an aside.)

> But if we declare
>   A::A(B&);
> then there is a problem with "A a(B())", because we will get a reference
> to the original object B().

Just as we'd get a const reference if we added const, yes?

> It then implies that the original B() must be
> kept alive as long as it is in use via A::A(B&). The problem is though
> that we could have defined
>   class A {
>     B* b;
>   public:
>     A(B& b0) : b(b0) { }
>   };
> Or, even worse, A(B&) may transfer this pointer somewhere else.

Add "const" and you can code up this bug right now.  Object lifetimes in
C++ are brutal (as well as static) things.

Any way we look at it, passing by const reference is reckoned to be slightly
safer than passing by non-const reference.  Or maybe it's just that it's more
generally useful, so that the utility outweighs the danger.

-- James Dennett <jdennett@acm.org>

---
[ 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: James.Kanze@dresdner-bank.com
Date: 2000/11/14
Raw View
In article <3A031BE8.31433C1F@physik.tu-muenchen.de>,
  Christopher Eltschka <celtschk@physik.tu-muenchen.de> wrote:
> Hans Aberg wrote:

> > In article <3A01EE3A.9B5EE72C@evtechnology.com>, James Dennett
> > <james@evtechnology.com> wrote:
> > >There is a reference (posted elsewhere in this thread) to where the
> > >Standard bans the binding of temporaries to non-const references.
> > ...
> > >It's explicitly disallowed by the Standard, but not because it's
> > >hard to implement.  Rather because it was viewed as being a Bad
> > >Thing on balance...

> > No, the reason it was banned is not that it was bad, but because
> > it is hard to implement: One gets into the question of having
> > dynamic bindings, which is usually resolved by implementing a CGC
> > (conservative garbage collector), which keeps track of it.

> > But with a CGC in hand, it is not bad at all; it is the standard
> > thing.

> I don't see why binding to non-const reference should be harder than
> binding to const reference (which _is_ allowed).

It's actually easier for the compiler to allow both, as it eliminates
a special case.

Originally, C++ allowed binding a temporary to any reference, const or
not.  The rule against binding to a non-const reference was introduced
because it was found to be too error prone.  People often got
temporaries when they didn't expect it.  (The result of an implicit
conversion, for example, is a temporary.)

Many compiler still allow both, generally with a warning, for reasons
of backward compatibility.

> Note that this has nothing to do with GC (be it conservative or
> not). Temporary objects don't live on the heap, and therefore
> wouldn't get collected anyway. And if the next revision of C++
> required to put temporaries on the heap, I guess lots of people
> would stop using it for their projects (or would use older
> compilers, or compilers where you can switch that behaviour off).
> In short, it would do harm to the language.

> Also note that g++ supported binding of rvalues to non-const
> references for quite a long time - without any GC.

So does every other compiler I know of.  Generally, as I said, with a
warning.  And most have an option which will turn it off.

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


Sent via Deja.com http://www.deja.com/
Before you buy.

---
[ 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: remove.haberg@matematik.su.se (Hans Aberg)
Date: 2000/11/14
Raw View
In article <3A103C53.B7FA29FD@evtechnology.com>, James Dennett
<james@evtechnology.com> wrote:
>> Now, if we have declared
>>   A::A(const B&);
>> then the C++ compiler would invoke the copy constructor of the temporary
>> object B()
>
>I don't know why you would say that.

Assuming that A wants to make the B() live longer than the scope rules,
and not only manipulate it in a const way:

We create a temporary, and want to let it live indefinitely. The scope
rules are such that if you try that with the const version, when you go
out of scope, you must invoke the const copy constructor.

If you try to do the same thing with
    A::A(B&)
waht you would need is to force C++ to invoke the "dynamic" copy constructor
    B::B(B&);
However, C++ is written so that this is not invoked. Thus it is not
possible to write _safe_ bindings that way.

I am sorry if I cannot explain it better: I worked a lot on this several
years ago, until I discovered that C++ isn't written to support such
bindings that are _safe_. I do not remeber all the gory details anymore;
you or somebody else will have to figure them out.

Instead, the best one can do is to write another class
  B_ref {
    B* bp;
    ...
  };
and A above becomes
  A::A(B&)
or
  A::A(B)

>> It then implies that the original B() must be
>> kept alive as long as it is in use via A::A(B&). The problem is though
>> that we could have defined
>>   class A {
>>     B* b;
>>   public:
>>     A(B& b0) : b(b0) { }
>>   };
>> Or, even worse, A(B&) may transfer this pointer somewhere else.
>
>Add "const" and you can code up this bug right now.  Object lifetimes in
>C++ are brutal (as well as static) things.

This is not a bug: With a CGC in place, this would not have been a
problem, which is what I said all along. C++ does not allow it, because it
isn't _safe_ unless one implements something like a CGC. But with a CGC in
place -- no problem.

  Hans Aberg      * Anti-spam: remove "remove." from email address.
                  * Email: Hans Aberg <remove.haberg@member.ams.org>
                  * Home Page: <http://www.matematik.su.se/~haberg/>
                  * AMS member listing: <http://www.ams.org/cml/>

---
[ 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: remove.haberg@matematik.su.se (Hans Aberg)
Date: Sun, 12 Nov 2000 03:01:12 GMT
Raw View
In article <3A031BE8.31433C1F@physik.tu-muenchen.de>, Christopher Eltschka
<celtschk@physik.tu-muenchen.de> wrote:
>I don't see why binding to non-const reference should be harder
>than binding to const reference (which _is_ allowed).

Let me try with an example. -- I am myself getting confused as to what the
actual C++ has to keep track of, because I work more with figuring out how
to work around the actual workings of the C++ compiler. :-)

So let's view this code:
  class A;
  class B;

  A a(B());

Now, if we have declared
  A::A(const B&);
then the C++ compiler would invoke the copy constructor of the temporary
object B(), and it would not make any difference how long the original B()
lives, as we will work with a copy of it.

But if we declare
  A::A(B&);
then there is a problem with "A a(B())", because we will get a reference
to the original object B(). It then implies that the original B() must be
kept alive as long as it is in use via A::A(B&). The problem is though
that we could have defined
  class A {
    B* b;
  public:
    A(B& b0) : b(b0) { }
  };
Or, even worse, A(B&) may transfer this pointer somewhere else.

It is no longer possible to figure out how long time the original B() is
bound by static scope rules within the C++ language.

On the other hand, a conservative GC will kept alive track of such dynamic
bindings: B() will be kept alive as long as there are pointers to it
somehow derived from the root set. When no such pointers longer exists to
B(), it may at some point be deleted.

An interesting question in this context is what happens with the
destructor B::~B(): There is no way for the object itself knowing when
this should be applied. Normally it would not be needed, but sometimes one
must perform special actions. Then I figure the CGC would invoke it when
it discovers the B() is no longer referenced. -- Perhaps this has
something to do with the "finalizing" in Java.

>Note that this has nothing to do with GC (be it conservative or
>not). Temporary objects don't live on the heap, and therefore
>wouldn't get collected anyway. And if the next revision of C++
>required to put temporaries on the heap, I guess lots of people
>would stop using it for their projects (or would use older
>compilers, or compilers where you can switch that behaviour off).
>In short, it would do harm to the language.

Once has moved into the domain of dynamic bindings, one has little choice
but to figure out a way to keep track of it, no matter what the cost is in
performance. Remember that a reason that one moves into the dynamic domain
is often that one wants to allow more structured runtime objects. So from
that point of view, one has little choice but to accept lower speeds, and
hoping for faster computers.

But just because one allows dynamic bindings in C++, it does not mean that
one has to scrap the static bindings. -- The latter can be kept in the
name of efficiency. So you will have your choice: Use dynamic bindings
when circumstances demands that; otherwise use static bindings.

Also, one reason that dynamic allocations are so slow seems to be poor
allocation algorithms: A lot has happened in this area recently. In
addition, I figure one will in the future see more hardware support for it
too.

  Hans Aberg      * Anti-spam: remove "remove." from email address.
                  * Email: Hans Aberg <remove.haberg@member.ams.org>
                  * Home Page: <http://www.matematik.su.se/~haberg/>
                  * AMS member listing: <http://www.ams.org/cml/>

---
[ 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: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 2000/11/10
Raw View
Hans Aberg wrote:
>
> In article <3A01EE3A.9B5EE72C@evtechnology.com>, James Dennett
> <james@evtechnology.com> wrote:
> >There is a reference (posted elsewhere in this thread) to where the
> >Standard bans the binding of temporaries to non-const references.
> ...
> >It's explicitly disallowed by the Standard, but
> >not because it's hard to implement.  Rather because it was viewed as being
> >a Bad Thing on balance...
>
> No, the reason it was banned is not that it was bad, but because it is
> hard to implement: One gets into the question of having dynamic bindings,
> which is usually resolved by implementing a CGC (conservative garbage
> collector), which keeps track of it.
>
> But with a CGC in hand, it is not bad at all; it is the standard thing.

I don't see why binding to non-const reference should be harder
than binding to const reference (which _is_ allowed).

Note that this has nothing to do with GC (be it conservative or
not). Temporary objects don't live on the heap, and therefore
wouldn't get collected anyway. And if the next revision of C++
required to put temporaries on the heap, I guess lots of people
would stop using it for their projects (or would use older
compilers, or compilers where you can switch that behaviour off).
In short, it would do harm to the language.

Also note that g++ supported binding of rvalues to non-const
references for quite a long time - without any GC.

---
[ 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: remove.haberg@matematik.su.se (Hans Aberg)
Date: 2000/11/10
Raw View
In article <3A031BE8.31433C1F@physik.tu-muenchen.de>, Christopher Eltschka
<celtschk@physik.tu-muenchen.de> wrote:
>I don't see why binding to non-const reference should be harder
>than binding to const reference (which _is_ allowed).

You bind it to an object whose life span normally cannot be predicted by
C++ context (blocks etc), but in the worst case only by runtime
considerations.

>Note that this has nothing to do with GC (be it conservative or
>not). Temporary objects don't live on the heap, and therefore
>wouldn't get collected anyway.

The temporaries are put into "registers", and belong to the root system;
also add global and stack data to the root system: One starts with the
root system, and those object that should be kept alive are those that can
be traced from the root system.

> And if the next revision of C++
>required to put temporaries on the heap, I guess lots of people
>would stop using it for their projects (or would use older
>compilers, or compilers where you can switch that behavior off).

I think the situation we have here is the other way around: You bind data
to a temporary, but you do not know how long time the temporary will live.
Thus you need a way to figure out to delete the object bound to the
temporary.

A CGC would keep track of this by adding the temporary to the root system.
At GC time, the CGC would trace all live objects, and the others will
marked as free space.

Note that the situation can be more complicated: First you bind data to a
temporary, and then that temporary may bind that data to another object,
which may be another temporary or whatever. The CGC keeps track of that,
too.

  Hans Aberg      * Anti-spam: remove "remove." from email address.
                  * Email: Hans Aberg <remove.haberg@member.ams.org>
                  * Home Page: <http://www.matematik.su.se/~haberg/>
                  * AMS member listing: <http://www.ams.org/cml/>

---
[ 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: James Dennett <james@evtechnology.com>
Date: 2000/11/04
Raw View
Hans Aberg wrote:
>
> In article <3A01EE3A.9B5EE72C@evtechnology.com>, James Dennett
> <james@evtechnology.com> wrote:
> >There is a reference (posted elsewhere in this thread) to where the
> >Standard bans the binding of temporaries to non-const references.
> ...
> >It's explicitly disallowed by the Standard, but
> >not because it's hard to implement.  Rather because it was viewed as being
> >a Bad Thing on balance...
>
> No, the reason it was banned is not that it was bad, but because it is
> hard to implement:

So, what is the difference between the case of binding a const reference to
a temporary (which *is implemented in Standard C++) and binding a non-const
reference?  How can one be easy to implement but not the other?

Granted, the C++ implementation doesn't avoid dangling references, but there's
no difference for the const-ness of the reference.

If you want to avoid dangling references, you're trying to solve another
problem, which C++ doesn't address.

> One gets into the question of having dynamic bindings,
> which is usually resolved by implementing a CGC (conservative garbage
> collector), which keeps track of it.
>
> But with a CGC in hand, it is not bad at all; it is the standard thing.

To slip into subjectivity:

C++ should always be designed to that it *can* run without GC.  Ideally it
should also remain implementable with GC too.  Choice is the C++ way, if I
may make ridiculous generalisations about the "spirit of C++".

-- James Dennett <jdennett@acm.org>

---
[ 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: remove.haberg@matematik.su.se (Hans Aberg)
Date: 2000/11/06
Raw View
In article <3A042983.2A3C9E47@evtechnology.com>, James Dennett
<james@evtechnology.com> wrote:
>> >There is a reference (posted elsewhere in this thread) to where the
>> >Standard bans the binding of temporaries to non-const references.
>> ...
>> >It's explicitly disallowed by the Standard, but
>> >not because it's hard to implement.  Rather because it was viewed as being
>> >a Bad Thing on balance...
>>
>> No, the reason it was banned is not that it was bad, but because it is
>> hard to implement:
>
>So, what is the difference between the case of binding a const reference to
>a temporary (which *is implemented in Standard C++) and binding a non-const
>reference?  How can one be easy to implement but not the other?

The way one implement dynamic bindings to a reference is this: One uses
pointer, which may or may not become outdated. In order to figure out
which pointers are outdated or not, one searches all pointers allocated in
global data, the parameter stack, and temporarily allocated in registers.
This is called the "root set". Then you trace forward to all pointers you
can find from the root set. At any time, this is the set of active data
referenced.

There is really no other way to determine which references that are
active, even though there are several methods to not bother finding the
exact set of active pointers. One simple method used by the OS (operative
system) is to put all data of a program, and then deleted it all when the
program terminates. Thus all references of the program are cleanupped.

>C++ should always be designed to that it *can* run without GC.  Ideally it
>should also remain implementable with GC too.  Choice is the C++ way, if I
>may make ridiculous generalisations about the "spirit of C++".

If we start discussing the GC question, then there probably will be a long
thread here... :-) Also note that if you use C++ "new" and "delete", then
that is a form of GC (by "delete").

But if the program is allowed to dynamically create references, then there
is no way to avoid memory leaks without having a CGC of some sort: If one
creates a circular object, then it will not be otherwise deleted.

So, one gets into the problem of implementing CGC's somehow.

Then, one can discuss in infinity as to what the advantages and
disadvantages of different GC's are: A lot seems to happen on this topic
these days.

I think therefore that the new C++ revision must allow one to use
different GC's on different types of data. To some extent C++ already
does:

The thing though, is that it is not possible for say a C++ class hierarchy
finding the root set, and then trace the pointers that may refer to data
of that class hierarchy. C++ support for this seems necessary as other
solutions seems slow (and the whole point of using a particular type of GC
is to make dynamic allocation fast without causing memory leaks).

Note here that there is a very simple type of GC: Simply never deallocate
any memory at all (set "delete" always to empty). If you are under an OS
that uses paged memory and give your program a full separate memory space
(4 GB when using 32-bit addresses), the unused pages will simply be paged
out, unless you are unlucky with memory fragmentation. You may of course
run out of memory: If you succeed to restart your program with its current
state, then this is called a "two-space GC" (or something).

  Hans Aberg      * Anti-spam: remove "remove." from email address.
                  * Email: Hans Aberg <remove.haberg@member.ams.org>
                  * Home Page: <http://www.matematik.su.se/~haberg/>
                  * AMS member listing: <http://www.ams.org/cml/>

---
[ 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: remove.haberg@matematik.su.se (Hans Aberg)
Date: Thu, 2 Nov 2000 21:55:25 GMT
Raw View
In article <3A00A8FA.BE5E408@sensor.com>, Ron Natalie <ron@sensor.com> wrote:
>Try paragraph five of 8.5.3 (Initialization of references).  THe
>first part says that the reference shall be initialized to an
>lvalue (or something converted to one) or it shall the reference
>shall be const.  Temporaries are not lvalues.

I felt this wasn't it, because C++ seems to have no objections about
binding ref's to temporary objects.

The limitation of not binding lvalues to temporaries seems me has to do
with that C++ want to be able to decide the lifespan of temporaries by
static block scope alone (thus avoiding dynamic scope).

  Hans Aberg      * Anti-spam: remove "remove." from email address.
                  * Email: Hans Aberg <remove.haberg@member.ams.org>
                  * Home Page: <http://www.matematik.su.se/~haberg/>
                  * AMS member listing: <http://www.ams.org/cml/>

---
[ 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: James Dennett <james@evtechnology.com>
Date: Thu, 2 Nov 2000 22:47:33 GMT
Raw View
Hans Aberg wrote:
>
> In article <3A00AA94.B64F7421@evtechnology.com>, James Dennett
> <james@evtechnology.com> wrote:
> >> >> >>  reassign(std::cerr, std::ofstream("log.txt"));
> ...
> >I may be in error here; I was thinking of the case of binding a temporary to
> >a local variable.  The referenced variable is required to survive for the
> >lifetime of the const reference to which it is bound.
>
> Because there is no problem to statically decide figure out how long time
> std::ofstream("log.txt") must survive here, it should pose no problem
> implementing it.

Indeed, the compilers I use do implement it for _const_ references.

> The difficulty seems to find a reference in the standard for it...

There is a reference (posted elsewhere in this thread) to where the
Standard bans the binding of temporaries to non-const references.

To quote Ron Natalie's message (also in this discussion):

> Try paragraph five of 8.5.3 (Initialization of references).  THe
> first part says that the reference shall be initialized to an
> lvalue (or something converted to one) or it shall the reference
> shall be const.  Temporaries are not lvalues.

So, there you have it.  It's explicitly disallowed by the Standard, but
not because it's hard to implement.  Rather because it was viewed as being
a Bad Thing on balance.  Certainly there are pieces of code which are
slightly simplified if we allow binding non-const references to temporaries
but they are rare and easily worked around, whereas the mistakes which
could be made would be relatively common and possible hard to track down.
On this occasion, C++ errs on the side of safety.  If only it did so more
often ;)

-- James Dennett <jdennett@acm.org>

---
[ 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: remove.haberg@matematik.su.se (Hans Aberg)
Date: 2000/11/03
Raw View
In article <3A01EE3A.9B5EE72C@evtechnology.com>, James Dennett
<james@evtechnology.com> wrote:
>There is a reference (posted elsewhere in this thread) to where the
>Standard bans the binding of temporaries to non-const references.
...
>It's explicitly disallowed by the Standard, but
>not because it's hard to implement.  Rather because it was viewed as being
>a Bad Thing on balance...

No, the reason it was banned is not that it was bad, but because it is
hard to implement: One gets into the question of having dynamic bindings,
which is usually resolved by implementing a CGC (conservative garbage
collector), which keeps track of it.

But with a CGC in hand, it is not bad at all; it is the standard thing.

  Hans Aberg      * Anti-spam: remove "remove." from email address.
                  * Email: Hans Aberg <remove.haberg@member.ams.org>
                  * Home Page: <http://www.matematik.su.se/~haberg/>
                  * AMS member listing: <http://www.ams.org/cml/>

---
[ 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: Ron Natalie <ron@sensor.com>
Date: Wed, 1 Nov 2000 23:35:21 GMT
Raw View
Try paragraph five of 8.5.3 (Initialization of references).  THe
first part says that the reference shall be initialized to an
lvalue (or something converted to one) or it shall the reference
shall be const.  Temporaries are not lvalues.

---
[ 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: James Dennett <james@evtechnology.com>
Date: Thu, 2 Nov 2000 15:53:15 GMT
Raw View
Hans Aberg wrote:
>
> In article <3A005978.E08EC9FB@evtechnology.com>, James Dennett
> <james@evtechnology.com> wrote:
> >> >>  reassign(std::cerr, std::ofstream("log.txt"));
> ...
> >> I don't see there is any problems with this line: all it means that the
> >> temporary must exist as long as it is bound (to reassign() in this case).
> >
> >You cannot bind a temporary (an lvalue) to a non-const reference.
> >
> >If you change the reference to const then IIRC the object would survive
> >to the end of the block, but that still wouldn't be long enough.  Holding
> >a const reference to a temporary as a data member sounds pretty dangerous
> >to me.
>
> You will have to explain why it (semantically) should need to survive to
> the end of the block, as it suffices in this case that it survives only as
> long as reassign() is called.

I may be in error here; I was thinking of the case of binding a temporary to
a local variable.  The referenced variable is required to survive for the
lifetime of the const reference to which it is bound.  In your case, that
would indeed be the duration of the function call; I believe that the temporary
could be destroyed at the end of the associated full expression.

-- James Dennett <jdennett@acm.org>

---
[ 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: remove.haberg@matematik.su.se (Hans Aberg)
Date: Thu, 2 Nov 2000 21:07:16 GMT
Raw View
In article <3A00AA94.B64F7421@evtechnology.com>, James Dennett
<james@evtechnology.com> wrote:
>> >> >>  reassign(std::cerr, std::ofstream("log.txt"));
...
>I may be in error here; I was thinking of the case of binding a temporary to
>a local variable.  The referenced variable is required to survive for the
>lifetime of the const reference to which it is bound.

Because there is no problem to statically decide figure out how long time
std::ofstream("log.txt") must survive here, it should pose no problem
implementing it.

The difficulty seems to find a reference in the standard for it...

  Hans Aberg      * Anti-spam: remove "remove." from email address.
                  * Email: Hans Aberg <remove.haberg@member.ams.org>
                  * Home Page: <http://www.matematik.su.se/~haberg/>
                  * AMS member listing: <http://www.ams.org/cml/>

---
[ 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: remove.haberg@matematik.su.se (Hans Aberg)
Date: Wed, 1 Nov 2000 16:45:54 GMT
Raw View
In article <39fece69.343875997@reading.news.pipex.net>,
the_wid@my-deja.com (Tom) wrote:
>>  reassign(std::cerr, std::ofstream("log.txt"));
>
>The line above is not legal C++ - you are binding a temporary to a
>non-const reference. If your (broken) compiler compiles this, then you
>have the problem of the ofstream destructing at the end of the line.

I don't see there is any problems with this line: all it means that the
temporary must exist as long as it is bound (to reassign() in this case).

  Hans Aberg      * Anti-spam: remove "remove." from email address.
                  * Email: Hans Aberg <remove.haberg@member.ams.org>
                  * Home Page: <http://www.matematik.su.se/~haberg/>
                  * AMS member listing: <http://www.ams.org/cml/>

---
[ 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: James Dennett <james@evtechnology.com>
Date: Wed, 1 Nov 2000 18:34:17 GMT
Raw View
Hans Aberg wrote:
>
> In article <39fece69.343875997@reading.news.pipex.net>,
> the_wid@my-deja.com (Tom) wrote:
> >>  reassign(std::cerr, std::ofstream("log.txt"));
> >
> >The line above is not legal C++ - you are binding a temporary to a
> >non-const reference. If your (broken) compiler compiles this, then you
> >have the problem of the ofstream destructing at the end of the line.
>
> I don't see there is any problems with this line: all it means that the
> temporary must exist as long as it is bound (to reassign() in this case).

You cannot bind a temporary (an lvalue) to a non-const reference.

If you change the reference to const then IIRC the object would survive
to the end of the block, but that still wouldn't be long enough.  Holding
a const reference to a temporary as a data member sounds pretty dangerous
to me.

-- James Dennett <jdennett@acm.org>

---
[ 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: the_wid@my-deja.com (Tom)
Date: Wed, 1 Nov 2000 19:20:10 GMT
Raw View
On Wed,  1 Nov 2000 16:45:54 GMT, remove.haberg@matematik.su.se (Hans
Aberg) wrote:

>In article <39fece69.343875997@reading.news.pipex.net>,
>the_wid@my-deja.com (Tom) wrote:
>>>  reassign(std::cerr, std::ofstream("log.txt"));
>>
>>The line above is not legal C++ - you are binding a temporary to a
>>non-const reference. If your (broken) compiler compiles this, then you
>>have the problem of the ofstream destructing at the end of the line.
>
>I don't see there is any problems with this line: all it means that the
>temporary must exist as long as it is bound (to reassign() in this case).

Oops, I actually read it as:

reassign rass(std::cerr, std::ofstream("log.txt"));

At the end of the above statement, the ofstream created is destroyed
which means that when rass destructs, you'll have undefined behaviour.
If it compiles at all (which it shouldn't).

What you actually said was that your compiler optimizes away the
following line:
reassign(std::cerr, std::ofstream("log.txt"));
This is not surprising, since it creates a temporary reassign object,
which is destroyed at the end of the line, returning cerr to its
original state. However, as I said, it is ill-formed C++ code. You
cannot bind a non-const reference (the second arg of your reassign
constructor) to a temporary.

Your original code is fine, of course, since the ofstream will outlive
rass as required, and is not a temporary.
std::ofstream flog("log.txt");
reassign rass(std::cerr, flog);

Tom

---
[ 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: remove.haberg@matematik.su.se (Hans Aberg)
Date: Wed, 1 Nov 2000 19:26:07 GMT
Raw View
In article <3A005978.E08EC9FB@evtechnology.com>, James Dennett
<james@evtechnology.com> wrote:
>> >>  reassign(std::cerr, std::ofstream("log.txt"));
...
>> I don't see there is any problems with this line: all it means that the
>> temporary must exist as long as it is bound (to reassign() in this case).
>
>You cannot bind a temporary (an lvalue) to a non-const reference.
>
>If you change the reference to const then IIRC the object would survive
>to the end of the block, but that still wouldn't be long enough.  Holding
>a const reference to a temporary as a data member sounds pretty dangerous
>to me.

You will have to explain why it (semantically) should need to survive to
the end of the block, as it suffices in this case that it survives only as
long as reassign() is called.

It may be one thing if C++ does not admit this construction, but
semantically I do not see a problem with this type of construction. And
with other such more long-lived bindings, one gets into the standard CGC
(conservative garbage collector) question.

But in this case one only needs to puit the temporary into a register
while reassign() is called, so the limitation seems strange.

  Hans Aberg      * Anti-spam: remove "remove." from email address.
                  * Email: Hans Aberg <remove.haberg@member.ams.org>
                  * Home Page: <http://www.matematik.su.se/~haberg/>
                  * AMS member listing: <http://www.ams.org/cml/>

---
[ 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: remove.haberg@matematik.su.se (Hans Aberg)
Date: Wed, 1 Nov 2000 21:32:47 GMT
Raw View
In article <3a0051d6.2986163@reading.news.pipex.net>, the_wid@my-deja.com
(Tom) wrote:
> However, as I said, it is ill-formed C++ code. You
>cannot bind a non-const reference (the second arg of your reassign
>constructor) to a temporary.

The funny thing is that I looked into the C++ standard, and I could not
find any reference for it. Can you provide the quote?

Semantically, I see no problems with such bindings -- the only problem is
how much should be required of a C++ compiler. Evidently, one felt when
creating the C++ standard that not too much should be required of the C++
compiler implementations.

  Hans Aberg      * Anti-spam: remove "remove." from email address.
                  * Email: Hans Aberg <remove.haberg@member.ams.org>
                  * Home Page: <http://www.matematik.su.se/~haberg/>
                  * AMS member listing: <http://www.ams.org/cml/>

---
[ 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: the_wid@my-deja.com (Tom)
Date: Tue, 31 Oct 2000 18:05:59 GMT
Raw View
On Mon, 30 Oct 2000 19:48:11 GMT, remove.haberg@matematik.su.se (Hans
Aberg) wrote:

>Then
>  std::ofstream flog("log.txt");
>  reassign rass(std::cerr, flog);
>will reassign as long as the automatic object is in scope, and one
>needs not worry about exceptions and such, because the destructors will
>always be called in the correct order. (Incidentally, I discovered that
>my compiler will optimize away
>  reassign(std::cerr, std::ofstream("log.txt"));

The line above is not legal C++ - you are binding a temporary to a
non-const reference. If your (broken) compiler compiles this, then you
have the problem of the ofstream destructing at the end of the line.

>But then, returning to the C++ standard, should one not expect such stuff
>be in it, so that programmers need not worry about it?

There's a lot of stuff that could be in it that isn't - including some
exception safety classes like yours (auto_ptr is all we get!). But the
smaller it is, the more likely a particular implementation is to be
both complete and relatively bug free. And the fact is we have a C++
standard now - had they (the standards committee) included everything
they wanted to, I expect they'd still be working on the draft.

Tom

---
[ 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: remove.haberg@matematik.su.se (Hans Aberg)
Date: Tue, 31 Oct 2000 20:56:54 GMT
Raw View
In article <39fece69.343875997@reading.news.pipex.net>,
the_wid@my-deja.com (Tom) wrote:
>>But then, returning to the C++ standard, should one not expect such stuff
>>be in it, so that programmers need not worry about it?
>
>There's a lot of stuff that could be in it that isn't - including some
>exception safety classes like yours (auto_ptr is all we get!). But the
>smaller it is, the more likely a particular implementation is to be
>both complete and relatively bug free. And the fact is we have a C++
>standard now - had they (the standards committee) included everything
>they wanted to, I expect they'd still be working on the draft.

I think that one principle ought to be that if C has a safety high-level
command, freopen() in this case, then if C++ introduces new C++ paradigms
that are such that one should be able to use them as replacements of the
corresponding C constructs, the streams replace FILE* in this case, then
it should also have the corresponding C++ high-level command doing at
least as good as C.

But it is a fact that there is no suitable C++ replacement for the C
freopen(), even though one can get around it by low-level buffer
programming.

Your argument is otherwise just called "pragmatics": Once the general
principles have been laid down, one say that this or that could not be
entered the standard because of lack of time or space or something.

  Hans Aberg      * Anti-spam: remove "remove." from email address.
                  * Email: Hans Aberg <remove.haberg@member.ams.org>
                  * Home Page: <http://www.matematik.su.se/~haberg/>
                  * AMS member listing: <http://www.ams.org/cml/>

---
[ 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: remove.haberg@matematik.su.se (Hans Aberg)
Date: Mon, 30 Oct 2000 19:48:11 GMT
Raw View
In article <39f77770.3446965@news.ntlworld.com>, the_wid@my-deja.com (Tom)
wrote:
>>The standard seems to not tell how to deflect the standard streams
>>std::cin, std::cout, std::cerr, std::clog to other i/o-streams... So
>>what is the suggested way to deflect those streams?
>
>ofstream flog("log.txt");  [This line changed by HA.]
>//save old target
>streambuf* oldcoutbuf = cout.rdbuf();
>//change target
>cout.rdbuf(flog.rdbuf());
>cout << "Boo!\n"; //goes to file
>//reset cout
>cout.rdbuf(oldcoutbuf);

The code aboove has a problem, namely, if one does not reset cout,
there might be a problem with the destructors of cout & log when the
program exits (the destructor of the "flog" buffer may be called twice,
by cout and flog, and the destructor buffer of cout not at all).

The standard way around this is to write a class with constructors/
destructors handling the stream deflection:
  class reassign {
    streambuf* buf_save;
    ostream* os_save;
  public:
    reassign(ostream& os1, ostream& os2)
     : buf_save(os1.rdbuf()), os_save(&os1) {
      os1.rdbuf(os2.rdbuf());
    }
    ~reassign() { os_save->rdbuf(buf_save); }
  };

Then
  std::ofstream flog("log.txt");
  reassign rass(std::cerr, flog);
will reassign as long as the automatic object is in scope, and one
needs not worry about exceptions and such, because the destructors will
always be called in the correct order. (Incidentally, I discovered that
my compiler will optimize away
  reassign(std::cerr, std::ofstream("log.txt"));
.)

But then, returning to the C++ standard, should one not expect such stuff
be in it, so that programmers need not worry about it?

  Hans Aberg      * Anti-spam: remove "remove." from email address.
                  * Email: Hans Aberg <remove.haberg@member.ams.org>
                  * Home Page: <http://www.matematik.su.se/~haberg/>
                  * AMS member listing: <http://www.ams.org/cml/>

---
[ 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: remove.haberg@matematik.su.se (Hans Aberg)
Date: 2000/10/25
Raw View
The standard seems to not tell how to deflect the standard streams
std::cin, std::cout, std::cerr, std::clog to other i/o-streams: Under C,
one can choose freopen, and once upon the time, the C++ standard streams
were "streams with assign", which is mentioned nowhere in the standard. So
what is the suggested way to deflect those streams? Also, the standard
seems to not explain the difference between std::cerr and std::clog; their
definition appears to be the same.

  Hans Aberg      * Anti-spam: remove "remove." from email address.
                  * Email: Hans Aberg <remove.haberg@member.ams.org>
                  * Home Page: <http://www.matematik.su.se/~haberg/>
                  * AMS member listing: <http://www.ams.org/cml/>

---
[ 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: the_wid@my-deja.com (Tom)
Date: Thu, 26 Oct 2000 14:36:48 GMT
Raw View
On Wed, 25 Oct 2000 18:10:18 GMT, remove.haberg@matematik.su.se (Hans
Aberg) wrote:

>The standard seems to not tell how to deflect the standard streams
>std::cin, std::cout, std::cerr, std::clog to other i/o-streams: Under C,
>one can choose freopen, and once upon the time, the C++ standard streams
>were "streams with assign", which is mentioned nowhere in the standard. So
>what is the suggested way to deflect those streams? Also, the standard
>seems to not explain the difference between std::cerr and std::clog; their
>definition appears to be the same.

ifstream log("log.txt");
//save old target
streambuf* oldcoutbuf = cout.rdbuf();
//change target
cout.rdbuf(log.rdbuf());
cout << "Boo!\n"; //goes to file
//reset cout
cout.rdbuf(oldcoutbuf);

clog is buffered for performance, while cerr is unbuffered for
immediate output.

Tom

---
[ 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: Michiel Salters <salters@lucent.com>
Date: Thu, 26 Oct 2000 14:37:14 GMT
Raw View
Hans Aberg wrote:

> The standard seems to not tell how to deflect the standard streams
> std::cin, std::cout, std::cerr, std::clog to other i/o-streams: Under C,
> one can choose freopen, and once upon the time, the C++ standard streams
> were "streams with assign", which is mentioned nowhere in the standard. So
> what is the suggested way to deflect those streams?

Assuming the meaning of "deflection" is redirection from/to another streambuf
cq. destiantion, the answer is trivial: provide another streambuf/destination.

The appropriate function would be rdbuf().

Michiel Salters

---
[ 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: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: Thu, 26 Oct 2000 16:31:58 GMT
Raw View
Tom wrote:
>
> On Wed, 25 Oct 2000 18:10:18 GMT, remove.haberg@matematik.su.se (Hans
> Aberg) wrote:
>
> >The standard seems to not tell how to deflect the standard streams
> >std::cin, std::cout, std::cerr, std::clog to other i/o-streams: Under C,
> >one can choose freopen, and once upon the time, the C++ standard streams
> >were "streams with assign", which is mentioned nowhere in the standard. So
> >what is the suggested way to deflect those streams? Also, the standard
> >seems to not explain the difference between std::cerr and std::clog; their
> >definition appears to be the same.
>
> ifstream log("log.txt");
> //save old target
> streambuf* oldcoutbuf = cout.rdbuf();
> //change target
> cout.rdbuf(log.rdbuf());
> cout << "Boo!\n"; //goes to file
> //reset cout
> cout.rdbuf(oldcoutbuf);
>
> clog is buffered for performance, while cerr is unbuffered for
> immediate output.

Are clog and cerr synchronized?
That is, assuming I write the following code:

  std::cerr << "This does ";
  std::clog << "not ";
  std::cerr << "change the order of output.\nThe word order is ";
  std::clog << "preserved." << std::endl;

Am I guaranteed to get

  This does not change the order of output.
  The word order is preserved.

or could I get

  This does change the order of output.
  The word order is not preserved.

or even (due to intermediate flush of clog - ok, unprobable in this
example):

  This does nochange the order of output.
  The word order is t preserved.

?

---
[ 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: remove.haberg@matematik.su.se (Hans Aberg)
Date: Thu, 26 Oct 2000 17:50:11 GMT
Raw View
In article <39f77770.3446965@news.ntlworld.com>, the_wid@my-deja.com (Tom)
wrote:
>clog is buffered for performance, while cerr is unbuffered for
>immediate output.

[Thank you for your example.]

The C++ standard, 27.3.1, "Narrow stream objects", says:

4 The object cerr controls output to a stream buffer associated with the
object stderr, declared in <cstdio> (27.8.2).
6 The object clog controls output to a stream buffer associated with the
object stderr, declared in <cstdio> (27.8.2).

So even if the idea with different bufferings seems good, it appears to
not be defined in the C++ standard.

  Hans Aberg      * Anti-spam: remove "remove." from email address.
                  * Email: Hans Aberg <remove.haberg@member.ams.org>
                  * Home Page: <http://www.matematik.su.se/~haberg/>
                  * AMS member listing: <http://www.ams.org/cml/>

---
[ 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: joerg.barfurth@attglobal.net (Joerg Barfurth)
Date: Thu, 26 Oct 2000 23:46:18 GMT
Raw View
Hans Aberg <remove.haberg@matematik.su.se> wrote:

> In article <39f77770.3446965@news.ntlworld.com>, the_wid@my-deja.com (T=
om)
> wrote:
> >clog is buffered for performance, while cerr is unbuffered for
> >immediate output.

> The C++ standard, 27.3.1, "Narrow stream objects", says:
>=20
> 4 The object cerr controls output to a stream buffer associated with th=
e
> object stderr, declared in <cstdio> (27.8.2).

5 After the object cerr is initialized, cerr.flags() & unitbuf is
nonzero [...]

> 6 The object clog controls output to a stream buffer associated with th=
e
> object stderr, declared in <cstdio> (27.8.2).
>=20
> So even if the idea with different bufferings seems good, it appears to
> not be defined in the C++ standard.

You left out p 5, which is the important one for this point.

27.4.2.1.2 describes the type std::ios_base::fmtflags. In particular
Table 83 describes the effects if certain flags of that bitmask type are
set.=20

It describes the effect of std::ios_base::unitbuf as=20

  "flushes output after each output operation".=20

This amounts to behavior that resembles really unbuffered output.

Of course this, as specified, describes the initial behavior only. If
you subsequently unset unitbuf in cerr and set it in clog, the roles of
these streams would be reversed.

Regards, J=F6rg

--=20
J=F6rg Barfurth                         joerg.barfurth@attglobal.net
-------------- using std::disclaimer; -----------------------------
Download:     StarOffice 5.2 at       http://www.sun.com/staroffice
Participate:  OpenOffice now at       http://www.OpenOffice.org

---
[ 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: James Kuyper <kuyper@wizard.net>
Date: Fri, 27 Oct 2000 13:30:19 GMT
Raw View
Christopher Eltschka wrote:
>
> Tom wrote:
...
> > clog is buffered for performance, while cerr is unbuffered for
> > immediate output.
>
> Are clog and cerr synchronized?

Both clog and cerr are described as controlling "output to a stream
buffer associated with the object stderr, declared in <cstdio>".

I conclude that they're both buffered, but it's not clear to me whether
they're required/allowed to use the same buffer. The only difference
between them is that "After the object cerr is initialized,
cerr.flags()& unitbuf is nonzero.", which means that "output is flushed
after each output operation". That's not quite the same as being
unbuffered.

---
[ 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.     ]