$extrastylesheet
compare_types.h
Go to the documentation of this file.
00001 // The libMesh Finite Element Library.
00002 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
00003 
00004 // This library is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU Lesser General Public
00006 // License as published by the Free Software Foundation; either
00007 // version 2.1 of the License, or (at your option) any later version.
00008 
00009 // This library is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 // Lesser General Public License for more details.
00013 
00014 // You should have received a copy of the GNU Lesser General Public
00015 // License along with this library; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 
00018 
00019 #ifndef LIBMESH_COMPARE_TYPES_H
00020 #define LIBMESH_COMPARE_TYPES_H
00021 
00022 // System includes
00023 #include <complex>
00024 
00025 namespace libMesh
00026 {
00027 
00028 // Copy of boost's enable_if_c
00029 
00030 namespace boostcopy {
00031 template <bool B, class T = void>
00032 struct enable_if_c {
00033   typedef T type;
00034 };
00035 
00036 template <class T>
00037 struct enable_if_c<false, T> {};
00038 }
00039 
00040 
00041 // TypesEqual takes two types as parameters.
00042 // If they are the exact same type, then TypesEqual::value is the boolean true,
00043 // otherwise TypesEqual::value is the boolean false.
00044 template <typename T1, typename T2>
00045 struct TypesEqual {
00046   static const bool value = false;
00047 };
00048 
00049 template <typename T>
00050 struct TypesEqual<T,T> {
00051   static const bool value = true;
00052 };
00053 
00054 
00055 // Complete list of scalar classes, needed for disambiguation
00056 template <typename T>
00057 struct ScalarTraits {
00058   static const bool value = false;
00059 };
00060 
00061 #define ScalarTraits_true(type)                                 \
00062   template<>                                                    \
00063   struct ScalarTraits<type> { static const bool value = true; }
00064 
00065 ScalarTraits_true(char);
00066 ScalarTraits_true(short);
00067 ScalarTraits_true(int);
00068 ScalarTraits_true(long);
00069 ScalarTraits_true(unsigned char);
00070 ScalarTraits_true(unsigned short);
00071 ScalarTraits_true(unsigned int);
00072 ScalarTraits_true(unsigned long);
00073 ScalarTraits_true(float);
00074 ScalarTraits_true(double);
00075 ScalarTraits_true(long double);
00076 
00077 template<typename T>
00078 struct ScalarTraits<std::complex<T> > { static const bool value = ScalarTraits<T>::value; };
00079 
00080 
00081 
00082 // Operators using different but compatible types need a return value
00083 // based on whichever type the other can be upconverted into.  For
00084 // instance, the proper return type for
00085 // TypeVector<float>::operator*(double) is TypeVector<double>.  In
00086 // general, an operation using types S and T should return a value
00087 // based on CompareTypes<S,T>::supertype
00088 
00089 template<typename S, typename T>
00090 struct CompareTypes {
00091   typedef void supertype;
00092 };
00093 
00094 template<typename T>
00095 struct CompareTypes<T, T> {
00096   typedef T supertype;
00097 };
00098 
00099 template<typename T>
00100 struct CompareTypes<T, std::complex<T> > {
00101   typedef std::complex<T> supertype;
00102 };
00103 
00104 template<typename T>
00105 struct CompareTypes<std::complex<T>, T> {
00106   typedef std::complex<T> supertype;
00107 };
00108 
00109 // There's got to be some magic template way to do these better - but the best
00110 // thing on the net requires a bunch of Alexandrescu's code and doesn't work
00111 // with older compilers
00112 
00113 #define CompareTypes_super(a,b,super)           \
00114   template<>                                    \
00115   struct CompareTypes<a, b> {                   \
00116     typedef super supertype;                    \
00117   }
00118 
00119 #define SUPERTYPE(mysub,mysuper)                                        \
00120   CompareTypes_super(mysub, mysuper, mysuper);                          \
00121   CompareTypes_super(mysuper, mysub, mysuper);                          \
00122   CompareTypes_super(std::complex<mysub>, mysuper, std::complex<mysuper>); \
00123   CompareTypes_super(mysuper, std::complex<mysub>, std::complex<mysuper>); \
00124   CompareTypes_super(mysub, std::complex<mysuper>, std::complex<mysuper>); \
00125   CompareTypes_super(std::complex<mysuper>, mysub, std::complex<mysuper>); \
00126   CompareTypes_super(std::complex<mysub>, std::complex<mysuper>, std::complex<mysuper>); \
00127   CompareTypes_super(std::complex<mysuper>, std::complex<mysub>, std::complex<mysuper>)
00128 
00129 SUPERTYPE(unsigned char, short);
00130 SUPERTYPE(unsigned char, int);
00131 SUPERTYPE(unsigned char, float);
00132 SUPERTYPE(unsigned char, double);
00133 SUPERTYPE(unsigned char, long double);
00134 SUPERTYPE(unsigned short, int);
00135 SUPERTYPE(unsigned short, float);
00136 SUPERTYPE(unsigned short, double);
00137 SUPERTYPE(unsigned short, long double);
00138 SUPERTYPE(unsigned int, float);
00139 SUPERTYPE(unsigned int, double);
00140 SUPERTYPE(unsigned int, long double);
00141 SUPERTYPE(char, short);
00142 SUPERTYPE(char, int);
00143 SUPERTYPE(char, float);
00144 SUPERTYPE(char, double);
00145 SUPERTYPE(char, long double);
00146 SUPERTYPE(short, int);
00147 SUPERTYPE(short, float);
00148 SUPERTYPE(short, double);
00149 SUPERTYPE(short, long double);
00150 SUPERTYPE(int, float);
00151 SUPERTYPE(int, double);
00152 SUPERTYPE(int, long double);
00153 SUPERTYPE(float, double);
00154 SUPERTYPE(float, long double);
00155 SUPERTYPE(double, long double);
00156 
00157 #undef CompareTypes_super
00158 #undef SUPERTYPE
00159 
00160 // gcc can't tell which of the following is the most specialized?  Weak.
00161 /*
00162   template<typename S, typename T>
00163   struct CompareTypes<std::complex<S>, std::complex<T> > {
00164   typedef std::complex<typename CompareTypes<S, T>::supertype> supertype;
00165   };
00166 
00167   template<typename S, typename T>
00168   struct CompareTypes<std::complex<S>, T> {
00169   typedef std::complex<typename CompareTypes<S, T>::supertype> supertype;
00170   };
00171 
00172   template<typename S, typename T>
00173   struct CompareTypes<S, std::complex<T> > {
00174   typedef std::complex<typename CompareTypes<S, T>::supertype> supertype;
00175   };
00176 */
00177 
00178 } // namespace libMesh
00179 
00180 #endif // LIBMESH_COMPARE_TYPES_H