Actual source code: type_traits.hpp
1: #pragma once
3: #include <petsc/private/petscimpl.h>
4: #include <petsc/private/cpp/macros.hpp>
6: #include <type_traits>
8: namespace Petsc
9: {
11: namespace util
12: {
14: #if PETSC_CPP_VERSION >= 14
15: using std::add_const_t;
16: using std::add_pointer_t;
17: using std::conditional_t;
18: using std::decay_t;
19: using std::enable_if_t;
20: using std::remove_const_t;
21: using std::remove_cv_t;
22: using std::remove_extent_t;
23: using std::remove_pointer_t;
24: using std::remove_reference_t;
25: using std::underlying_type_t;
26: using std::common_type_t;
27: #else // C++14
28: template <bool B, class T = void>
29: using enable_if_t = typename std::enable_if<B, T>::type;
30: template <bool B, class T, class F>
31: using conditional_t = typename std::conditional<B, T, F>::type;
32: template <class T>
33: using remove_const_t = typename std::remove_const<T>::type;
34: template <class T>
35: using add_const_t = typename std::add_const<T>::type;
36: template <class T>
37: using remove_cv_t = typename std::remove_cv<T>::type;
38: template <class T>
39: using underlying_type_t = typename std::underlying_type<T>::type;
40: template <class T>
41: using remove_pointer_t = typename std::remove_pointer<T>::type;
42: template <class T>
43: using add_pointer_t = typename std::add_pointer<T>::type;
44: template <class T>
45: using decay_t = typename std::decay<T>::type;
46: template <class T>
47: using remove_reference_t = typename std::remove_reference<T>::type;
48: template <class T>
49: using remove_extent_t = typename std::remove_extent<T>::type;
50: template <class... T>
51: using common_type_t = typename std::common_type<T...>::type;
52: #endif // C++14
54: #if PETSC_CPP_VERSION >= 17
55: using std::void_t;
56: using std::invoke_result_t;
57: using std::disjunction;
58: using std::conjunction;
59: #else
60: template <class...>
61: using void_t = void;
63: template <class F, class... Args>
64: using invoke_result_t = typename std::result_of<F && (Args && ...)>::type;
66: template <class...>
67: struct disjunction : std::false_type { };
68: template <class B1>
69: struct disjunction<B1> : B1 { };
70: template <class B1, class... Bn>
71: struct disjunction<B1, Bn...> : conditional_t<bool(B1::value), B1, disjunction<Bn...>> { };
73: template <class...>
74: struct conjunction : std::true_type { };
75: template <class B1>
76: struct conjunction<B1> : B1 { };
77: template <class B1, class... Bn>
78: struct conjunction<B1, Bn...> : conditional_t<bool(B1::value), conjunction<Bn...>, B1> { };
79: #endif
81: #if PETSC_CPP_VERSION >= 20
82: using std::remove_cvref;
83: using std::remove_cvref_t;
84: using std::type_identity;
85: using std::type_identity_t;
86: #else
87: template <class T>
88: struct remove_cvref {
89: using type = remove_cv_t<remove_reference_t<T>>;
90: };
92: template <class T>
93: using remove_cvref_t = typename remove_cvref<T>::type;
95: template <class T>
96: struct type_identity {
97: using type = T;
98: };
100: template <class T>
101: using type_identity_t = typename type_identity<T>::type;
102: #endif // C++20
104: #if PETSC_CPP_VERSION >= 23
105: using std::to_underlying;
106: #else
107: template <typename T>
108: static inline constexpr underlying_type_t<T> to_underlying(T value) noexcept
109: {
110: static_assert(std::is_enum<T>::value, "");
111: return static_cast<underlying_type_t<T>>(value);
112: }
114: #endif
116: template <typename... T>
117: struct always_false : std::false_type { };
119: namespace detail
120: {
122: template <typename T, typename U = _p_PetscObject>
123: struct is_derived_petsc_object_impl : conditional_t<!std::is_same<T, U>::value && std::is_base_of<_p_PetscObject, T>::value, std::true_type, std::false_type> { };
125: template <typename T>
126: struct is_derived_petsc_object_impl<T, decltype(T::hdr)> : conditional_t<std::is_class<T>::value && std::is_standard_layout<T>::value, std::true_type, std::false_type> { };
128: namespace test
129: {
131: struct Empty { };
133: struct IntHdr {
134: int hdr;
135: };
137: struct CPetscObject {
138: _p_PetscObject hdr;
139: int x;
140: };
142: struct CxxPetscObject {
143: void *x;
144: _p_PetscObject hdr;
145: };
147: struct CxxDerivedPetscObject : _p_PetscObject { };
149: // PetscObject is not derived from itself
150: static_assert(!::Petsc::util::detail::is_derived_petsc_object_impl<_p_PetscObject>::value, "");
151: // an int is not a PetscObject
152: static_assert(!::Petsc::util::detail::is_derived_petsc_object_impl<int>::value, "");
153: static_assert(!::Petsc::util::detail::is_derived_petsc_object_impl<Empty>::value, "");
154: static_assert(!::Petsc::util::detail::is_derived_petsc_object_impl<IntHdr>::value, "");
156: // each of these should be valid in PetscObjectCast()
157: static_assert(::Petsc::util::detail::is_derived_petsc_object_impl<CPetscObject>::value, "");
158: static_assert(::Petsc::util::detail::is_derived_petsc_object_impl<CxxPetscObject>::value, "");
159: static_assert(::Petsc::util::detail::is_derived_petsc_object_impl<CxxDerivedPetscObject>::value, "");
161: } // namespace test
163: } // namespace detail
165: template <typename T>
166: using is_derived_petsc_object = detail::is_derived_petsc_object_impl<remove_pointer_t<decay_t<T>>>;
168: template <class, template <class> class>
169: struct is_instance : public std::false_type { };
171: template <class T, template <class> class U>
172: struct is_instance<U<T>, U> : public std::true_type { };
174: namespace detail
175: {
176: template <template <class> class B, class E>
177: struct is_crtp_base_of_impl : std::is_base_of<B<E>, E> { };
179: template <template <class> class B, class E, template <class> class F>
180: struct is_crtp_base_of_impl<B, F<E>> : disjunction<std::is_base_of<B<E>, F<E>>, std::is_base_of<B<F<E>>, F<E>>> { };
181: } // namespace detail
183: template <template <class> class B, class E>
184: using is_crtp_base_of = detail::is_crtp_base_of_impl<B, decay_t<E>>;
186: } // namespace util
188: } // namespace Petsc
190: template <typename T>
191: PETSC_NODISCARD inline constexpr Petsc::util::remove_const_t<T> &PetscRemoveConstCast(T &object) noexcept
192: {
193: return const_cast<Petsc::util::remove_const_t<T> &>(object);
194: }
196: template <typename T>
197: PETSC_NODISCARD inline constexpr T &PetscRemoveConstCast(const T &object) noexcept
198: {
199: return const_cast<T &>(object);
200: }
202: template <typename T>
203: PETSC_NODISCARD inline constexpr T *&PetscRemoveConstCast(const T *&object) noexcept
204: {
205: return const_cast<T *&>(object);
206: }
208: template <typename T>
209: PETSC_NODISCARD inline constexpr Petsc::util::add_const_t<T> &PetscAddConstCast(T &object) noexcept
210: {
211: return const_cast<Petsc::util::add_const_t<T> &>(std::forward<T>(object));
212: }
214: template <typename T>
215: PETSC_NODISCARD inline constexpr Petsc::util::add_const_t<T> *&PetscAddConstCast(T *&object) noexcept
216: {
217: static_assert(!std::is_const<T>::value, "");
218: return const_cast<Petsc::util::add_const_t<T> *&>(std::forward<T>(object));
219: }
221: // PetscObjectCast() - Cast an object to PetscObject
222: //
223: // input param:
224: // object - the object to cast
225: //
226: // output param:
227: // [return value] - The resulting PetscObject
228: //
229: // notes:
230: // This function checks that the object passed in is in fact a PetscObject, and hence requires
231: // the full definition of the object. This means you must include the appropriate header
232: // containing the _p_
233: //
234: // not available from Fortran
235: template <typename T>
236: PETSC_NODISCARD inline constexpr PetscObject PetscObjectCast(T &&object) noexcept
237: {
238: static_assert(Petsc::util::is_derived_petsc_object<Petsc::util::decay_t<T>>::value, "If this is a PetscObject then the private definition of the struct must be visible for this to work");
239: return (PetscObject)object;
240: }
242: PETSC_NODISCARD inline constexpr PetscObject PetscObjectCast(PetscObject object) noexcept
243: {
244: return object;
245: }
247: template <typename T>
248: PETSC_NODISCARD inline constexpr auto PetscObjectComm(T &&obj) noexcept -> Petsc::util::enable_if_t<!std::is_same<Petsc::util::decay_t<T>, PetscObject>::value, MPI_Comm>
249: {
250: return PetscObjectComm(PetscObjectCast(std::forward<T>(obj)));
251: }