1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2003 - 2020 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
16 #ifndef dealii_template_constraints_h
17 #define dealii_template_constraints_h
18 
19 
20 #include <deal.II/base/config.h>
21 
22 #include <deal.II/base/complex_overloads.h>
23 
24 #include <complex>
25 #include <iterator>
26 #include <utility>
27 
28 DEAL_II_NAMESPACE_OPEN
29 
30 namespace internal
31 {
32   namespace TemplateConstraints
33   {
34     // helper struct for is_base_of_all and all_same_as
35     template <bool... Values>
36     struct BoolStorage;
37 
38 
39     /**
40      * A helper class whose `value` member is true or false depending on
41      * whether all of the given boolean template arguments are true.
42      */
43     template <bool... Values>
44     struct all_true
45     {
46       static constexpr bool value =
47         std::is_same<BoolStorage<Values..., true>,
48                      BoolStorage<true, Values...>>::value;
49     };
50   } // namespace TemplateConstraints
51 } // namespace internal
52 
53 /**
54  * This struct is a generalization of std::is_base_of<Base, Derived>
55  * to template parameter packs and tests if all of the Derived...
56  * classes have Base as base class or are Base itself. The result
57  * is stored in the member variable value.
58  */
59 template <class Base, class... Derived>
60 struct is_base_of_all
61 {
62   static constexpr bool value = internal::TemplateConstraints::all_true<
63     std::is_base_of<Base, Derived>::value...>::value;
64 };
65 
66 
67 
68 /**
69  * This struct is a generalization of std::is_same to template
70  * parameter packs and tests if all of the types in the `Types...`
71  * parameter pack are equal to the `Type` given as first template
72  * argument. The result is stored in the member variable value.
73  */
74 template <class Type, class... Types>
75 struct all_same_as
76 {
77   static constexpr bool value = internal::TemplateConstraints::all_true<
78     std::is_same<Type, Types>::value...>::value;
79 };
80 
81 
82 
83 /*
84  * A generalization of `std::enable_if` that only works if
85  * <i>all</i> of the given boolean template parameters are
86  * true.
87  */
88 template <bool... Values>
89 struct enable_if_all
90   : std::enable_if<internal::TemplateConstraints::all_true<Values...>::value>
91 {};
92 
93 
94 
95 /**
96  * A type trait that checks to see if a class behaves as an iterable container
97  * that has a beginning and an end. This implies that the class either defines
98  * the `begin()` and `end()` functions, or is a C-style array.
99  */
100 template <typename T>
101 class has_begin_and_end
102 {
103   template <typename C>
104   static std::false_type
105   test(...);
106 
107   template <typename C>
108   static auto
109   test(int) -> decltype(std::begin(std::declval<C>()),
110                         std::end(std::declval<C>()),
111                         std::true_type());
112 
113 public:
114   using type = decltype(test<T>(0));
115 
116   static const bool value = type::value;
117 };
118 
119 
120 
121 /**
122  * A template class that simply exports its template argument as a local
123  * alias. This class, while at first appearing useless, makes sense in the
124  * following context: if you have a function template as follows:
125  * @code
126  * template <typename T>
127  * void f(T, T);
128  * @endcode
129  * then it can't be called in an expression like <code>f(1, 3.141)</code>
130  * because the type <code>T</code> of the template can not be deduced in a
131  * unique way from the types of the arguments. However, if the template is
132  * written as
133  * @code
134  * template <typename T>
135  * void f(T, typename identity<T>::type);
136  * @endcode
137  * then the call becomes valid: the type <code>T</code> is not deducible from
138  * the second argument to the function, so only the first argument
139  * participates in template type resolution.
140  *
141  * The context for this feature is as follows: consider
142  * @code
143  * template <typename RT, typename A>
144  * void forward_call(RT (*p) (A), A a)
145  * {
146  *   p(a);
147  * }
148  *
149  * void h (double);
150  *
151  * void g()
152  * {
153  *   forward_call(&h, 1);
154  * }
155  * @endcode
156  * This code fails to compile because the compiler can't decide whether the
157  * template type <code>A</code> should be <code>double</code> (from the
158  * signature of the function given as first argument to
159  * <code>forward_call</code>, or <code>int</code> because the expression
160  * <code>1</code> has that type. Of course, what we would like the compiler to
161  * do is simply cast the <code>1</code> to <code>double</code>. We can achieve
162  * this by writing the code as follows:
163  * @code
164  * template <typename RT, typename A>
165  * void forward_call(RT (*p) (A), typename identity<A>::type a)
166  * {
167  *   p(a);
168  * }
169  *
170  * void h (double);
171  *
172  * void g()
173  * {
174  *   forward_call(&h, 1);
175  * }
176  * @endcode
177  */
178 template <typename T>
179 struct identity
180 {
181   using type = T;
182 };
183 
184 
185 
186 /**
187  * A class to perform comparisons of arbitrary pointers for equality. In some
188  * circumstances, one would like to make sure that two arguments to a function
189  * are not the same object. One would, in this case, make sure that their
190  * addresses are not the same. However, sometimes the types of these two
191  * arguments may be template types, and they may be the same type or not. In
192  * this case, a simple comparison as in <tt>&object1 != &object2</tt> does
193  * only work if the types of the two objects are equal, but the compiler will
194  * barf if they are not. However, in the latter case, since the types of the
195  * two objects are different, we can be sure that the two objects cannot be
196  * the same.
197  *
198  * This class implements a comparison function that always returns @p false if
199  * the types of its two arguments are different, and returns <tt>p1 == p2</tt>
200  * otherwise.
201  */
202 struct PointerComparison
203 {
204   /**
205    * Comparison function for pointers of the same type. Returns @p true if the
206    * two pointers are equal.
207    */
208   template <typename T>
209   static bool
equalPointerComparison210   equal(const T *p1, const T *p2)
211   {
212     return (p1 == p2);
213   }
214 
215 
216   /**
217    * Comparison function for pointers of different types. The C++ language
218    * does not allow comparing these pointers using <tt>operator==</tt>.
219    * However, since the two pointers have different types, we know that they
220    * can't be the same, so we always return @p false.
221    */
222   template <typename T, typename U>
223   static bool
equalPointerComparison224   equal(const T *, const U *)
225   {
226     return false;
227   }
228 };
229 
230 
231 
232 namespace internal
233 {
234   /**
235    * A struct that implements the default product type resulting from the
236    * multiplication of two types.
237    *
238    * @note Care should be taken when @p T or @p U have qualifiers (@p const or
239    * @p volatile) or are @p lvalue or @p rvalue references! It is recommended
240    * that specialization of this class is only made for unqualified (fully
241    * stripped) types and that the ProductType class be used to determine the
242    * result of operating with (potentially) qualified types.
243    */
244   template <typename T, typename U>
245   struct ProductTypeImpl
246   {
247     using type = decltype(std::declval<T>() * std::declval<U>());
248   };
249 
250 } // namespace internal
251 
252 
253 
254 /**
255  * A class with a local alias that represents the type that results from the
256  * product of two variables of type @p T and @p U. In other words, we would
257  * like to infer the type of the <code>product</code> variable in code like
258  * this:
259  * @code
260  *   T t;
261  *   U u;
262  *   auto product = t*u;
263  * @endcode
264  * The local alias of this structure represents the type the variable
265  * <code>product</code> would have.
266  *
267  *
268  * <h3>Where is this useful</h3>
269  *
270  * The purpose of this class is principally to represent the type one needs to
271  * use to represent the values or gradients of finite element fields at
272  * quadrature points. For example, assume you are storing the values $U_j$ of
273  * unknowns in a Vector<float>, then evaluating $u_h(x_q) = \sum_j U_j
274  * \varphi_j(x_q)$ at quadrature points results in values $u_h(x_q)$ that need
275  * to be stored as @p double variables because the $U_j$ are @p float values
276  * and the $\varphi_j(x_q)$ are computed as @p double values, and the product
277  * are then @p double values. On the other hand, if you store your unknowns
278  * $U_j$ as <code>std::complex@<double@></code> values and you try to evaluate
279  * $\nabla u_h(x_q) = \sum_j U_j \nabla\varphi_j(x_q)$ at quadrature points,
280  * then the gradients $\nabla u_h(x_q)$ need to be stored as objects of type
281  * <code>Tensor@<1,dim,std::complex@<double@>@></code> because that's what you
282  * get when you multiply a complex number by a <code>Tensor@<1,dim@></code>
283  * (the type used to represent the gradient of shape functions of scalar
284  * finite elements).
285  *
286  * Likewise, if you are using a vector valued element (with dim components)
287  * and the $U_j$ are stored as @p double variables, then $u_h(x_q) = \sum_j
288  * U_j \varphi_j(x_q)$ needs to have type <code>Tensor@<1,dim@></code>
289  * (because the shape functions have type <code>Tensor@<1,dim@></code>).
290  * Finally, if you store the $U_j$ as objects of type
291  * <code>std::complex@<double@></code> and you have a vector valued element,
292  * then the gradients $\nabla u_h(x_q) = \sum_j U_j \nabla\varphi_j(x_q)$ will
293  * result in objects of type <code>Tensor@<2,dim,std::complex@<double@>
294  * @></code>.
295  *
296  * In all of these cases, this type is used to identify which type needs to be
297  * used for the result of computing the product of unknowns and the values,
298  * gradients, or other properties of shape functions.
299  */
300 template <typename T, typename U>
301 struct ProductType
302 {
303   using type =
304     typename internal::ProductTypeImpl<typename std::decay<T>::type,
305                                        typename std::decay<U>::type>::type;
306 };
307 
308 namespace internal
309 {
310   // Annoyingly, there is no std::complex<T>::operator*(U) for scalars U
311   // other than T (not even in C++11, or C++14). We provide our own overloads
312   // in base/complex_overloads.h, but in order for them to work, we have to
313   // manually specify all products we want to allow:
314 
315   template <typename T>
316   struct ProductTypeImpl<std::complex<T>, std::complex<T>>
317   {
318     using type = std::complex<T>;
319   };
320 
321   template <typename T, typename U>
322   struct ProductTypeImpl<std::complex<T>, std::complex<U>>
323   {
324     using type = std::complex<typename ProductType<T, U>::type>;
325   };
326 
327   template <typename U>
328   struct ProductTypeImpl<double, std::complex<U>>
329   {
330     using type = std::complex<typename ProductType<double, U>::type>;
331   };
332 
333   template <typename T>
334   struct ProductTypeImpl<std::complex<T>, double>
335   {
336     using type = std::complex<typename ProductType<T, double>::type>;
337   };
338 
339   template <typename U>
340   struct ProductTypeImpl<float, std::complex<U>>
341   {
342     using type = std::complex<typename ProductType<float, U>::type>;
343   };
344 
345   template <typename T>
346   struct ProductTypeImpl<std::complex<T>, float>
347   {
348     using type = std::complex<typename ProductType<T, float>::type>;
349   };
350 
351 } // namespace internal
352 
353 
354 
355 /**
356  * This class provides a local alias @p type that is equal to the template
357  * argument but only if the template argument corresponds to a scalar type
358  * (i.e., one of the floating point types, signed or unsigned integer, or a
359  * complex number). If the template type @p T is not a scalar, then no class
360  * <code>EnableIfScalar@<T@></code> is declared and, consequently, no local
361  * alias is available.
362  *
363  * The purpose of the class is to disable certain template functions if one of
364  * the arguments is not a scalar number. By way of (nonsensical) example,
365  * consider the following function:
366  * @code
367  *   template <typename T>
368  *   T multiply (const T t1, const T t2)
369  *   {
370  *     return t1*t2;
371  *   }
372  * @endcode
373  * This function can be called with any two arguments of the same type @p T.
374  * This includes arguments for which this clearly makes no sense.
375  * Consequently, one may want to restrict the function to only scalars, and
376  * this can be written as
377  * @code
378  *   template <typename T>
379  *   typename EnableIfScalar<T>::type
380  *   multiply (const T t1, const T t2)
381  *   {
382  *     return t1*t2;
383  *   }
384  * @endcode
385  * At a place where you call the function, the compiler will deduce the type
386  * @p T from the arguments. For example, in
387  * @code
388  *   multiply(1.234, 2.345);
389  * @endcode
390  * it will deduce @p T to be @p double, and because
391  * <code>EnableIfScalar@<double@>::%type</code> equals @p double, the compiler
392  * will instantiate a function <code>double multiply(const double, const
393  * double)</code> from the template above. On the other hand, in a context
394  * like
395  * @code
396  *   std::vector<char> v1, v2;
397  *   multiply(v1, v2);
398  * @endcode
399  * the compiler will deduce @p T to be <code>std::vector@<char@></code> but
400  * because <code>EnableIfScalar@<std::vector@<char@>@>::%type</code> does not
401  * exist the compiler does not consider the template for instantiation. This
402  * technique is called "Substitution Failure is not an Error (SFINAE)". It
403  * makes sure that the template function can not even be called, rather than
404  * leading to a later error about the fact that the operation
405  * <code>t1*t2</code> is not defined (or may lead to some nonsensical result).
406  * It also allows the declaration of overloads of a function such as @p
407  * multiply for different types of arguments, without resulting in ambiguous
408  * call errors by the compiler.
409  */
410 template <typename T>
411 struct EnableIfScalar;
412 
413 
414 template <>
415 struct EnableIfScalar<double>
416 {
417   using type = double;
418 };
419 
420 template <>
421 struct EnableIfScalar<float>
422 {
423   using type = float;
424 };
425 
426 template <>
427 struct EnableIfScalar<long double>
428 {
429   using type = long double;
430 };
431 
432 template <>
433 struct EnableIfScalar<int>
434 {
435   using type = int;
436 };
437 
438 template <>
439 struct EnableIfScalar<unsigned int>
440 {
441   using type = unsigned int;
442 };
443 
444 template <typename T>
445 struct EnableIfScalar<std::complex<T>>
446 {
447   using type = std::complex<T>;
448 };
449 
450 
451 DEAL_II_NAMESPACE_CLOSE
452 
453 #endif
454