casa
$Rev:20696$
|
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