casa
$Rev:20696$
|
00001 //# Fallible.h: Identifies a value as valid or invalid 00002 //# Copyright (C) 1994,1995,1999 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: Fallible.h 20652 2009-07-06 05:04:32Z Malte.Marquarding $ 00027 00028 #ifndef CASA_FALLIBLE_H 00029 #define CASA_FALLIBLE_H 00030 00031 #include <casa/aips.h> 00032 00033 namespace casa { //# NAMESPACE CASA - BEGIN 00034 00035 //# The following function is to be found in Fallible2.cc not Fallible.cc 00036 //# because it's a non-templated function and template instantiators normally 00037 //# do not like them in the same .cc file with templated functions. 00038 // 00039 // <summary> throw exception on access of an invalid object </summary> 00040 // 00041 // This function gets called when an invalid object is accessed. It 00042 // just throws an exception. Since we have inline functions, let's keep 00043 // the throw out of them to keep them from moving out of line. 00044 // <thrown> 00045 // <li> AipsError 00046 // </thrown> 00047 // 00048 // <group name=invalid_access> 00049 void AccessInvalidFallibleObject(); 00050 // </group> 00051 00052 // <summary> Mark a value as valid or invalid. </summary> 00053 // <use visibility=export> 00054 // <reviewed reviewer="Gareth Hunt" date="1994/09/14" tests="tFallible,TestCenter" demos=""> 00055 // </reviewed> 00056 00057 // <etymology> 00058 // This is to be used for values which might be fallible, i.e. might not 00059 // be valid. 00060 // </etymology> 00061 00062 // <synopsis> 00063 // This class resembles the one in <em>Scientific and Engineering C++</em> 00064 // by Barton and Nackman. While it was written with that book closed, the 00065 // class is simple enough that resemblances likely remain. 00066 // 00067 // This class essentially just holds a value (with automatic conversion) 00068 // and allows inquiry as to whether the value is valid. If the value is 00069 // used and is indeed invalid an exception will be thrown. 00070 // 00071 // A copy of the value is stored in the <src>Fallible<T></src> object, so 00072 // making copies shouldn't be too expensive. It is anticipated that this 00073 // class will most often be used with built in, or other small, types. 00074 // </synopsis> 00075 00076 // <example> 00077 // Suppose we write some code that turns a day/month/year into a day 00078 // of the week: 00079 // <srcblock> 00080 // enum DayName {Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, 00081 // Saturday}; 00082 // Fallible<DayName> dayFromDate(uInt day, uInt month, uInt year); // a func. 00083 // </srcblock> 00084 // And we also have some other function that needs a day name, for example 00085 // just prints it: 00086 // <srcblock> 00087 // ostream &operator<<(ostream &os, DayName day); // Print name as string 00088 // </srcblock> 00089 // 00090 // Since the automatic conversions are defined, if we are certain that the 00091 // dates are valid, we can just go ahead and use the value: 00092 // <srcblock> 00093 // cout << dayFromData(2, 1, 1962) << endl; // A valid date 00094 // </srcblock> 00095 // If, by some chance, you are wrong and a date fails, then an exception will 00096 // be thrown and a run-time error will occur. 00097 // 00098 // If, as is more likely the case, you don't know a priori whether a test will 00099 // succeed, you can check it: 00100 // <srcblock> 00101 // Fallible<DayName> result = dayFromDate(d,m,y); // who knows if valid? 00102 // if (result.isValid()) { 00103 // cout << result << endl; 00104 // } else { 00105 // // some corrective action 00106 // } 00107 // </srcblock> 00108 // </example> 00109 00110 // <motivation> 00111 // The alternatives are to have "special values" (e.g. have an "undefined 00112 // day" in the enumeration) or return a Boolean, or change a Boolean. While 00113 // those solutions are often adequate, <src>Fallible<T></src> can often be 00114 // more natural. 00115 // </motivation> 00116 00117 // <templating arg=T> 00118 // <LI> default constructor 00119 // <LI> copy constructor 00120 // </templating> 00121 00122 template<class T> class Fallible 00123 { 00124 public: 00125 // The default constructor creates an invalid object. 00126 Fallible() : value_p(T()), isValid_p(False) {} 00127 00128 // Create a valid object 00129 Fallible(const T &value) : value_p(value), isValid_p(True) {} 00130 00131 //# Actually, the default copy ctor and assignment operator would work 00132 Fallible(const Fallible<T> &other) : value_p(other.value_p), 00133 isValid_p(other.isValid_p) {} 00134 00135 Fallible<T> &operator=(const Fallible<T> &other) 00136 {value_p = other.value_p; isValid_p = other.isValid_p; 00137 return *this;} 00138 00139 ~Fallible() {} 00140 00141 // Automatically convert a <src>Fallible<T></src> to a <src>T</src>. 00142 operator T() const { if (! isValid_p) AccessInvalidFallibleObject(); 00143 return value_p; } 00144 00145 // Sometimes it's more convenient to not rely on a compiler supplied 00146 // conversion, especially when the compiler is confused. 00147 T value() const { if (! isValid_p) AccessInvalidFallibleObject(); 00148 return value_p; } 00149 00150 Bool isValid() const {return isValid_p;} 00151 private: 00152 T value_p; 00153 Bool isValid_p; 00154 }; 00155 00156 00157 } //# NAMESPACE CASA - END 00158 00159 #endif 00160