casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Fallible.h
Go to the documentation of this file.
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