00001 // -*- C++ -*- 00002 /*************************************************************************** 00003 * 00004 * The IPPL Framework 00005 * 00006 * 00007 * Visit http://people.web.psi.ch/adelmann/ for more details 00008 * 00009 ***************************************************************************/ 00010 00011 #ifndef PASSERT_H 00012 #define PASSERT_H 00013 00015 // 00016 // This is a compile time assert. 00017 // That is, if you say: 00018 // CTAssert<true>::test(); 00019 // it compiles just fine and inserts no code. 00020 // If you say: 00021 // CTAssert<false>::test(); 00022 // you get a compile error that it can't find CTAssert<false>::test(). 00023 // 00024 // The template argument can of course be a calculation of const bools 00025 // that are known at compile time. 00026 // 00028 00029 template<bool B> struct IpplCTAssert {}; 00030 00031 template<> struct IpplCTAssert<true> { static void test() {} }; 00032 00033 #if defined(NOCTAssert) 00034 #define CTAssert(c) 00035 #else 00036 #define CTAssert(c) IpplCTAssert<(c)>::test() 00037 #endif 00038 00039 //===========================================================================// 00040 // class assertion - exception notification class for assertions 00041 00042 // This class should really be derived from std::runtime_error, but 00043 // unfortunately we don't have good implementation of the library standard 00044 // yet, on compilers other than KCC. So, this class will keep with the 00045 // "what" method evidenced in the standard, but dispense with inheriting from 00046 // classes for which we don't have implementations... 00047 //===========================================================================// 00048 00049 class assertion /* : std::runtime_error */ 00050 { 00051 char *msg; 00052 public: 00053 assertion( const char *cond, const char *file, int line ); 00054 assertion( const char *m ); 00055 assertion( const assertion& a ); 00056 ~assertion() { delete[] msg; } 00057 assertion& operator=( const assertion& a ); 00058 const char* what() const { return msg; } 00059 }; 00060 00061 //---------------------------------------------------------------------------// 00062 // Now we define a run time assertion mechanism. We will call it "PAssert", 00063 // to reflect the idea that this is for use in IPPL per se, recognizing that 00064 // there are numerous other assertion facilities in use in client codes. 00065 //---------------------------------------------------------------------------// 00066 00067 // These are the functions that will be called in the assert macros. 00068 00069 void toss_cookies( const char *cond, const char *file, int line ); 00070 void insist( const char *cond, const char *msg, const char *file, int line ); 00071 00072 //---------------------------------------------------------------------------// 00073 // The PAssert macro is intended to be used for validating preconditions 00074 // which must be true in order for following code to be correct, etc. For 00075 // example, PAssert( x > 0. ); y = sqrt(x); If the assertion fails, the code 00076 // should just bomb. Philosophically, it should be used to feret out bugs in 00077 // preceding code, making sure that prior results are within reasonable 00078 // bounds before proceeding to use those results in further computation, etc. 00079 //---------------------------------------------------------------------------// 00080 00081 #ifdef NOPAssert 00082 #define PAssert(c) 00083 #else 00084 #define PAssert(c) if (!(c)) toss_cookies( #c, __FILE__, __LINE__ ); 00085 #endif 00086 00087 //---------------------------------------------------------------------------// 00088 // The PInsist macro is akin to the PAssert macro, but it provides the 00089 // opportunity to specify an instructive message. The idea here is that you 00090 // should use Insist for checking things which are more or less under user 00091 // control. If the user makes a poor choice, we "insist" that it be 00092 // corrected, providing a corrective hint. 00093 //---------------------------------------------------------------------------// 00094 00095 #define PInsist(c,m) if (!(c)) insist( #c, m, __FILE__, __LINE__ ); 00096 00097 //---------------------------------------------------------------------------// 00098 // NOTE: We provide a way to eliminate assertions, but not insistings. The 00099 // idea is that PAssert is used to perform sanity checks during program 00100 // development, which you might want to eliminate during production runs for 00101 // performance sake. PInsist is used for things which really really must be 00102 // true, such as "the file must've been opened", etc. So, use PAssert for 00103 // things which you want taken out of production codes (like, the check might 00104 // inhibit inlining or something like that), but use PInsist for those things 00105 // you want checked even in a production code. 00106 //---------------------------------------------------------------------------// 00107 00108 #endif // PASSERT_H 00109 00110 /*************************************************************************** 00111 * $RCSfile: PAssert.h,v $ $Author: adelmann $ 00112 * $Revision: 1.1.1.1 $ $Date: 2003/01/23 07:40:33 $ 00113 * IPPL_VERSION_ID: $Id: PAssert.h,v 1.1.1.1 2003/01/23 07:40:33 adelmann Exp $ 00114 ***************************************************************************/