* <ul>
*
* <li> Static assertions: These are checks that are only enabled in debug
- * mode, not in optimized (or production) mode. They are meant to check that
- * parameters to functions satisfy certain properties and similar
+ * mode, not in release (or optimized, production) mode. In deal.II, static
+ * assertions are typically used to check that parameters to functions satisfy
+ * certain properties, that internal data structures are consistent, and similar
* assertions. For example, static assertions are used to make sure that two
* vectors that are added together have the same number of components --
* everything else would not make any sense anyway.
*
- * Such checks are performed by the Assert macro in several thousand places
+ * Such checks are performed by the @p Assert macro in several thousand places
* within the library. Also, several tutorial programs starting with step-5
* show how to do this.
*
* If a static assertion is violated, the exception mechanism generates an
* exception of a type that indicates what exactly goes wrong, displays
- * appropriate information, and then aborts the program -- if you try to add
+ * appropriate information including the exact location where the problem
+ * was detected, and then aborts the program -- if you try to add
* two vectors of different length, there is nothing that can be done within
* the program to cope with the situation, you have to go fix the program
- * code instead. The exceptions of this module are used to indicate the
- * reason for the failure.
- *
- *
- * <li> Dynamic assertions: These are used to check dynamic features, such
- * as whether an output file can be written to. These are things that can't
- * be checked statically, i.e. they may change from program run to program
- * run. It is therefore insufficient to only check these situations in debug
- * mode.
+ * code instead. There is generally not even a reason to @p throw an exception
+ * object using the usual C++ exception mechanism because there is nothing
+ * a function higher up could do in such cases to rectify the situation
+ * and deal with it in a useful way -- it's not that the program received
+ * bad data; the program is just buggy, and one can not intelligently
+ * work around that.
+ *
+ * (It is sometimes useful to change the behavior of the @p Assert macro
+ * from aborting a program to throwing exceptions. On the other hand,
+ * exceptions are not allowed to propagate out of destructors of classes.
+ * For this purpose, there is a variant of the macro, called @p AssertNothrow,
+ * that can be used in destructors. These use cases are discussed further
+ * down below on this page.)
+ *
+ *
+ * <li> Dynamic assertions: These are used to check conditions that depend on
+ * external things that may be different from one program run to the next, such
+ * as whether an output file can be written to.
+ *
+ * These are things that shouldn't
+ * be checked statically, because it is not guaranteed that a program for which
+ * the condition is satisfied in a debug mode run, will also have the condition
+ * satisfied in a subsequent release mode run -- in other words, it is not
+ * sufficient to only check these situations in debug mode.
*
* Rather, one has to check them every time during execution of a
- * program. Within deal.II, this is done using the AssertThrow macro
+ * program. Within deal.II, this is done using the @p AssertThrow macro
* introduced in step-9, step-13, and
* following tutorial programs. The macro checks a condition, and if
* violated throws an exception of one of the types declared in this
* @code
* Assert (n<dim, ExcDomain(n,dim));
* @endcode
- * which by macro expansion does essentially the following:
+ * which by macro expansion does essentially the following (though the actual
+ * code is slightly more complicated):
* @code
* #ifdef DEBUG
* if (!(cond))
* issue error of class ExcDomain(n,dim)
* #else
- * do nothing
+ * // do nothing
* #endif
* @endcode
- * i.e. it issues an error only if the preprocessor variable
+ * That is, it issues an error only if the preprocessor variable
* <tt>DEBUG</tt> is set and if the given condition (in this case
* <tt>n < dim</tt> is violated).
*
* If the exception was declared using the <tt>DeclException0 (...)</tt>
- * macro, i.e. without any additional parameters, its name has
+ * macro, i.e., without any additional parameters, its name has
* nonetheless to be given with parentheses:
* <tt>Assert (i>m, ExcSomewhat());</tt>
*
* message about suppressed follow-up messages is shown.
*
*
- * <h3>Use of run-time exceptions</h3>
+ * <h3>Use of run-time exceptions (dynamic checks)</h3>
+ *
+ * C++ has a mechanism to indicate that something exceptional has
+ * happened: exceptions that can be triggered by <tt>throw</tt> statements
+ * and captured by <tt>catch</tt> clauses, see for example
+ * https://en.wikipedia.org/wiki/C%2B%2B#Exception_handling and
+ * http://www.cplusplus.com/doc/tutorial/exceptions/ .
*
- * For this mode, the standard <tt>C++</tt> <tt>throw</tt> and <tt>catch</tt>
- * concept exists. We
- * want to keep to this, but want to extend it a bit. In general, the
- * structure is the same, i.e. you normally raise and exception by
+ * At some fundamental level, a typical C++ exception is an object that
+ * is placed in some special place, and then the function exits the current
+ * scope (e.g., the current function) through an exceptional return path.
+ * This is often enough to tell what problem triggered the exception,
+ * but more frequently it would be nice if one had more information: for
+ * example, in which line of the code the problem happened, or what
+ * non-existent entry of a sparse matrix the code wanted to write into.
+ *
+ * Dynamic assertions in deal.II therefore extend this mechanism a bit.
+ * Typically, one would raise an exception by code such as
* @code
* if (!(cond))
* throw ExcSomething();
* try {
* do_something ();
* }
- * catch (exception &e) {
+ * catch (std::exception &e) {
* std::cerr << "Exception occurred:" << std::endl
* << e.what ()
* << std::endl;
* do_something_to_reciver ();
* };
* @endcode
- * <tt>exception</tt> is a standard <tt>C++</tt> class providing basic functionality for
- * exceptions, such as the virtual function <tt>what()</tt> which returns some
+ * <tt>std::exception</tt> is a standard <tt>C++</tt> class providing basic functionality for
+ * exceptions, such as the virtual function <tt>what()</tt> that returns some
* information on the exception itself. This information is useful if an
* exception can't be handled properly, in which case as precise a description
* as possible should be printed.
*
* The problem here is that to get significant and useful information out
- * of <tt>what()</tt>, it is necessary to overload this function in out exception
+ * of <tt>what()</tt>, it is necessary to overload this function in our exception
* class and call the <tt>throw</tt> operator with additional arguments to the
* exception class. The first thing, overloading the <tt>what</tt> function is
* done using the <tt>DeclExceptionN</tt> macros, but putting the right information,
*
* For this purpose, the macro <tt>AssertThrow</tt> was invented. It does
* mainly the same job as does the <tt>Assert</tt> macro, but it does not
- * kill the program, it rather throws an exception as shown above. The mode
+ * abort the program; rather, it throws an exception as shown above. The mode
* of usage is
* @code
* AssertThrow (cond, ExcSomething(additional information));
* Obviously for the <tt>DeclException0(name)</tt> macro, no types and
* also no output sequence is allowed.
*
- * @author Wolfgang Bangerth, 1998-2006
+ *
+ * <h3>A corner case of @p Assert: The @p AssertNothrow macro</h3>
+ *
+ * The default implementation of the @p Assert macro, as discussed above,
+ * prints detailed information about what exactly went wrong to the
+ * screen and then aborts the program. Aborting the program is useful
+ * because it allows easily finding the place where something went
+ * wrong -- including all of the information how we got to that
+ * place -- by running the program in a debugger.
+ *
+ * On the other hand, there are cases where aborting a program may be
+ * undesirable and one needs to exit in a somewhat more graceful
+ * way -- even if there is really not very much one can do in these
+ * cases to still produce a meaningful result. An example is if a
+ * deal.II program is run a one module in a bigger framework of
+ * software. Think, for example, of a case where a deal.II program
+ * computed the flow field that corresponds to a set of input
+ * variables provided by some optimization routine: if the optimizer
+ * on the outside provided a negative density as input (a condition
+ * one might want to check via @p Assert), then this
+ * clearly makes no sense, and the flow solver cannot produce a
+ * meaningful answer; but it should tell that to the optimizer nicely,
+ * rather than just aborting the entire process (optimizer and flow
+ * solver).
+ *
+ * For this purpose, one can call
+ * deal_II_exceptions::disable_abort_on_exception() that switches
+ * what @p Assert does from aborting the program to essentially the
+ * same as @p AssertThrow does, namely using the C++ @p throw mechanism
+ * to raise an exception. This exception can then be caught at a higher
+ * level -- e.g., in the optimization routine that sits atop the flow
+ * solver, and that can then decide what it wants to do with the
+ * situation.
+ *
+ * This is all nice and good, but C++ does not allow throwing exceptions
+ * inside the destructors of classes, or in a function that is currently
+ * being called from a destructor higher up in the call stack. To this
+ * end, there is a separate macro, @p AssertNothrow, that can be used in
+ * destructors: It acts just like @p Assert usually does -- in particular,
+ * it only checks the condition in debug mode -- but it is immune to the
+ * effect of deal_II_exceptions::disable_abort_on_exception(): It will
+ * only ever abort the program, and never throw an exception.
+ *
+ *
+ * @author Wolfgang Bangerth, 1998-2017
*/