casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Assert.h
Go to the documentation of this file.
00001 //# Assert.h: Throw exceptions when Assertions fail.
00002 //# Copyright (C) 1993,1994,1995,1999,2000,2002
00003 //# Associated Universities, Inc. Washington DC, USA.
00004 //# 
00005 //# This library is free software; you can redistribute it and/or modify it
00006 //# under the terms of the GNU Library General Public License as published by
00007 //# the Free Software Foundation; either version 2 of the License, or (at your
00008 //# option) any later version.
00009 //# 
00010 //# This library is distributed in the hope that it will be useful, but WITHOUT
00011 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00012 //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00013 //# License for more details.
00014 //# 
00015 //# You should have received a copy of the GNU Library General Public License
00016 //# along with this library; if not, write to the Free Software Foundation,
00017 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
00018 //# 
00019 //# Correspondence concerning AIPS++ should be addressed as follows:
00020 //#        Internet email: aips2-request@nrao.edu.
00021 //#        Postal address: AIPS++ Project Office
00022 //#                        National Radio Astronomy Observatory
00023 //#                        520 Edgemont Road
00024 //#                        Charlottesville, VA 22903-2475 USA
00025 //#
00026 //# $Id: Assert.h 20551 2009-03-25 00:11:33Z Malte.Marquarding $
00027 
00028 #ifndef CASA_ASSERT_H
00029 #define CASA_ASSERT_H
00030 
00031 #include <casa/aips.h>
00032 #include <casa/Exceptions/Error.h>
00033 
00034 
00035 namespace casa { //# NAMESPACE CASA - BEGIN
00036 
00037 // <summary>Utility class for Assert macros.</summary>
00038 // <use visibility=export>
00039 // <reviewed reviewer="Friso Olnon" date="1995/03/13" tests="" demos="">
00040 // </reviewed>
00041 
00042 // <prerequisite>
00043 //   <li> module <linkto module=Exceptions>Exceptions</linkto>
00044 // </prerequisite>
00045 
00046 // <etymology>
00047 // Templated class <src>assert_</src> is the basis for the macros
00048 // <src>DebugAssertExit</src>, <src>DebugAssert</src>, 
00049 // <src>AlwaysAssertExit</src>, and <src>AlwaysAssert</src> which 
00050 // form the "public interface" to the Assertion mechanism.
00051 // </etymology>
00052 
00053 // <synopsis>
00054 // The present Assertion mechanism uses the exception 
00055 // handling mechanism to throw the errors when an Assertion 
00056 // fails. It can be used in two ways:
00057 // <dl>
00058 //  <dt> <src>DebugAssertExit(expr)</src>
00059 //  <dt> <src>AlwaysAssertExit(expr)</src>
00060 //  <dd> cause the program to abort if <src>expr</src> evaluates to a
00061 //       null value.  This form is intended for the <em>end users</em>
00062 //       because presumabily at their level there is no way to recover
00063 //       from errors.
00064 //  <dt> <src>DebugAssert(expr, exception)</src>
00065 //  <dt> <src>AlwaysAssert(expr, exception)</src>
00066 //  <dd> throw the specified exception if the <src>expr</src> is
00067 //       null. This form is designed to be used by <em>library 
00068 //       elements</em> because it actually raises an exception which
00069 //       can be later caught in the regular way.
00070 // </dl>
00071 //
00072 // <note role=tip> <src>DebugAssertExit</src> and 
00073 // <src>DebugAssert</src> are only invoked in
00074 // debug mode (i.e. when <src>AIPS_DEBUG</src> is defined); otherwise
00075 //  they preprocess to null statements. <src>AlwaysAssertExit</src> 
00076 // and <src>AlwaysAssert</src> are always invoked.
00077 // </note>
00078 //
00079 // <note role=tip> Class <src>assert_</src> is internal to the
00080 // Assertion mechanism and should be undocumented. However,
00081 // documenting the class is the only way to document this mechanism,
00082 // which for the rest consists of preprocessor macros.
00083 // </note>
00084 //
00085 // </synopsis>
00086 
00087 // <example>
00088 // The implementation of the <linkto module=Arrays>Array classes</linkto>
00089 // contains many examples of the Assertion mechanism. The following
00090 // application of the Assertion mechanism is taken from the archive of
00091 // the aips2-workers@nrao.edu mail group (Brian Glendenning, 1994/03/23):
00092 //
00093 // I thought I'd readvertise a technique I use that helps me find
00094 // problems in the classes I write. I have found this to be an
00095 // EXTREMELY useful way of discovering bugs automatically (so the users
00096 // of your class don't have to manually).
00097 //
00098 // In your class, write an <src>ok()</src> member function that
00099 // returns a <src>Bool</src>.  Allow for inheritance and make it a
00100 // virtual function (in fact, the derived class's <src>ok()</src> would
00101 // probably call the <src>ok()</src> from it's parent, as well as doing
00102 // specific stuff for the derived class).
00103 //
00104 // Then in every member function, place a call to <src>ok()</src> in
00105 // an Assertion.  Like this:
00106 // <srcblock>
00107 // DebugAssert(ok(), AipsError);  // include aips/Assert.h in your .cc file
00108 // </srcblock>
00109 //
00110 // The second argument is the exception you want to throw. 
00111 // <src>AipsError</src> will always do, although you can throw a
00112 // more particular one if you want to. This Assertion will not be in
00113 // production code -- i.e. if <src>AIPS_DEBUG</src> is not defined, the
00114 // above line will be a null statement. I place these lines at the entry
00115 // to all member functions (except I place them at the <em>end</em> of a
00116 // constructor!). (I normally don't put an Assertion in an inline
00117 // function).
00118 //
00119 // In the <src>ok()</src> function you should Assert a class's
00120 // invariants. This is more or less the same as Asserting that an
00121 // object's private and protected data are <em>consistent</em>. For
00122 // example, one of the simple tests I do in the array classes is Assert
00123 // that the number of elements (which I cache) is indeed equal to the
00124 // product of its shape (I do ~15 tests in the <src>ok()</src> for the
00125 // new <src>Array<T></src> class).
00126 // </example>
00127 
00128 template<class t> class assert_ {
00129 public:
00130     // <group>
00131     assert_(int expr, const char *msg) {
00132         if (! expr) throw(t(msg));
00133     }
00134     assert_(const void *ptr, const char *msg) {
00135         if (! ptr) throw(t(msg));
00136     }
00137     assert_(int expr, const char *msg, const char* file, Int line);
00138     assert_(const void *ptr, const char *msg, const char* file, Int line);
00139     // </group>
00140 
00141     // A no-op, but it keeps g++ from complaining about "variable not used"
00142     // errors
00143     void null() {}
00144 };
00145 
00146 //  These marcos are provided for use instead of simply using the
00147 //  constructors of <src>assert_</src> to allow addition of line
00148 //  numbers and file name in the future.
00149 //
00150 // <src>DebugAssert</src> and <src>AlwaysAssert</src> are designed to
00151 // be used by library elements because they actually raise an exception
00152 // which can later be later caught.
00153 // <src>DebugAssertExit</src> and <src>AlwaysAssertExit</src> are
00154 // intended to be used by the applications writer, because they cause an
00155 // <src>exit(0)</src>.
00156 
00157 #define AlwaysAssert(expr, exception) \
00158     {assert_<exception > dummy_(expr, "Failed AlwaysAssert " #expr,__FILE__,(Int)__LINE__); dummy_.null(); }
00159 #define AlwaysAssertExit(expr) \
00160     {assert_<AbortError> dummy_(expr, "Unrecoverable AlwaysAssertExit: " #expr,__FILE__,(Int)__LINE__); dummy_.null();}
00161 
00162 #if defined(AIPS_DEBUG)
00163 
00164 //# The backslashes below have spaces after them to make the egcs
00165 //  compiler happy # (otherwise it thinks they are multiline //
00166 //  comments). If ever uncommented # the spaces should be removed.
00167 
00168 // #define DebugAssert(expr, exception)  
00169 //     (assert_<exception > (expr, "Failed Assertion: " #expr))
00170 // #define Assert(expr)  
00171 //     (assert_<AbortError> (expr, "Unrecoverable Assertion: " #expr))
00172 
00173 // #define DebugAssert(expr, exception) 
00174 //     (assert_<exception > (expr, "Failed Assertion: " #expr,__FILE__,(Int)__LINE__))
00175 // #define Assert(expr) 
00176 //     (assert_<AbortError> (expr, "Unrecoverable Assertion: " #expr,__FILE__,(Int)__LINE__))
00177 
00178 #define DebugAssert(expr, exception) \
00179     {assert_<exception > dummy_(expr, "Failed Assertion: " #expr,__FILE__,(Int)__LINE__); dummy_.null();}
00180 #define DebugAssertExit(expr) \
00181     {assert_<AbortError> dummy_(expr, "Unrecoverable Assertion: " #expr,__FILE__,(Int)__LINE__); dummy_.null();}
00182 
00183 #else
00184 
00185 #define DebugAssert(expr, exception)
00186 #define DebugAssertExit(expr)
00187 
00188 #endif
00189 
00190 
00191 } //# NAMESPACE CASA - END
00192 
00193 #ifndef CASACORE_NO_AUTO_TEMPLATES
00194 #include <casa/Utilities/Assert.tcc>
00195 #endif //# CASACORE_NO_AUTO_TEMPLATES
00196 #endif