Block-Structured AMR Software Framework
AMReX_TypeTraits.H
Go to the documentation of this file.
1 #ifndef BL_TYPETRAITS_H_
2 #define BL_TYPETRAITS_H_
3 #include <AMReX_Config.H>
4 
5 #include <AMReX_Extension.H>
6 #include <vector>
7 #include <type_traits>
8 
9 // In case they are still used by applications
10 #define AMREX_IS_TRIVIALLY_COPYABLE(T) std::is_trivially_copyable_v<T>
11 #define AMREX_IS_TRIVIALLY_DEFAULT_CONSTRUCTIBLE(T) std::is_trivially_default_constructible_v<T>
12 
13 namespace amrex
14 {
15  template <class T> class BaseFab;
16  template <class FAB> class FabArray;
17 
18  template <class A, class Enable = void> struct IsBaseFab : std::false_type {};
19  //
20  template <class D>
21  struct IsBaseFab<D, std::enable_if_t<
22  std::is_base_of_v<BaseFab<typename D::value_type>,
23  D>>>
24  : std::true_type {};
25  //
26  template <class A>
27  inline constexpr bool IsBaseFab_v = IsBaseFab<A>::value;
28 
29  template <class A, class Enable = void> struct IsFabArray : std::false_type {};
30  //
31  template <class D>
32  struct IsFabArray<D, std::enable_if_t<
33  std::is_base_of_v<FabArray<typename D::FABType::value_type>,
34  D>>>
35  : std::true_type {};
36  //
37  template <class A>
38  inline constexpr bool IsFabArray_v = IsFabArray<A>::value;
39 
40  template <class M, class Enable = void>
41  struct IsMultiFabLike : std::false_type {};
42  //
43  template <class M>
44  struct IsMultiFabLike<M, std::enable_if_t<IsFabArray_v<M> &&
45  IsBaseFab_v<typename M::fab_type> > >
46  : std::true_type {};
47  //
48  template <class M>
49  inline constexpr bool IsMultiFabLike_v = IsMultiFabLike<M>::value;
50 
51 
52  template <bool B, class T = void>
53  using EnableIf_t = std::enable_if_t<B,T>;
54 
55  template <class T, class Enable = void>
56  struct HasAtomicAdd : std::false_type {};
57  template <> struct HasAtomicAdd<int> : std::true_type {};
58  template <> struct HasAtomicAdd<long> : std::true_type {};
59  template <> struct HasAtomicAdd<unsigned int> : std::true_type {};
60  template <> struct HasAtomicAdd<unsigned long long> : std::true_type {};
61  template <> struct HasAtomicAdd<float> : std::true_type {};
62  template <> struct HasAtomicAdd<double> : std::true_type {};
63 
64  class MFIter;
65  template <typename T>
66  struct IsMultiFabIterator : public std::is_base_of<MFIter, T>::type {};
67 
68 #ifdef AMREX_PARTICLES
69  // template <bool is_const, int NStructReal, int NStructInt, int NArrayReal, int NArrayInt,
70  // template<class> class Allocator>
71  // class ParIterBase;
72 
73  // template <int NStructReal, int NStructInt, int NArrayReal, int NArrayInt,
74  // template<class> class Allocator>
75  // class ParIter;
76 
77  // template <int NStructReal, int NStructInt, int NArrayReal, int NArrayInt,
78  // template<class> class Allocator>
79  // class ParConstIter;
80 
82 
83  template <typename T>
84  struct IsParticleIterator : public std::is_base_of<MFIter, T>::type {}; // not exactly right
85 
86  template <typename T>
87  struct IsParticleContainer : public std::is_base_of<ParticleContainerBase, T>::type {};
88 #endif
89 
90 #ifdef AMREX_USE_GPU
91 
92  template <class T, class Enable = void>
93  struct MaybeDeviceRunnable : std::true_type {};
94 
95  template <class T, class Enable = void>
96  struct MaybeHostDeviceRunnable : std::true_type {};
97 
98  template <class T, class Enable = void>
99  struct DefinitelyNotHostRunnable : std::false_type {};
100 
101 #if defined(AMREX_USE_CUDA) && defined(__NVCC__)
102 
103  template <class T>
104  struct MaybeHostDeviceRunnable<T, std::enable_if_t<__nv_is_extended_device_lambda_closure_type(T)> >
105  : std::false_type {};
106 
107  template <class T>
108  struct DefinitelyNotHostRunnable<T, std::enable_if_t<__nv_is_extended_device_lambda_closure_type(T)> >
109  : std::true_type {};
110 
111 #elif defined(AMREX_USE_HIP)
112 
113  // xxxxx HIP todo
114 
115 #endif
116 
117 #endif
118 
119  template <typename T, typename U1, typename... Us>
120  struct Same;
121 
122  template <typename T, typename U>
123  struct Same<T,U>
124  {
125  static constexpr bool value = std::is_same_v<T,U>;
126  };
127 
128  template <typename T, typename U1, typename... Us>
129  struct Same
130  {
131  static constexpr bool value = std::is_same_v<T,U1> && Same<T,Us...>::value;
132  };
133 
135  // [traits.IsDetected]
136  //
137  // We use IsDetected as a SFINAE tool to test for valid expressions.
138  //
139  // is_detected was proposed to C++ but is surpassed by concepts.
140  //
141  // The implementation is taken from
142  //
143  // https://en.cppreference.com/w/cpp/experimental/is_detected
144 
145  namespace detail {
146  template <class...> using Void_t = void;
147 
148  struct Nonesuch {
149  Nonesuch() = delete;
150  ~Nonesuch() = delete;
151  Nonesuch(Nonesuch const&) = delete;
152  Nonesuch(Nonesuch &&) = delete;
153  void operator=(Nonesuch const&) = delete;
154  void operator=(Nonesuch &&) = delete;
155  };
156 
157  template <class Default, class AlwaysVoid, template <class...> class Op,
158  class... Args>
159  struct Detector {
160  using value_t = std::false_type;
161  using type = Default;
162  };
163 
164  template <class Default, template <class...> class Op, class... Args>
165  struct Detector<Default, Void_t<Op<Args...>>, Op, Args...> {
166  using value_t = std::true_type;
167  using type = Op<Args...>;
168  };
169  }
170 
171  template <template <class...> class Op, class... Args>
172  using IsDetected = typename detail::Detector<detail::Nonesuch, void, Op, Args...>::value_t;
173 
174  template <template <class...> class Op, class... Args>
175  using Detected_t = typename detail::Detector<detail::Nonesuch, void, Op, Args...>::type;
176 
177  template <class Default, template <class...> class Op, class... Args>
178  using DetectedOr = typename detail::Detector<Default, void, Op, Args...>::type;
179 
180  template <class Expected, template <typename...> class Op, class... Args>
181  using IsDetectedExact = std::is_same<Expected, Detected_t<Op, Args...>>;
182 
184  // [traits.IsCallable]
185 
186  namespace detail {
187  template <typename T, typename... Args>
188  using call_result_t = decltype(std::declval<T>()(std::declval<Args>()...));
189  }
190 
200  template <typename T, typename... Args>
201  struct IsCallable : IsDetected<detail::call_result_t, T, Args...> {};
202 
206  template <typename R, typename T, typename... Args>
207  struct IsCallableR : IsDetectedExact<R, detail::call_result_t, T, Args...> {};
208 
210  // [traits.Conjunction]
211  // [traits.Disjunction]
212  // [traits.Negation]
213 
214 
216 #if defined(__cpp_lib_logical_traits)
217  template <typename... Args> using Conjunction = std::conjunction<Args...>;
218  template <typename... Args> using Disjunction = std::disjunction<Args...>;
219  template <typename... Args> using Negation = std::negation<Args...>;
220 #elif defined(__cpp_lib_experimental_logical_traits)
221  template <typename... Args> using Conjunction = std::experimental::conjunction<Args...>;
222  template <typename... Args> using Disjunction = std::experimental::disjunction<Args...>;
223  template <typename... Args> using Negation = std::experimental::negation<Args...>;
224 #else
225  template <class...> struct Conjunction : std::true_type {};
226  template <class B1> struct Conjunction<B1> : B1 {};
227  template <class B1, class... Bn>
228  struct Conjunction<B1, Bn...>
229  : std::conditional_t<bool(B1::value), Conjunction<Bn...>, B1> {};
230 
231  template <class...> struct Disjunction : std::false_type {};
232  template <class B1> struct Disjunction<B1> : B1 {};
233  template <class B1, class... Bn>
234  struct Disjunction<B1, Bn...>
235  : std::conditional_t<bool(B1::value), B1, Disjunction<Bn...>> {};
236 
237  template <class B>
238  using Negation = std::integral_constant<bool, !bool(B::value)>;
239 #endif
240 
242  // [traits.IsConvertible]
243 
244  namespace detail {
245  template<typename T>
246  inline constexpr bool is_convertible(T) {return true;}
247 
248  template <typename T, typename U, typename Enable = void>
249  struct IsConvertibleImp : std::false_type {};
250 
251  template <typename T, typename U>
252  struct IsConvertibleImp<T, U, std::enable_if_t<is_convertible<T>(U{})>> : std::true_type {};
253  }
254 
256  template <typename T, typename... Args>
257  struct IsConvertible {
258  static constexpr bool value = (... && detail::IsConvertibleImp<T, Args>::value);
259  };
260 
261  template <typename T, typename... Args>
262  inline constexpr bool IsConvertible_v = IsConvertible<T, Args...>::value;
263 
264  // Move this down, because doxygen can not parse anything below IsStoreAtomic
265  template <class T, class Enable = void>
266  struct IsStoreAtomic : std::false_type {};
267  //
268  template <class T>
269  struct IsStoreAtomic<T, std::enable_if_t <
270  std::is_arithmetic_v<T>
271  && sizeof(T) <= 8 > >
272  : std::true_type {};
273 
274  template <class T, class Enable = void>
275  struct IsStdVector : std::false_type {};
276  //
277  template <class T>
278  struct IsStdVector<T, std::enable_if_t<std::is_base_of_v<std::vector<typename T::value_type,
279  typename T::allocator_type>,
280  T>> >
281  : std::true_type {};
282 
283 }
284 
285 #endif
Definition: AMReX_MFIter.H:57
Definition: AMReX_ParticleContainerBase.H:23
static constexpr GPUBinPolicy Default
Definition: AMReX_DenseBins.H:24
void Void_t
Definition: AMReX_TypeTraits.H:146
constexpr bool is_convertible(T)
Definition: AMReX_TypeTraits.H:246
decltype(std::declval< T >()(std::declval< Args >()...)) call_result_t
Definition: AMReX_TypeTraits.H:188
static constexpr int M
Definition: AMReX_OpenBC.H:13
Definition: AMReX_Amr.cpp:49
constexpr bool IsFabArray_v
Definition: AMReX_TypeTraits.H:38
std::integral_constant< bool, !bool(B::value)> Negation
Definition: AMReX_TypeTraits.H:238
constexpr bool IsMultiFabLike_v
Definition: AMReX_TypeTraits.H:49
typename detail::Detector< detail::Nonesuch, void, Op, Args... >::type Detected_t
Definition: AMReX_TypeTraits.H:175
constexpr bool IsConvertible_v
Definition: AMReX_TypeTraits.H:262
constexpr bool IsBaseFab_v
Definition: AMReX_TypeTraits.H:27
typename detail::Detector< Default, void, Op, Args... >::type DetectedOr
Definition: AMReX_TypeTraits.H:178
const int[]
Definition: AMReX_BLProfiler.cpp:1664
std::enable_if_t< B, T > EnableIf_t
Definition: AMReX_TypeTraits.H:53
typename detail::Detector< detail::Nonesuch, void, Op, Args... >::value_t IsDetected
Definition: AMReX_TypeTraits.H:172
std::is_same< Expected, Detected_t< Op, Args... > > IsDetectedExact
Definition: AMReX_TypeTraits.H:181
Definition: AMReX_FabArrayCommI.H:896
Definition: AMReX_TypeTraits.H:226
Logical traits let us combine multiple type requirements in one enable_if_t clause.
Definition: AMReX_TypeTraits.H:225
Definition: AMReX_TypeTraits.H:99
Definition: AMReX_TypeTraits.H:232
Definition: AMReX_TypeTraits.H:231
Definition: AMReX_TypeTraits.H:56
Definition: AMReX_TypeTraits.H:18
Test if a given type T is callable with arguments of type Args...
Definition: AMReX_TypeTraits.H:207
Test if a given type T is callable with arguments of type Args...
Definition: AMReX_TypeTraits.H:201
Test if all the types Args... are automatically convertible to type T.
Definition: AMReX_TypeTraits.H:257
static constexpr bool value
Definition: AMReX_TypeTraits.H:258
Definition: AMReX_TypeTraits.H:29
Definition: AMReX_TypeTraits.H:66
Definition: AMReX_TypeTraits.H:41
Definition: AMReX_TypeTraits.H:266
Definition: AMReX_TypeTraits.H:93
Definition: AMReX_TypeTraits.H:96
Definition: AMReX_TypeTraits.H:130
static constexpr bool value
Definition: AMReX_TypeTraits.H:131
std::true_type value_t
Definition: AMReX_TypeTraits.H:166
Op< Args... > type
Definition: AMReX_TypeTraits.H:167
Definition: AMReX_TypeTraits.H:159
std::false_type value_t
Definition: AMReX_TypeTraits.H:160
Default type
Definition: AMReX_TypeTraits.H:161
Definition: AMReX_TypeTraits.H:249
Definition: AMReX_TypeTraits.H:148
void operator=(Nonesuch &&)=delete
void operator=(Nonesuch const &)=delete
Nonesuch(Nonesuch const &)=delete
Nonesuch(Nonesuch &&)=delete