[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [lmi] "Alert" messages [Was: Code review: product editor]

From: Evgeniy Tarassov
Subject: Re: [lmi] "Alert" messages [Was: Code review: product editor]
Date: Mon, 5 Mar 2007 11:33:44 +0100

On 3/3/07, Greg Chicares <address@hidden> wrote:
On 2007-3-2 10:59 UTC, Evgeniy Tarassov wrote:
> IIRC it is not advised to add return after a call to fatal_error().
> Does it apply to warning() too?

The simple answer to the question posed is:
 - don't routinely add anything after either of those
 - but add a return if it would be obviously wrong not to
 - and add an explicit throw-expression only if gcc wouldn't
     compile without it

Thank you for detailing it all!

The simple answer to an underlying question not posed is:
 - rarely write warning(): fatal_error() is usually better
In more detail...


avoid that problem by using a throw-expression instead. That's
better, because we can always throw.

Now, what (uniform) throw-expression would be best? Consider:

  throw std::logic_error("Unreachable"); // Silence compiler warning.
  throw lmi_unreachable_exception_to_silence_compiler_diagnostic();
  throw "Unreachable--silences a compiler diagnostic.");
Self documenting, and no <stdexcept> dependency. I think I
like this best; have you any other suggestions?

Another fancy way of explicitly telling the compiler that
fatal_error() (after an LMI_FLUSH) throws, could be to add 'throw'
just in front of fatal_error(), like so:

throw fatal_error()
   << "Some diagnostic message"
The syntax is unusual but explicitly points the reader and a compiler
to the fact that the expression forces the workflow to exit the
IIRC the expression being thrown must have a copy constructor. This
could be worked around by slightly rewriting the code in alert.?pp to
return (from fatal_error(), warning() and other functions) a reference
to a class extending (or wrapping) std::ostream (instead of a
reference to std::ostream). This class should have a copy constructor
which in turns throws to prevent it from mistakenly being called
(additionally it could add the content of the underlying buffer to
point out the place where copy constructor was incorrectly used).

If we do it uniformly for every alert.?pp facility, then someone (like
me :)) could mistakenly write:
 throw warning() << "A warning" << LMI_FLUSH;
which is incorrect and will _not_ be detected at compile time. But the
bright side is that such an error will only turn warning() into a

> "Generally" (for fatal_error()) and "would probably" (for warning())
> and exception will be thrown.

I will clarify that as shown in a footnote [1]. My intention
was to specify a very general, abstract API, with hints about
what C99 3.16 would call "recommended practice". Maybe I spend
too much time reading ISO standards.

Just to be very clear: for warning(), it is not "recommended",
and never was, that an exception be thrown; now [1] it's
explicitly forbidden.

I don't know why i was mistakenly thinking that warning throws... Now
i understand it does not.

Well, warning() doesn't throw, and a future implementation
that throws would be wrong, so I'll make the documentation
say that [1], and also specify that an exception must be
thrown when the ostream returned by fatal_error() is flushed.

I'm sorry -- i misunderstood the meaning of warning. I will run
through the code I've written to check that it is used correctly!

reply via email to

[Prev in Thread] Current Thread [Next in Thread]