$extrastylesheet
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