Topic: Exceptions and dtor
Author: deef@teleport.com (Derek Foster)
Date: 1995/12/12 Raw View
In <9512071429.AA03532@titania.hai.siemens.co.at> mueller@titania.hai.siemens.co.at (Harald M. Mueller) writes:
>The other day I had a nice idea how one (i.e. the C++ standardization
>committee - if it would still be willing to change the semantics of
>the language) could solve all these problems with exceptions and
>destructors.
I also think they could solve it, with a bit of change to the language. The
current situation (calling terminate()) seems to me to be extremely unsafe,
and a very poor way to handle exceptions thrown while unwinding exceptions.
Once inside terminate(), we have absolutely no way to determine what
happened, where it happened, or to prioritize exceptions and continue on. If
we ever, ever, even accidentally and indirectly, throw an exception from a
destructor, we risk this happening. In applications of mine, this has been a
serious problem, and has necessitated putting a try..catch block around the
body of many destructors, just in case they _somehow_ throw an exception.
The question remains, however, just how to handle an error that occurs in a
destructor (e.g. an attempt to close a file fails, an attempt to deallocate
an object fails, etc.) We can't safely throw an exception, setting a flag
won't in general work (how could you check for it being set?), etc.
To solve the situation, I had an idea quite similar to yours, but with
slightly different syntax and semantics. I would be curious if others see
problems with this proposal:
class MyClass
{
public:
MyClass();
~MyClass();
~catch(ReallyCriticalError &); // called instead of destructor if stack
~catch(SemiCriticalError &); // unwinding is due to thrown exception
// of these types.
};
MyClass::~MyClass()
{
// Since ~catch clauses exist, this destructor is never called as
// a result of stack unwinding. So throwing is always OK here.
destructor_stuff();
if (phaseOfMoon() == FULL)
throw WrongPhaseOfMoon();
}
// There is an implicit 'throw;' executed for any '~catch' function
// that does not exit via a thrown exception. In other words, a
// '~catch' function cannot exit without throwing an exception,
// either the one that was used to enter it, or another of its
// choosing.
MyClass::~catch(ReallyCriticalError &)
{
// Since this is a horrendously critical error, we just want to
// pass on the exception.
// We might even want to skip some steps of destruction here, if
// the exception implies that they can't be done. (e.g. skip the
// 'delete' operations if the 'HeapIsCorrupted' exception is being
// thrown.)
if (destruction_is_safe())
destructor_stuff();
}
MyClass::~catch(SemiCriticalError &)
{
// This error is less critical than the program being run in the wrong
// phase of the moon. So if the phase is wrong, throw the
// WrongPhaseOfMoon exception in preference to this one.
// Otherwise, continue throwing this one.
destructor_stuff();
if (phaseOfMoon() == FULL)
throw WrongPhaseOfMoon();
}
Derek Riippa Foster
--
deef@teleport.com Public Access User --- Not affiliated with TECHbooks
Public Access UNIX and Internet at (503) 220-1016 (2400-14400, N81)
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: chase@centerline.com (David Chase)
Date: 1995/12/13 Raw View
In article 8LA@research.att.com, ark@research.att.com (Andrew Koenig) writes:
> In article <49tuq4$238@wcap.centerline.com> chase@centerline.com writes:
> > The first problem I have is that my reading of this is that a
> > destructor invoked because a block is exited non-exceptionally, can
> > throw an exception WITHOUT causing terminate to be called. But, if
> > that destructor is called be the block is exited exceptionally,
> > terminate is not called. This seems, to me, to be a weird
> > inconsistency. (How could someone writing a destructor know the cause
> > of their call?) Is this just an oversight?
> It is not an oversight. One reason for the distinction is that otherwise
> it would have been necessary to draw a clearly visible dividing line between
> when end-of-block destruction of objects starts and when it has not started
> yet. But other things, such as compiler-generated temporaries, are destroyed
> during a block before any kind of stack unwinding starts, and their destructors
> could throw exceptions too.
> So instead we take the view that there's this system-defined thing called
> stack unwinding that happens only as part of exception handling. Exiting
> from user code by an exception is OK, even if that user code is in the process
> of destroying local objects. Exiting from stack unwinding by an exception
> is not OK.
> You may be right. The reason the prohibition is there is that while unwinding
> is in progress there is an object that must eventually be cleaned up, namely
> the object that was thrown. What if that object's destructor throws an exception?
> More generally, we opted for the draconian treatment because liberalizing it
> is easier than making something stricter that was inadvertently too liberal.
This is the counter-example that give me pause, yes. I still think my choice is
better, but I think I need to explain why, and how I approach the problem.
First of all, this differing treatment for destructors throwing
exceptions seems odd, especially when the user has essentially no way
of testing for "unwinding" or controlling the behavior (this is not
unlike the fuss over DEC-SRC's choice of failing-NEW-aborts for their
Modula-3 implementation -- many people hate it, a lot, because they've
got no way of detecting the potential for an abort, or of recovering
from it after the fact).
Second of all, from an implementation point-of-view, I have found that
dealing with exception handling is easier if you can arrange that
exception handlers and destructors run in a context that is as near to
"normal" as possible, and with any "stacking" actually taking place in
compiler-generated glue code that is similar to the handlers that get
written anyhow. That is, from an implementation point of view, there's
nothing that special about unwinding. (For reference, I've done 1.5
exception handling implementations -- all of one for Modula-3, based on
setjmp/longjmp, and .5 of one for C++, that used a PC-range style
dispatch).
Even the pathological case doesn't look as bad as I had thought.
Consider this:
try {
throw C();
} catch (...) {
if ( some_boolean_function() )
throw A();
else
throw;
}
Let's also suppose that C's destructor throws B(), B's destructor
throws A(). And, A's destructor throws C(). So,
suppose some_boolean_function is true -- then, we intend to throw A().
But, before we can throw this exception, we must destroy the current
one, C(). C's destructor throws B(), which supercedes A() (using
proposed semantics, roughly consistent with what you get in Modula-3
and Ada). ** If A had already been constructed ** , then we would need to
destroy it, which will throw C, which will supercede B, which will
in turn need to be destroyed, throwing A, which will supercede C, etc.
So, yes, if we do it like this, we end up with an infinite destruction
loop.
On the other hand, I think there are two ways out of this. One of them
is "IF A had already been constructed". If we could destroy the
"current" exception before throwing the next one, then life would be
relatively ducky, because we'd get the superceding semantics without
the additional destructor needing to be run. Unfortunately, this does
not mesh will with my favorite implementation (since it is my favorite,
it must be the best :-), where pending exceptions are stacked in the
activation records where their handlers/destructors are running (that
is, you enter the handler, get the current exception from the runtime,
and run the body of the handler/destructor. As required, you either
reraise or destroy the exception when you exit the handler. The
problem is, you don't know what goes on in code that you call, and it
might throw an exception (which certainly means that the exception
object has been constructed). Furthermore, that code (that you don't
necessarily know about) probably shouldn't be running the destructor
for an exception object that it's never heard about, because that could
cause it to throw an exception that IT's never heard about, either (this
is why I don't like to embed the "current exception" in the runtime
for any longer than I must).
Way-out number two is to refine the restriction on destructors throwing
exceptions. Basically, if the destructor for an object that you throw,
throws an exception, then something-bad-should-happen (unexpected() or
terminate()). The destructors for these objects are run in well-known
places, perhaps even within a library routine, so it is relatively easy
to guard against this. Written in try-catch notation, with the
compiler-generated glue code <written like this>, it goes something
like:
original:
{
declaration for ONE object with a destructor
body of code
}
translated (into compiler-ese):
try {
<body of code>
<E = NULL> // We made it to the end with no surprises.
<goto destroy_stuff>
} catch (...) {
<E = current exception>
destroy_stuff:
try { <run one destructor> }
catch (...) {
<F = current exception>
try { <destroy E> }
catch (...) { <die horribly> }
throw; /* throw F */
}
reraise_E:
if (E) throw; /* throw E */
}
Compare this with the current
try {
<body of code>
<E = NULL>
<goto destroy_stuff>
} catch (...) {
<E = current exception>
destroy_stuff:
try { <run one destructor> }
catch ( ... ) {
<F = current exception>
if (E) <die horribly>
throw; /* throw F */
}
reraise_E:
if (E) throw; /* throw E */
}
These examples reflect my choices as to how to implement this; the
exceptions should probably not be hanging around in some runtime data
structures, because (among other things) you'd need to make those data
structures thread safe. If you only have one exception at a time
(per-thread) "in the runtime", and the rest pushed into various
activation records, I think it is easier to avoid storage leaks and
other surprises. Note that, in the presentation above, the "current
exception" is the runtime's idea of the exception, and thus carries
information about the type, destructors, etc.
Note, too, that this proposed compilation is very simplified. It is
entirely likely that a list of objects-to-be-destroyed would be handed
off to some subroutine, together with the current exception, and it
would do something like:
destroy_all(L,E,N) {
for (i = N-1; i >= 0; i--) {
try {
~L[i]; // Assume the runtime/compiler conspire to get the
// right destructor called here.
} catch (...) {
F = <current exception>
if (E) try { <destroy E> }
catch (...) { <die horribly> }
E = F;
}
}
if (E) throw E;
}
This has obvious advantages if you are interested in compact
code for destructors, since it avoids the need to have a different
handler for each one. All it does is sequentially destroy objects,
keeping track of the exception most recently thrown from one of
the destructors, and calling the exception-object-destructor for
the exception that was current before one of the auto-object-
destructors threw a new one. Destructors are always "allowed"
to throw exceptions, unless the object being destroyed is an
exception-object (users are encouraged to not get too excited
about throwing complicated objects with interesting constructors
and destructors).
And, of course, note that this code is oblivious to whatever
exception-throwing foolishness goes on within the scope of the
destructors, or code that they call, which is how it should be.
speaking for myself,
David Chase
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: mueller@titania.hai.siemens.co.at (Harald M. Mueller)
Date: 1995/12/13 Raw View
In article <4aj3sn$erg@julie.teleport.com>, deef@teleport.com (Derek Foster) writes:
|>
|>In <9512071429.AA03532@titania.hai.siemens.co.at> mueller@titania.hai.siemens.co.at (Harald M. Mueller) writes:
|>
|>>The other day I had a nice idea how one (i.e. the C++ standardization
|>>committee - if it would still be willing to change the semantics of
|>>the language) could solve all these problems with exceptions and
|>>destructors.
|>
|>I also think they could solve it, with a bit of change to the language.
[...]
Small addition: Both proposals are somewhat related the rescue clause
of Eiffel, which can also be added to a class to serve as a default for
functions without handlers.
If Eiffel can have it, why not C++? :-( ;-)
|>To solve the situation, I had an idea quite similar to yours, but with
|>slightly different syntax and semantics. I would be curious if others see
|>problems with this proposal:
[...]
Well, the problem of my proposal (namely with the "unexpected handling" in
a block in e.g.
{ A a;
a.f1(); // throws exception
a.f2(); // jumped over
}
f3(); // here we continue!!??!!
) has been solved by postulating that
|> // There is an implicit 'throw;' executed for any '~catch' function
|> // that does not exit via a thrown exception. In other words, a
However, what about inheritance - in which order are the various handlers
tried, is only one executed, or one per class, how's that with multiple
inheritance etc.etc.
Nevertheless, I think such a concept should be given a try - if I only
had more time ... :-)
Harald M. Mueller
== -------------------------------------------------------------------
== Dr. Harald M. Mueller PSE EZE TNA1
== email: mueller@garwein.hai.siemens.co.at Siemens AG Austria
== tel: +43-1-71711-5336 Erdberger Laende 26
== fax: +43-1-71711-5425 A-1030 Vienna/Austria
== -------------------------------------------------------------------
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: fenster@cs.columbia.edu (Sam Fenster)
Date: 1995/12/05 Raw View
The text from the DWP, as quoted by David Chase below, is actually completely
unclear as to whether an exception thrown during processing of a prior
exception causes program termination.
> John Max Skaller <maxtal@suphys.physics.su.oz.au> () writes:
>> For example you should be able to throw an exception INSIDE the body of a
>> destructor and catch it, pre-empting the execution of the rest of the body,
>> but then continuing unwinding for the first exception which triggered
>> destruction in the first place.
chase@centerline.com (David Chase) writes:
> I would hope that this is the intent of the committee.[...] Looking at the
> April draft, I believe that this is the intent of the committee, and that
> the April draft supports it. See [except.terminate]
>
> "In the following situations, exception handling must be abandoned...
> ...
> -- when an attempt by the implementation to destroy an object during
> stack unwinding [1] exits [2] using an exception"
>
> [1] Stack unwinding is defined to be the destruction of objects constructed
> on the path from a try block to the throw-expression.
>
> [2] "exits" is the crucial word -- a destructor which throws an exception
> but does not propagate it to the destructor's caller, is not using the
> exception to exit.
The part of this text that makes it incomprehensible is the undefined
terminology, "when an *attempt* exits..." What is an "attempt"? Do they
mean:
- "when any *function* exits using an exception"?
- "when *any* *block* of code is exited by means of a `throw' statement"?
- "when the *destructor* of an object that was on the stack when the prior
exception was thrown exits with an exception"?
No, I don't want someone to tell me their personal interpretation. I want the
committee to revise text of the draft to use unambiguous, *well-defined*
terminology.
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: ark@research.att.com (Andrew Koenig)
Date: 1995/12/06 Raw View
In article <49tuq4$238@wcap.centerline.com> chase@centerline.com writes:
> The first problem I have is that my reading of this is that a
> destructor invoked because a block is exited non-exceptionally, can
> throw an exception WITHOUT causing terminate to be called. But, if
> that destructor is called be the block is exited exceptionally,
> terminate is not called. This seems, to me, to be a weird
> inconsistency. (How could someone writing a destructor know the cause
> of their call?) Is this just an oversight?
It is not an oversight. One reason for the distinction is that otherwise
it would have been necessary to draw a clearly visible dividing line between
when end-of-block destruction of objects starts and when it has not started
yet. But other things, such as compiler-generated temporaries, are destroyed
during a block before any kind of stack unwinding starts, and their destructors
could throw exceptions too.
So instead we take the view that there's this system-defined thing called
stack unwinding that happens only as part of exception handling. Exiting
from user code by an exception is OK, even if that user code is in the process
of destroying local objects. Exiting from stack unwinding by an exception
is not OK.
> The minor gripe is that I think that the choice should be the second
> one -- I see no reason why destructors should not be permitted to throw
> exceptions in the way that I describe above. There is some additional
> hair required to ensure that the "lost" exception is properly destructed,
> but that hair had to be there anyway to deal with throws/re-throws from
> handlers.
You may be right. The reason the prohibition is there is that while unwinding
is in progress there is an object that must eventually be cleaned up, namely
the object that was thrown. What if that object's destructor throws an exception?
More generally, we opted for the draconian treatment because liberalizing it
is easier than making something stricter that was inadvertently too liberal.
I was hoping that someone would come forward with a reason to change the
present treatment, but no one ever did.
--
--Andrew Koenig
ark@research.att.com
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: mueller@titania.hai.siemens.co.at (Harald M. Mueller)
Date: 1995/12/07 Raw View
The other day I had a nice idea how one (i.e. the C++ standardization
committee - if it would still be willing to change the semantics of
the language) could solve all these problems with exceptions and
destructors. Before I tell you my idea, I'll tell you the two problems
with destructors and exceptions:
(a) A destructor must not throw an exception during stack unwinding; however,
there is no language-defined means of testing whether we are in stack-unwinding
or not, and hence all destructors must be written under the assumption that they
*might* be called during unwinding, hence they must not throw exceptions -
which some people find too restrictive (This has been discussed in this thread
quite thouroughly).
--- end of problem (a) ---
(b) A problem which I haven't seen discussed so far: How are you going to
handle an exception?!?!? Let me present my view:
- Throwing an exception means that some resource in a program is no longer
in a correct state (because memory was running out, because a parameter had
a wrong value, because of anything else).
- What can we do with this resource? In all cases where the correct value
cannot recomputed from some other information - i.e. in almost all cases!
because only very few pieces of information are stored redundantly -, we
must shut down (usually destroy) the resource. Consider e.g.:
struct Stack {
struct XStack { // exception class thrown if anything goes
// wrong in a stack object
XStack(const Stack& the_object_to_be_destroyed);
// ...
private:
const Stack& s;
};
Stack() throw(Stack::XStack);
void push(Something) throw(Stack::XStack);
// ...
};
How would this class be used? E.g.:
f1() {
try {
Stack s1;
...
f2(s1);
...
} catch (Stack::XStack& xs) {
...(1)...
}
}
f2(Stack& s1) throw(Stack::XStack) {
try {
Stack s2;
...
f3(s1,s2);
} catch (Stack::XStack& xs) {
...(2)...
}
}
f3(Stack& s1, Stack& s2) throw(Stack::XStack) {
s1.push(s2.pop());
}
The question is: Which statements do we put at places (1) and (2)? What we
(might) want to do is:
If the exception came from s2, we only want to execute (2), but f1()
should continue;
however, if s1 is also bad (which it tells us by throwing XStck),
we also want to execute (1).
We therefore write:
...(2)...:
...deal with the problems from s2's shutdown...
if (& xs.s != & s2) throw;
and
...(1)...:
...deal with the problems from s2's shutdown...
if (& xs.s != & s1) throw;
Now, this is a very simple case. Consider e.g. the case where there is an
array of stacks in f2(): In this case we will have to search the array
to find out whether xs.s actually is a stack from the array (and hence we could
assume the exception handled if the array has vanished) or not (i.e. we
have to re-throw).
So what I would like to have is a possibility to stop stack-unwinding in
a destructor of an object that gets called during that stack-unwinding!
(BTW, does anyone have another idea or maybe concept what to write at (1) and
(2) in the above cases?)
--- end of problem (b) ---
Here's my proposal:
If a destructor has the (already allowed) form
X::~X() try {
...
}
catch (ExcType1) {
...
}
catch (ExcType2) {
...
}
etc.
then, IF it is called during stack unwinding (i.e. there is an "active
exception"), we immediately enter the corresponding handler - i.e. the
body of the constructor is NOT executed.
If it is not called during stack-unwinding, the current semantics
(execute body; if exception occurs, execute corresponding handler)
is not changed.
--- end of proposal ---
The solution to the problem of an exception occuring during stack
unwinding (problem (a)) now is simple: Write
X::~X() try {
...how to destroy object if no exception is active...
...here we can write:
if (problem) throw An_X_Cannot_Be_Destructed();
}
catch (Exctype& exc) {
...or...
catch (...) {
...how to destroy object if there is another exception present...
...here we write:
if (problem) throw An_X_Cannot_Be_Destructed(); // override exc
...or...
if (problem) throw; // re-throw exc
...or...
if (problem) throw An_X_Cannot_Be_Destructed(exc); // make a
// linked list from a new
// exception and exc
...or...
if (problem) throw X(A(exc),y,asfg etc.)
// throw some complex data
// structure as exception which
// tells everything about what
// happened.
}
The solution to problem (b) above is also simple, namely:
X::~X() try {
destruct();
}
catch (Stack::XStack& xs) {
destruct();
if ( & xs.s != this) throw;
}
where Stack::destruct() is the factored-out common code to destroy a
stack object, whether an exception occurred or not.
... a lot is still missing: How does this work with inheritance (single
and multiple)? When does stack unwinding actually end (of course, the
objects containing the "ending handler" must still be destroyed fully).
In the above form, weird effects can happen:
f() {
{ A a;
g1(a);
g2(a);
}
g3();
}
- if g1(a) throws an exception, the block containing a would be exited,
but if A::~A() now caught the exception, we would continue with g3() as
if nothing happened - an effect the programmer certainly would not suspect!
Maybe some syntax of the form
f() {
try { A a;
g1(a);
g2(a);
}
g3();
}
might help (note: no handlers except the "implicit ones" in try-block); and a
definition that implicit handlers end the first (dynamically) surrounding
try-block - be it with or without handlers.
Other problems include destructors of dynamic variables (what are they supposed
to do - if occuring in a destructor which runs/runs not during stack unwinding);
code bloat (will many destructors have to contain two function calls to some
destruct() routine - one in the body, one in catch(...) ); etc.
Maybe the whole thing does not work. But I think that something in this
vein is necessary - if only to make exceptions more "object oriented" - i.e.
bound to objects=resources - and emancipate them from a pure control structure.
(Is there any reason I should work on this? or is C++ already defined? :-))
Harald M. Mueller
== -------------------------------------------------------------------
== Dr. Harald M. Mueller PSE EZE TNA1
== email: mueller@garwein.hai.siemens.co.at Siemens AG Austria
== tel: +43-1-71711-5336 Erdberger Laende 26
== fax: +43-1-71711-5425 A-1030 Vienna/Austria
== -------------------------------------------------------------------
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: chase@centerline.com (David Chase)
Date: 1995/12/04 Raw View
John Max Skaller <maxtal@suphys.physics.su.oz.au> () writes:
> NESTED exceptions would GREATLY aid in simplifying this
> task, but you'd have to have a suitable handler
> close enough to catch such a nested exception.
>
> I believe this is the INTENT of the committee, even though
> the current words don't quite support nested exceptions.
>
> For example you should be able to throw an exception INSIDE
> the body of a destructor and catch it, pre-empting the
> execution of the rest of the body, but then continuing
> unwinding for the first exception which triggered destruction
> in the first place.
I would hope that this is the intent of the committee, and I had
believed that this was what was specified, if only because it is the
only sane alternative -- exception-handling must certainly be usable in
code run within exception handlers and destructors. If I write a
handler which calls a subroutine S, how am I to know whether or not S
uses exceptions within itself, if it handles them properly and does not
propagate them to callers. Looking at the April draft, I believe
that this is the intent of the committee, and that the April draft
supports it. See [except.terminate]
"In the following situations, exception handling must be abandoned...
...
-- when an attempt by the implementation to destroy an object during
stack unwinding [1] exits [2] using an exception"
[1] Stack unwinding is defined to be the destruction of objects
constructed on the path from a try block to the throw-expression.
[2] "exits" is the crucial word -- a destructor which throws an exception
but does not propagate it to the destructor's caller, is not using the
exception to exit.
I think this is generally good, because lacking a clear specification
of what may or may not be done in a destructor, one must assume that the
entire language can and will be used.
However, I have two problems with this, one perhaps serious, the other
not so much.
The first problem I have is that my reading of this is that a
destructor invoked because a block is exited non-exceptionally, can
throw an exception WITHOUT causing terminate to be called. But, if
that destructor is called be the block is exited exceptionally,
terminate is not called. This seems, to me, to be a weird
inconsistency. (How could someone writing a destructor know the cause
of their call?) Is this just an oversight? Why not be consistent, and
either declare that destructors which attempt to exit exceptionally
result in a call to terminate, always, or else declare that destructors
may throw exceptions in either case, and that the "new" exception
replaces the old one (just as catch block may exit normally, re-throw
the current exception to exit, or throw a new exception to exit.
The minor gripe is that I think that the choice should be the second
one -- I see no reason why destructors should not be permitted to throw
exceptions in the way that I describe above. There is some additional
hair required to ensure that the "lost" exception is properly destructed,
but that hair had to be there anyway to deal with throws/re-throws from
handlers.
speaking for myself,
David Chase
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]