Reference documentation for deal.II version 9.5.0
\(\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 - 2023 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
24
25#include <complex>
26#include <type_traits>
27#include <utility>
28
29
31
32// Detection idiom adapted from Version 2 of the C++ Extensions for Library
33// Fundamentals, ISO/IEC TS 19568:2017
34namespace internal
35{
41 namespace SupportsOperation
42 {
43 template <class...>
44 using void_t = void;
45
52 template <class Default,
53 class AlwaysVoid,
54 template <class...>
55 class Op,
56 class... Args>
57 struct detector
58 {
59 using value_t = std::false_type;
60 using type = Default;
61 };
62
75 template <class Default, template <class...> class Op, class... Args>
76 struct detector<Default, void_t<Op<Args...>>, Op, Args...>
77 {
78 using value_t = std::true_type;
79 using type = Op<Args...>;
80 };
81
82
88 {};
89
94 struct nonesuch : private nonesuch_base
95 {
96 ~nonesuch() = delete;
97 nonesuch(nonesuch const &) = delete;
98 void
99 operator=(nonesuch const &) = delete;
100 };
101
102 template <class Default, template <class...> class Op, class... Args>
103 using detected_or = detector<Default, void, Op, Args...>;
104
105 template <template <class...> class Op, class... Args>
106 using is_detected = typename detected_or<nonesuch, Op, Args...>::value_t;
107
108 template <template <class...> class Op, class... Args>
109 using detected_t = typename detected_or<nonesuch, Op, Args...>::type;
110
111 template <class Default, template <class...> class Op, class... Args>
112 using detected_or_t = typename detected_or<Default, Op, Args...>::type;
113
114 template <class Expected, template <class...> class Op, class... Args>
115 using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
116
117 template <class To, template <class...> class Op, class... Args>
119 std::is_convertible<detected_t<Op, Args...>, To>;
120 } // namespace SupportsOperation
121
122
157 template <template <class...> class Op, class... Args>
158 constexpr bool is_supported_operation =
160} // namespace internal
161
162
163
164namespace internal
165{
166 namespace TemplateConstraints
167 {
168 // TODO: Once we are able to use DEAL_II_HAVE_CXX17, the following classes
169 // can be made much simpler with the help of fold expressions, see
170 // https://en.cppreference.com/w/cpp/language/fold
171
172 // helper struct for is_base_of_all and all_same_as
173 template <bool... Values>
175
176
185 template <bool... Values>
186 struct all_true
187 {
188 static constexpr bool value =
189 std::is_same<BoolStorage<Values..., true>,
190 BoolStorage<true, Values...>>::value;
191 };
192
193
198 template <bool... Values>
199 struct any_true;
200
201
202 template <bool V1, bool... Values>
203 struct any_true<V1, Values...>
204 {
205 static constexpr bool value = V1 || any_true<Values...>::value;
206 };
207
208
209 template <>
210 struct any_true<>
211 {
212 static constexpr bool value = false;
213 };
214 } // namespace TemplateConstraints
215} // namespace internal
216
223template <class Base, class... Derived>
225{
227 std::is_base_of<Base, Derived>::value...>::value;
228};
229
230
231
238template <class Type, class... Types>
240{
242 std::is_same<Type, Types>::value...>::value;
243};
244
245
246
253template <class Type, class... Types>
255{
257 std::is_same<Type, Types>::value...>::value;
258};
259
260
261
262/*
263 * A generalization of `std::enable_if` that only works if
264 * <i>all</i> of the given boolean template parameters are
265 * true. See [here](https://en.cppreference.com/w/cpp/types/enable_if)
266 * for what `std::enable_if` does.
267 *
268 * @note
269 * In contrast to `std::enable_if`, this template has no additional
270 * template type (which for `std::enable_if` is defaulted to `void`).
271 * As a consequence, this structure cannot be used for anything other
272 * than enabling or disabling a template declaration; in particular
273 * it cannot be used to set the return type of a function as one might
274 * do with something like
275 * @code
276 * template <typename T>
277 * typename std::enable_if<std::is_floating_point<T>::value, T>::type
278 * abs (const T t);
279 * @endcode
280 * which declares a function template `abs()` that can only be
281 * instantiated if `T` is a floating point type; this function then
282 * returns an object of type `T` as indicated by the last argument to
283 * `std::enable_if`. The reason `enable_if_all` does not allow providing
284 * this additional type is that variadic templates (here, the list of
285 * `bool` arguments) must be the last template argument.
286 */
287template <bool... Values>
289 : std::enable_if<internal::TemplateConstraints::all_true<Values...>::value>
290{};
291
292
293
294/*
295 * A generalization of `std::enable_if_t` that only works if
296 * <i>all</i> of the given boolean template parameters are
297 * true. See [here](https://en.cppreference.com/w/cpp/types/enable_if)
298 * for what `std::enable_if_t` does.
299 *
300 * @note
301 * In contrast to `std::enable_if_t`, this template has no additional
302 * template type (which for `std::enable_if` is defaulted to `void`).
303 * As a consequence, this structure cannot be used for anything other
304 * than enabling or disabling a template declaration; in particular
305 * it cannot be used to set the return type of a function as one might
306 * do with something like
307 * @code
308 * template <typename T>
309 * std::enable_if_t<std::is_floating_point<T>::value, T>
310 * abs (const T t);
311 * @endcode
312 * which declares a function template `abs()` that can only be
313 * instantiated if `T` is a floating point type; this function then
314 * returns an object of type `T` as indicated by the last argument to
315 * `std::enable_if`. The reason `enable_if_all` does not allow providing
316 * this additional type is that variadic templates (here, the list of
317 * `bool` arguments) must be the last template argument.
318 */
319template <bool... Values>
320using enable_if_all_t = typename enable_if_all<Values...>::type;
321
322
328template <typename T>
330 decltype(std::begin(std::declval<T>()), std::end(std::declval<T>()));
331
332template <typename T>
333constexpr bool has_begin_and_end =
334 internal::is_supported_operation<begin_and_end_t, T>;
335
336
344template <typename T>
345using identity DEAL_II_DEPRECATED_EARLY = std_cxx20::type_identity<T>;
346
347
353template <typename ArgType, typename ValueType>
355{
356 ValueType value;
357 ValueType
358 operator()(const ArgType &)
359 {
360 return value;
361 }
362};
363
364
365
383{
388 template <typename T>
389 static bool
390 equal(const T *p1, const T *p2)
391 {
392 return (p1 == p2);
393 }
394
395
402 template <typename T, typename U>
403 static bool
404 equal(const T *, const U *)
405 {
406 return false;
407 }
408};
409
410
411
412namespace internal
413{
424 template <typename T, typename U>
426 {
427 using type = decltype(std::declval<T>() * std::declval<U>());
428 };
429
430} // namespace internal
431
432
433
480template <typename T, typename U>
482{
483 using type =
485 typename std::decay<U>::type>::type;
486};
487
488namespace internal
489{
490 // Annoyingly, there is no std::complex<T>::operator*(U) for scalars U
491 // other than T (not even in C++11, or C++14). We provide our own overloads
492 // in base/complex_overloads.h, but in order for them to work, we have to
493 // manually specify all products we want to allow:
494
495 template <typename T>
496 struct ProductTypeImpl<std::complex<T>, std::complex<T>>
497 {
498 using type = std::complex<T>;
499 };
500
501 template <typename T, typename U>
502 struct ProductTypeImpl<std::complex<T>, std::complex<U>>
503 {
504 using type = std::complex<typename ProductType<T, U>::type>;
505 };
506
507 template <typename U>
508 struct ProductTypeImpl<double, std::complex<U>>
509 {
510 using type = std::complex<typename ProductType<double, U>::type>;
511 };
512
513 template <typename T>
514 struct ProductTypeImpl<std::complex<T>, double>
515 {
516 using type = std::complex<typename ProductType<T, double>::type>;
517 };
518
519 template <typename U>
520 struct ProductTypeImpl<float, std::complex<U>>
521 {
522 using type = std::complex<typename ProductType<float, U>::type>;
523 };
524
525 template <typename T>
526 struct ProductTypeImpl<std::complex<T>, float>
527 {
528 using type = std::complex<typename ProductType<T, float>::type>;
529 };
530
531} // namespace internal
532
533
534
590template <typename T>
592
593
594template <>
595struct EnableIfScalar<double>
596{
597 using type = double;
598};
599
600template <>
601struct EnableIfScalar<float>
602{
603 using type = float;
604};
605
606template <>
607struct EnableIfScalar<long double>
608{
609 using type = long double;
610};
611
612template <>
614{
615 using type = int;
616};
617
618template <>
619struct EnableIfScalar<unsigned int>
620{
621 using type = unsigned int;
622};
623
624template <typename T>
625struct EnableIfScalar<std::complex<T>>
626{
627 using type = std::complex<T>;
628};
629
630
631// Forward declarations of vector types
632template <typename Number>
633class Vector;
634
635template <typename Number>
636class BlockVector;
637
639{
640 template <typename Number>
641 class Vector;
642
643 template <typename Number>
645
646 namespace distributed
647 {
648 template <typename Number, typename MemorySpace>
649 class Vector;
650
651 template <typename Number>
652 class BlockVector;
653 } // namespace distributed
654} // namespace LinearAlgebra
655
656#ifdef DEAL_II_WITH_PETSC
658{
659 class VectorBase;
660 class Vector;
661 class BlockVector;
662
663 namespace MPI
664 {
665 class Vector;
666 class BlockVector;
667
668 class SparseMatrix;
669 class BlockSparseMatrix;
670 } // namespace MPI
671} // namespace PETScWrappers
672#endif
673
674#ifdef DEAL_II_WITH_TRILINOS
676{
677 namespace MPI
678 {
679 class Vector;
680 class BlockVector;
681 } // namespace MPI
682} // namespace TrilinosWrappers
683
684namespace LinearAlgebra
685{
686 namespace EpetraWrappers
687 {
688 class Vector;
689 }
690
691# ifdef DEAL_II_TRILINOS_WITH_TPETRA
692 namespace TpetraWrappers
693 {
694 template <typename Number>
695 class Vector;
696 }
697# endif
698} // namespace LinearAlgebra
699#endif
700
701
702
707namespace concepts
708{
709#if defined(DEAL_II_HAVE_CXX20) || defined(DOXYGEN)
719 template <int dim, int spacedim>
720 concept is_valid_dim_spacedim = (dim >= 1 && spacedim <= 3 &&
721 dim <= spacedim);
722
723 namespace internal
724 {
731 template <typename T>
732 inline constexpr bool is_dealii_vector_type = false;
733
734 template <typename Number>
735 inline constexpr bool is_dealii_vector_type<::Vector<Number>> = true;
736
737 template <typename Number>
738 inline constexpr bool is_dealii_vector_type<::BlockVector<Number>> =
739 true;
740
741 template <typename Number>
742 inline constexpr bool
744
745 template <typename Number>
746 inline constexpr bool
748
749 template <typename Number, typename MemorySpace>
750 inline constexpr bool is_dealii_vector_type<
752
753 template <typename Number>
754 inline constexpr bool is_dealii_vector_type<
756
757# ifdef DEAL_II_WITH_PETSC
758 template <>
760 true;
761
762 template <>
763 inline constexpr bool
765
766 template <>
767 inline constexpr bool
769
770 template <>
771 inline constexpr bool
773# endif
774
775# ifdef DEAL_II_WITH_TRILINOS
776 template <>
777 inline constexpr bool
779
780 template <>
781 inline constexpr bool
783
784 template <>
785 inline constexpr bool
787 true;
788
789# ifdef DEAL_II_TRILINOS_WITH_TPETRA
790 template <typename Number>
791 inline constexpr bool is_dealii_vector_type<
793# endif
794# endif
795
796
804 template <typename T>
805 inline constexpr bool is_dealii_petsc_vector_type = false;
806
807# ifdef DEAL_II_WITH_PETSC
808 template <>
809 inline constexpr bool
811
812 template <>
813 inline constexpr bool
815
816 template <>
817 inline constexpr bool
819
820 template <>
821 inline constexpr bool
823
824 template <>
825 inline constexpr bool
827 true;
828# endif
829
830
838 template <typename T>
839 inline constexpr bool is_dealii_petsc_matrix_type = false;
840
841# ifdef DEAL_II_WITH_PETSC
842 template <>
843 inline constexpr bool
845 true;
846
847 template <>
848 inline constexpr bool is_dealii_petsc_matrix_type<
850# endif
851 } // namespace internal
852
853
865 template <typename VectorType>
867 internal::is_dealii_vector_type<std::remove_cv_t<VectorType>>;
868
878 template <typename VectorType>
880 (std::is_const_v<VectorType> ==
881 false);
882
891 template <typename VectorType>
893 internal::is_dealii_petsc_vector_type<VectorType>;
894
903 template <typename VectorType>
905 internal::is_dealii_petsc_matrix_type<VectorType>;
906#endif
907} // namespace concepts
908
909
910template <int dim, int spacedim>
912class Triangulation;
913
914template <int dim, int spacedim>
916class DoFHandler;
917
918namespace parallel
919{
920 namespace distributed
921 {
922 template <int dim, int spacedim>
924 class Triangulation;
925 }
926 namespace shared
927 {
928 template <int dim, int spacedim>
930 class Triangulation;
931 }
932 namespace fullydistributed
933 {
934 template <int dim, int spacedim>
936 class Triangulation;
937 }
938} // namespace parallel
939
940namespace concepts
941{
942#if defined(DEAL_II_HAVE_CXX20) || defined(DOXYGEN)
943 namespace internal
944 {
945 template <typename T>
946 inline constexpr bool is_triangulation_or_dof_handler = false;
947
948 template <int dim, int spacedim>
949 inline constexpr bool
951
952 template <int dim, int spacedim>
953 inline constexpr bool is_triangulation_or_dof_handler<
955
956 template <int dim, int spacedim>
957 inline constexpr bool is_triangulation_or_dof_handler<
959
960 template <int dim, int spacedim>
961 inline constexpr bool is_triangulation_or_dof_handler<
963
964 template <int dim, int spacedim>
965 inline constexpr bool
967 } // namespace internal
968
969
977 template <typename MeshType>
979 internal::is_triangulation_or_dof_handler<MeshType>;
980#endif
981} // namespace concepts
982
983
984
986
987#endif
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:472
#define DEAL_II_CXX20_REQUIRES(condition)
Definition config.h:160
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:473
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
typename enable_if_all< Values... >::type enable_if_all_t
decltype(std::begin(std::declval< T >()), std::end(std::declval< T >())) begin_and_end_t
constexpr bool has_begin_and_end