Reference documentation for deal.II version GIT 196b8d1939 2022-07-03 13:35:01+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
template_constraints.h
Go to the documentation of this file.
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2003 - 2022 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 
23 
24 #include <complex>
25 #include <utility>
26 
28 
29 // Detection idiom adapted from Version 2 of the C++ Extensions for Library
30 // Fundamentals, ISO/IEC TS 19568:2017
31 namespace internal
32 {
38  namespace SupportsOperation
39  {
40  template <class...>
41  using void_t = void;
42 
49  template <class Default,
50  class AlwaysVoid,
51  template <class...>
52  class Op,
53  class... Args>
54  struct detector
55  {
56  using value_t = std::false_type;
57  using type = Default;
58  };
59 
72  template <class Default, template <class...> class Op, class... Args>
73  struct detector<Default, void_t<Op<Args...>>, Op, Args...>
74  {
75  using value_t = std::true_type;
76  using type = Op<Args...>;
77  };
78 
79 
85  {};
86 
91  struct nonesuch : private nonesuch_base
92  {
93  ~nonesuch() = delete;
94  nonesuch(nonesuch const &) = delete;
95  void
96  operator=(nonesuch const &) = delete;
97  };
98 
99  template <class Default, template <class...> class Op, class... Args>
100  using detected_or = detector<Default, void, Op, Args...>;
101 
102  template <template <class...> class Op, class... Args>
103  using is_detected = typename detected_or<nonesuch, Op, Args...>::value_t;
104 
105  template <template <class...> class Op, class... Args>
106  using detected_t = typename detected_or<nonesuch, Op, Args...>::type;
107 
108  template <class Default, template <class...> class Op, class... Args>
109  using detected_or_t = typename detected_or<Default, Op, Args...>::type;
110 
111  template <class Expected, template <class...> class Op, class... Args>
112  using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
113 
114  template <class To, template <class...> class Op, class... Args>
116  std::is_convertible<detected_t<Op, Args...>, To>;
117  } // namespace SupportsOperation
118 
119 
154  template <template <class...> class Op, class... Args>
155  constexpr bool is_supported_operation =
156  SupportsOperation::is_detected<Op, Args...>::value;
157 } // namespace internal
158 
159 
160 
161 namespace internal
162 {
163  namespace TemplateConstraints
164  {
165  // TODO: Once we are able to use DEAL_II_HAVE_CXX17, the following classes
166  // can be made much simpler with the help of fold expressions, see
167  // https://en.cppreference.com/w/cpp/language/fold
168 
169  // helper struct for is_base_of_all and all_same_as
170  template <bool... Values>
171  struct BoolStorage;
172 
173 
182  template <bool... Values>
183  struct all_true
184  {
185  static constexpr bool value =
186  std::is_same<BoolStorage<Values..., true>,
187  BoolStorage<true, Values...>>::value;
188  };
189 
190 
195  template <bool... Values>
196  struct any_true;
197 
198 
199  template <bool V1, bool... Values>
200  struct any_true<V1, Values...>
201  {
202  static constexpr bool value = V1 || any_true<Values...>::value;
203  };
204 
205 
206  template <>
207  struct any_true<>
208  {
209  static constexpr bool value = false;
210  };
211  } // namespace TemplateConstraints
212 } // namespace internal
213 
220 template <class Base, class... Derived>
222 {
224  std::is_base_of<Base, Derived>::value...>::value;
225 };
226 
227 
228 
235 template <class Type, class... Types>
237 {
239  std::is_same<Type, Types>::value...>::value;
240 };
241 
242 
243 
250 template <class Type, class... Types>
252 {
254  std::is_same<Type, Types>::value...>::value;
255 };
256 
257 
258 
259 /*
260  * A generalization of `std::enable_if` that only works if
261  * <i>all</i> of the given boolean template parameters are
262  * true.
263  */
264 template <bool... Values>
266  : std::enable_if<internal::TemplateConstraints::all_true<Values...>::value>
267 {};
268 
269 
270 
276 template <typename T>
278  decltype(std::begin(std::declval<T>()), std::end(std::declval<T>()));
279 
280 template <typename T>
281 constexpr bool has_begin_and_end =
282  internal::is_supported_operation<begin_and_end_t, T>;
283 
284 
285 
343 template <typename T>
344 struct identity
345 {
346  using type = T;
347 };
348 
349 
350 
356 template <typename ArgType, typename ValueType>
358 {
359  ValueType value;
360  ValueType
361  operator()(const ArgType &)
362  {
363  return value;
364  }
365 };
366 
367 
368 
386 {
391  template <typename T>
392  static bool
393  equal(const T *p1, const T *p2)
394  {
395  return (p1 == p2);
396  }
397 
398 
405  template <typename T, typename U>
406  static bool
407  equal(const T *, const U *)
408  {
409  return false;
410  }
411 };
412 
413 
414 
415 namespace internal
416 {
427  template <typename T, typename U>
429  {
430  using type = decltype(std::declval<T>() * std::declval<U>());
431  };
432 
433 } // namespace internal
434 
435 
436 
483 template <typename T, typename U>
485 {
486  using type =
488  typename std::decay<U>::type>::type;
489 };
490 
491 namespace internal
492 {
493  // Annoyingly, there is no std::complex<T>::operator*(U) for scalars U
494  // other than T (not even in C++11, or C++14). We provide our own overloads
495  // in base/complex_overloads.h, but in order for them to work, we have to
496  // manually specify all products we want to allow:
497 
498  template <typename T>
499  struct ProductTypeImpl<std::complex<T>, std::complex<T>>
500  {
501  using type = std::complex<T>;
502  };
503 
504  template <typename T, typename U>
505  struct ProductTypeImpl<std::complex<T>, std::complex<U>>
506  {
507  using type = std::complex<typename ProductType<T, U>::type>;
508  };
509 
510  template <typename U>
511  struct ProductTypeImpl<double, std::complex<U>>
512  {
513  using type = std::complex<typename ProductType<double, U>::type>;
514  };
515 
516  template <typename T>
517  struct ProductTypeImpl<std::complex<T>, double>
518  {
519  using type = std::complex<typename ProductType<T, double>::type>;
520  };
521 
522  template <typename U>
523  struct ProductTypeImpl<float, std::complex<U>>
524  {
525  using type = std::complex<typename ProductType<float, U>::type>;
526  };
527 
528  template <typename T>
529  struct ProductTypeImpl<std::complex<T>, float>
530  {
531  using type = std::complex<typename ProductType<T, float>::type>;
532  };
533 
534 } // namespace internal
535 
536 
537 
593 template <typename T>
595 
596 
597 template <>
599 {
600  using type = double;
601 };
602 
603 template <>
604 struct EnableIfScalar<float>
605 {
606  using type = float;
607 };
608 
609 template <>
610 struct EnableIfScalar<long double>
611 {
612  using type = long double;
613 };
614 
615 template <>
616 struct EnableIfScalar<int>
617 {
618  using type = int;
619 };
620 
621 template <>
622 struct EnableIfScalar<unsigned int>
623 {
624  using type = unsigned int;
625 };
626 
627 template <typename T>
628 struct EnableIfScalar<std::complex<T>>
629 {
630  using type = std::complex<T>;
631 };
632 
633 
635 
636 #endif
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:442
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:443
static const char U
static const char T
VectorType::value_type * begin(VectorType &V)
VectorType::value_type * end(VectorType &V)
typename detected_or< Default, Op, Args... >::type detected_or_t
std::is_convertible< detected_t< Op, Args... >, To > is_detected_convertible
typename detected_or< nonesuch, Op, Args... >::value_t is_detected
typename detected_or< nonesuch, Op, Args... >::type detected_t
std::is_same< Expected, detected_t< Op, Args... > > is_detected_exact
constexpr bool is_supported_operation
static bool equal(const T *p1, const T *p2)
static bool equal(const T *, const U *)
typename internal::ProductTypeImpl< typename std::decay< T >::type, typename std::decay< U >::type >::type type
static constexpr bool value
ValueType operator()(const ArgType &)
std::complex< typename ProductType< double, U >::type > type
std::complex< typename ProductType< float, U >::type > type
std::complex< typename ProductType< T, double >::type > type
std::complex< typename ProductType< T, float >::type > type
std::complex< typename ProductType< T, U >::type > type
decltype(std::declval< T >() *std::declval< U >()) type
nonesuch(nonesuch const &)=delete
void operator=(nonesuch const &)=delete
static constexpr bool value
static constexpr bool value
decltype(std::begin(std::declval< T >()), std::end(std::declval< T >())) begin_and_end_t
constexpr bool has_begin_and_end