compare_types.h
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2018 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 
19 #ifndef LIBMESH_COMPARE_TYPES_H
20 #define LIBMESH_COMPARE_TYPES_H
21 
22 // System includes
23 #include <complex>
24 
25 namespace libMesh
26 {
27 
28 // Copy of boost's enable_if_c
29 
30 namespace boostcopy {
31 template <bool B, class T = void>
32 struct enable_if_c {
33  typedef T type;
34 };
35 
36 template <class T>
37 struct enable_if_c<false, T> {};
38 }
39 
40 
41 // TypesEqual takes two types as parameters.
42 // If they are the exact same type, then TypesEqual::value is the boolean true,
43 // otherwise TypesEqual::value is the boolean false.
44 template <typename T1, typename T2>
45 struct TypesEqual {
46  static const bool value = false;
47 };
48 
49 template <typename T>
50 struct TypesEqual<T,T> {
51  static const bool value = true;
52 };
53 
54 
55 // Complete list of scalar classes, needed for disambiguation
56 template <typename T>
57 struct ScalarTraits {
58  static const bool value = false;
59 };
60 
61 #define ScalarTraits_true(type) \
62  template<> \
63  struct ScalarTraits<type> { static const bool value = true; }
64 
65 ScalarTraits_true(char);
66 ScalarTraits_true(short);
68 ScalarTraits_true(long);
69 ScalarTraits_true(unsigned char);
70 ScalarTraits_true(unsigned short);
71 ScalarTraits_true(unsigned int);
72 ScalarTraits_true(unsigned long);
73 ScalarTraits_true(float);
74 ScalarTraits_true(double);
75 ScalarTraits_true(long double);
76 
77 template<typename T>
78 struct ScalarTraits<std::complex<T>> { static const bool value = ScalarTraits<T>::value; };
79 
80 
81 
82 // Operators using different but compatible types need a return value
83 // based on whichever type the other can be upconverted into. For
84 // instance, the proper return type for
85 // TypeVector<float>::operator*(double) is TypeVector<double>. In
86 // general, an operation using types S and T should return a value
87 // based on CompareTypes<S,T>::supertype
88 
89 template<typename S, typename T>
90 struct CompareTypes {
91  typedef void supertype;
92 };
93 
94 template<typename T>
95 struct CompareTypes<T, T> {
96  typedef T supertype;
97 };
98 
99 template<typename T>
100 struct CompareTypes<T, std::complex<T>> {
101  typedef std::complex<T> supertype;
102 };
103 
104 template<typename T>
105 struct CompareTypes<std::complex<T>, T> {
106  typedef std::complex<T> supertype;
107 };
108 
109 // There's got to be some magic template way to do these better - but the best
110 // thing on the net requires a bunch of Alexandrescu's code and doesn't work
111 // with older compilers
112 
113 #define CompareTypes_super(a,b,super) \
114  template<> \
115  struct CompareTypes<a, b> { \
116  typedef super supertype; \
117  }
118 
119 #define SUPERTYPE(mysub,mysuper) \
120  CompareTypes_super(mysub, mysuper, mysuper); \
121  CompareTypes_super(mysuper, mysub, mysuper); \
122  CompareTypes_super(std::complex<mysub>, mysuper, std::complex<mysuper>); \
123  CompareTypes_super(mysuper, std::complex<mysub>, std::complex<mysuper>); \
124  CompareTypes_super(mysub, std::complex<mysuper>, std::complex<mysuper>); \
125  CompareTypes_super(std::complex<mysuper>, mysub, std::complex<mysuper>); \
126  CompareTypes_super(std::complex<mysub>, std::complex<mysuper>, std::complex<mysuper>); \
127  CompareTypes_super(std::complex<mysuper>, std::complex<mysub>, std::complex<mysuper>)
128 
129 SUPERTYPE(unsigned char, short);
130 SUPERTYPE(unsigned char, int);
131 SUPERTYPE(unsigned char, float);
132 SUPERTYPE(unsigned char, double);
133 SUPERTYPE(unsigned char, long double);
134 SUPERTYPE(unsigned short, int);
135 SUPERTYPE(unsigned short, float);
136 SUPERTYPE(unsigned short, double);
137 SUPERTYPE(unsigned short, long double);
138 SUPERTYPE(unsigned int, float);
139 SUPERTYPE(unsigned int, double);
140 SUPERTYPE(unsigned int, long double);
141 SUPERTYPE(char, short);
142 SUPERTYPE(char, int);
143 SUPERTYPE(char, float);
144 SUPERTYPE(char, double);
145 SUPERTYPE(char, long double);
146 SUPERTYPE(short, int);
147 SUPERTYPE(short, float);
148 SUPERTYPE(short, double);
149 SUPERTYPE(short, long double);
150 SUPERTYPE(int, float);
151 SUPERTYPE(int, double);
152 SUPERTYPE(int, long double);
153 SUPERTYPE(float, double);
154 SUPERTYPE(float, long double);
155 SUPERTYPE(double, long double);
156 
157 #undef CompareTypes_super
158 #undef SUPERTYPE
159 
160 // gcc can't tell which of the following is the most specialized? Weak.
161 /*
162  template<typename S, typename T>
163  struct CompareTypes<std::complex<S>, std::complex<T>> {
164  typedef std::complex<typename CompareTypes<S, T>::supertype> supertype;
165  };
166 
167  template<typename S, typename T>
168  struct CompareTypes<std::complex<S>, T> {
169  typedef std::complex<typename CompareTypes<S, T>::supertype> supertype;
170  };
171 
172  template<typename S, typename T>
173  struct CompareTypes<S, std::complex<T>> {
174  typedef std::complex<typename CompareTypes<S, T>::supertype> supertype;
175  };
176 */
177 
178 } // namespace libMesh
179 
180 #endif // LIBMESH_COMPARE_TYPES_H
static const bool value
Definition: compare_types.h:46
SUPERTYPE(unsigned char, short)
ScalarTraits_true(char)
static const bool value
Definition: compare_types.h:58