Reference documentation for deal.II version 9.4.1
\(\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\}}\)
Loading...
Searching...
No Matches
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
31namespace 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 =
157} // namespace internal
158
159
160
161namespace 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>
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
220template <class Base, class... Derived>
222{
224 std::is_base_of<Base, Derived>::value...>::value;
225};
226
227
228
235template <class Type, class... Types>
237{
239 std::is_same<Type, Types>::value...>::value;
240};
241
242
243
250template <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 */
264template <bool... Values>
266 : std::enable_if<internal::TemplateConstraints::all_true<Values...>::value>
267{};
268
269
270
276template <typename T>
278 decltype(std::begin(std::declval<T>()), std::end(std::declval<T>()));
279
280template <typename T>
281constexpr bool has_begin_and_end =
282 internal::is_supported_operation<begin_and_end_t, T>;
283
284
285
343template <typename T>
345{
346 using type = T;
347};
348
349
350
356template <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
415namespace 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
483template <typename T, typename U>
485{
486 using type =
488 typename std::decay<U>::type>::type;
489};
490
491namespace 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
593template <typename T>
595
596
597template <>
598struct EnableIfScalar<double>
599{
600 using type = double;
601};
602
603template <>
604struct EnableIfScalar<float>
605{
606 using type = float;
607};
608
609template <>
610struct EnableIfScalar<long double>
611{
612 using type = long double;
613};
614
615template <>
617{
618 using type = int;
619};
620
621template <>
622struct EnableIfScalar<unsigned int>
623{
624 using type = unsigned int;
625};
626
627template <typename T>
628struct 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
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
STL namespace.
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