1 #ifndef STAN_MATH_PRIM_META_REQUIRE_HELPERS_HPP
2 #define STAN_MATH_PRIM_META_REQUIRE_HELPERS_HPP
3 
4 #include <stan/math/prim/meta/conjunction.hpp>
5 #include <stan/math/prim/meta/disjunction.hpp>
6 #include <stan/math/prim/meta/bool_constant.hpp>
7 #include <stan/math/prim/meta/scalar_type.hpp>
8 #include <stan/math/prim/meta/value_type.hpp>
9 
10 #include <type_traits>
11 
12 namespace stan {
13 
14 /**
15  * If condition is true, template is enabled
16  * @ingroup type_traits
17  */
18 template <class Check>
19 using require_t = std::enable_if_t<Check::value>;
20 
21 /**
22  * If condition is false, template is disabled
23  * @ingroup type_traits
24  */
25 template <typename Check>
26 using require_not_t = std::enable_if_t<!Check::value>;
27 
28 /**
29  * If all conditions are true, template is enabled
30  * Returns a type void if all conditions are true and otherwise fails.
31  * @ingroup type_traits
32  */
33 template <class... Checks>
34 using require_all_t = std::enable_if_t<math::conjunction<Checks...>::value>;
35 
36 /**
37  * If any condition is true, template is enabled.
38  *
39  * Returns a type void if any of the conditions are true and otherwise fails.
40  * @ingroup type_traits
41  */
42 template <class... Checks>
43 using require_any_t = std::enable_if_t<math::disjunction<Checks...>::value>;
44 
45 /**
46  * If all conditions are false, template is enabled.
47  *
48  * Returns a type void if all of the conditions are false.
49  * @ingroup type_traits
50  */
51 template <class... Checks>
52 using require_all_not_t
53     = std::enable_if_t<!math::disjunction<Checks...>::value>;
54 
55 /**
56  * If any condition is false, template is enabled.
57  *
58  * Returns a type void if any of the conditions are false.
59  * @ingroup type_traits
60  */
61 template <class... Checks>
62 using require_any_not_t
63     = std::enable_if_t<!math::conjunction<Checks...>::value>;
64 
65 /** \ingroup macro_helpers
66  * Adds Unary require aliases.
67  * @param check_type The name of the type to check, used to define
68  * `require_<check_type>_t`.
69  * @param checker A struct that returns holds a boolean `value`
70  * @param doxygen_group The doxygen group to add this requires to.
71  */
72 #define STAN_ADD_REQUIRE_UNARY(check_type, checker, doxygen_group)       \
73   /*! \ingroup doxygen_group */                                          \
74   /*! \defgroup check_type##_types check_type  */                        \
75   /*! \addtogroup check_type##_types */                                  \
76   /*! @{ */                                                              \
77   /*! \brief Require type satisfies checker */                           \
78   template <typename T>                                                  \
79   using require_##check_type##_t = require_t<checker<std::decay_t<T>>>;  \
80                                                                          \
81   /*! \brief Require type does not satisfy checker */                    \
82   template <typename T>                                                  \
83   using require_not_##check_type##_t                                     \
84       = require_not_t<checker<std::decay_t<T>>>;                         \
85                                                                          \
86   /*! \brief Require all of the types satisfy checker */                 \
87   template <typename... Types>                                           \
88   using require_all_##check_type##_t                                     \
89       = require_all_t<checker<std::decay_t<Types>>...>;                  \
90                                                                          \
91   /*! \brief Require any of the types satisfy checker */                 \
92   template <typename... Types>                                           \
93   using require_any_##check_type##_t                                     \
94       = require_any_t<checker<std::decay_t<Types>>...>;                  \
95                                                                          \
96   /*! \brief Require none of the types satisfy checker */                \
97   template <typename... Types>                                           \
98   using require_all_not_##check_type##_t                                 \
99       = require_all_not_t<checker<std::decay_t<Types>>...>;              \
100                                                                          \
101   /*! \brief Require at least one of the types do not satisfy checker */ \
102   template <typename... Types>                                           \
103   using require_any_not_##check_type##_t                                 \
104       = require_any_not_t<checker<std::decay_t<Types>>...>;              \
105 /*! @} */
106 
107 /** \ingroup macro_helpers
108  * Adds unary require aliases that check the `value_type`.
109  * @param check_type The name of the type to check, used to define
110  * `require_<check_type>_t`.
111  * @param checker A struct that returns holds a boolean `value`
112  * @param doxygen_group The doxygen group to add this requires to.
113  */
114 #define STAN_ADD_REQUIRE_UNARY_INNER(check_type, checker, doxygen_group)       \
115   /*! \ingroup doxygen_group */                                                \
116   /*! \addtogroup check_type##_types */                                        \
117   /*! @{ */                                                                    \
118   /*! \brief Require value type satisfies checker */                           \
119   template <typename T>                                                        \
120   using require_vt_##check_type                                                \
121       = require_t<checker<value_type_t<std::decay_t<T>>>>;                     \
122                                                                                \
123   /*! \brief Require value type does not satisfy checker */                    \
124   template <typename T>                                                        \
125   using require_not_vt_##check_type                                            \
126       = require_not_t<checker<value_type_t<std::decay_t<T>>>>;                 \
127                                                                                \
128   /*! \brief Require all of the value types satisfy checker */                 \
129   template <typename... Types>                                                 \
130   using require_all_vt_##check_type                                            \
131       = require_all_t<checker<value_type_t<std::decay_t<Types>>>...>;          \
132                                                                                \
133   /*! \brief Require any of the value types satisfy checker */                 \
134   template <typename... Types>                                                 \
135   using require_any_vt_##check_type                                            \
136       = require_any_t<checker<value_type_t<std::decay_t<Types>>>...>;          \
137                                                                                \
138   /*! \brief Require none of the value types satisfy checker */                \
139   template <typename... Types>                                                 \
140   using require_all_not_vt_##check_type                                        \
141       = require_all_not_t<checker<value_type_t<std::decay_t<Types>>>...>;      \
142                                                                                \
143   /*! \brief Require at least one of the value types do not satisfy checker */ \
144   template <typename... Types>                                                 \
145   using require_any_not_vt_##check_type                                        \
146       = require_any_not_t<checker<value_type_t<std::decay_t<Types>>>...>;      \
147                                                                                \
148   /*! \brief Require scalar type satisfies checker */                          \
149   template <typename T>                                                        \
150   using require_st_##check_type                                                \
151       = require_t<checker<scalar_type_t<std::decay_t<T>>>>;                    \
152                                                                                \
153   /*! \brief Require scalar type does not satisfy checker */                   \
154   template <typename T>                                                        \
155   using require_not_st_##check_type                                            \
156       = require_not_t<checker<scalar_type_t<std::decay_t<T>>>>;                \
157                                                                                \
158   /*! \brief Require all of the scalar types satisfy checker */                \
159   template <typename... Types>                                                 \
160   using require_all_st_##check_type                                            \
161       = require_all_t<checker<scalar_type_t<std::decay_t<Types>>>...>;         \
162                                                                                \
163   /*! \brief Require any of the scalar types satisfy checker */                \
164   template <typename... Types>                                                 \
165   using require_any_st_##check_type                                            \
166       = require_any_t<checker<scalar_type_t<std::decay_t<Types>>>...>;         \
167                                                                                \
168   /*! \brief Require none of the scalar types satisfy checker */               \
169   template <typename... Types>                                                 \
170   using require_all_not_st_##check_type                                        \
171       = require_all_not_t<checker<scalar_type_t<std::decay_t<Types>>>...>;     \
172                                                                                \
173   /*! \brief Any of the scalar types do not satisfy checker */                 \
174   template <typename... Types>                                                 \
175   using require_any_not_st_##check_type                                        \
176       = require_any_not_t<checker<scalar_type_t<std::decay_t<Types>>>...>;     \
177 /*! @} */
178 
179 /** \ingroup macro_helpers
180  * Adds binary require aliases.
181  * @param check_type The name of the type to check, used to define
182  * `require_<check_type>_t`.
183  * @param checker A struct that returns holds a boolean `value`
184  * @param doxygen_group The doxygen group to add this requires to.
185  */
186 #define STAN_ADD_REQUIRE_BINARY(check_type, checker, doxygen_group)          \
187   /*! \ingroup doxygen_group */                                              \
188   /*! \defgroup check_type##_types check_type  */                            \
189   /*! \addtogroup check_type##_types */                                      \
190   /*! @{ */                                                                  \
191   /*! \brief Require types `T` and `S` satisfies checker */                  \
192   template <typename T, typename S>                                          \
193   using require_##check_type##_t                                             \
194       = require_t<checker<std::decay_t<T>, std::decay_t<S>>>;                \
195                                                                              \
196   /*! \brief Require types `T` and `S` does not satisfy checker */           \
197   template <typename T, typename S>                                          \
198   using require_not_##check_type##_t                                         \
199       = require_not_t<checker<std::decay_t<T>, std::decay_t<S>>>;            \
200                                                                              \
201   /*! \brief Require `T` and all of the `Types` satisfy checker */           \
202   template <typename T, typename... Types>                                   \
203   using require_all_##check_type##_t                                         \
204       = require_all_t<checker<std::decay_t<T>, std::decay_t<Types>>...>;     \
205                                                                              \
206   /*! \brief Require any of the `Types` and `T` satisfy checker */           \
207   template <typename T, typename... Types>                                   \
208   using require_any_##check_type##_t                                         \
209       = require_any_t<checker<std::decay_t<T>, std::decay_t<Types>>...>;     \
210                                                                              \
211   /*! \brief Require none of the `Types` and `T` satisfy checker */          \
212   template <typename T, typename... Types>                                   \
213   using require_all_not_##check_type##_t                                     \
214       = require_all_not_t<checker<std::decay_t<T>, std::decay_t<Types>>...>; \
215                                                                              \
216   /*! \brief Any one of the `Types` and `T` do not satisfy */                \
217   template <typename T, typename... Types>                                   \
218   using require_any_not_##check_type##_t                                     \
219       = require_any_not_t<checker<std::decay_t<T>, std::decay_t<Types>>...>; \
220 /*! @} */
221 
222 /** \ingroup macro_helpers
223  * Adds binary require aliases that check the `scalar_type`.
224  * @param check_type The name of the type to check, used to define
225  * `require_<check_type>_t`.
226  * @param checker A struct that returns holds a boolean `value`
227  * @param doxygen_group The doxygen group to add this requires to.
228  */
229 #define STAN_ADD_REQUIRE_BINARY_INNER(check_type, checker, doxygen_group)      \
230   /*! \ingroup doxygen_group */                                                \
231   /*! \addtogroup check_type##_types */                                        \
232   /*! @{ */                                                                    \
233   /*! \brief Require that value types of `T` and `S` satisfies checker */      \
234   template <typename T, typename S>                                            \
235   using require_st_##check_type                                                \
236       = require_t<checker<scalar_type_t<std::decay_t<T>>,                      \
237                           scalar_type_t<std::decay_t<S>>>>;                    \
238                                                                                \
239   /*! \brief Require scalar types of `T` and `S` does not satisfy checker */   \
240   template <typename T, typename S>                                            \
241   using require_not_st_##check_type                                            \
242       = require_not_t<checker<scalar_type_t<std::decay_t<T>>,                  \
243                               scalar_type_t<std::decay_t<S>>>>;                \
244                                                                                \
245   /*! \brief All scalar types of `T` and all of the `Types` satisfy checker */ \
246   template <typename T, typename... Types>                                     \
247   using require_all_st_##check_type                                            \
248       = require_all_t<checker<scalar_type_t<std::decay_t<T>>,                  \
249                               scalar_type_t<std::decay_t<Types>>>...>;         \
250                                                                                \
251   /*! \brief Any of the scalar types of `Types` and `T` satisfy checker */     \
252   template <typename T, typename... Types>                                     \
253   using require_any_st_##check_type                                            \
254       = require_any_t<checker<scalar_type_t<std::decay_t<T>>,                  \
255                               scalar_type_t<std::decay_t<Types>>>...>;         \
256                                                                                \
257   /*! \brief None of the scalar types of `Types` and `T` satisfy checker */    \
258   template <typename T, typename... Types>                                     \
259   using require_all_not_st_##check_type                                        \
260       = require_all_not_t<checker<scalar_type_t<std::decay_t<T>>,              \
261                                   scalar_type_t<std::decay_t<Types>>>...>;     \
262                                                                                \
263   /*! \brief Any of the scalar types `Types` and `T` do not satisfy checker */ \
264   template <typename T, typename... Types>                                     \
265   using require_any_not_st_##check_type                                        \
266       = require_any_not_t<checker<scalar_type_t<std::decay_t<T>>,              \
267                                   scalar_type_t<std::decay_t<Types>>>...>;     \
268                                                                                \
269   /*! \brief Value types of `T` and `S` satisfies checker */                   \
270   template <typename T, typename S>                                            \
271   using require_vt_##check_type = require_t<                                   \
272       checker<value_type_t<std::decay_t<T>>, value_type_t<std::decay_t<S>>>>;  \
273                                                                                \
274   /*! \brief Value types of `T` and `S` does not satisfy checker */            \
275   template <typename T, typename S>                                            \
276   using require_not_vt_##check_type = require_not_t<                           \
277       checker<value_type_t<std::decay_t<T>>, value_type_t<std::decay_t<S>>>>;  \
278                                                                                \
279   /*! \brief Value types of `T` and all of the `Types` satisfy checker */      \
280   template <typename T, typename... Types>                                     \
281   using require_all_vt_##check_type                                            \
282       = require_all_t<checker<value_type_t<std::decay_t<T>>,                   \
283                               value_type_t<std::decay_t<Types>>>...>;          \
284                                                                                \
285   /*! \brief Any of the value types of `Types` and `T` satisfy checker */      \
286   template <typename T, typename... Types>                                     \
287   using require_any_vt_##check_type                                            \
288       = require_any_t<checker<value_type_t<std::decay_t<T>>,                   \
289                               value_type_t<std::decay_t<Types>>>...>;          \
290                                                                                \
291   /*! \brief None of the value types of `Types` and `T` satisfy checker */     \
292   template <typename T, typename... Types>                                     \
293   using require_all_not_vt_##check_type                                        \
294       = require_all_not_t<checker<value_type_t<std::decay_t<T>>,               \
295                                   value_type_t<std::decay_t<Types>>>...>;      \
296                                                                                \
297   /*! \brief Any of the value types `Types` and `T` do not satisfy checker */  \
298   template <typename T, typename... Types>                                     \
299   using require_any_not_vt_##check_type                                        \
300       = require_any_not_t<checker<value_type_t<std::decay_t<T>>,               \
301                                   value_type_t<std::decay_t<Types>>>...>;      \
302 /*! @} */
303 
304 /**
305  * Used as the base for checking whether a type is a container with
306  * an underlying scalar type
307  *
308  * @tparam ContainerCheck Templated struct or alias that wraps a static constant
309  * scalar called type. Used to check the container satisfies a particular type
310  * check.
311  * @tparam ValueCheck Templated struct or alias that returns a containers
312  * inner type.
313  * @tparam CheckType Templated struct or alias that wraps a static constant
314  * scalar called type. Used to check the container's underlying type satisfies a
315  * particular type check.
316  *
317  */
318 template <template <class...> class ContainerCheck,
319           template <class...> class ValueCheck,
320           template <class...> class TypeCheck, class... Check>
321 using container_type_check_base
322     = bool_constant<math::conjunction<ContainerCheck<std::decay_t<Check>>...,
323                                       TypeCheck<ValueCheck<Check>>...>::value>;
324 
325 /** \ingroup macro_helpers
326  * Adds container require aliases that check the containers inner type.
327  * @param check_type The name of the type to check, used to define
328  * `require_<check_type>_t`.
329  * @param checker A struct that returns holds a boolean `value`
330  * @param doxygen_group The doxygen group to add this requires to.
331  */
332 #define STAN_ADD_REQUIRE_CONTAINER(check_type, checker, doxygen_group)         \
333   /*! \ingroup doxygen_group */                                                \
334   /*! \defgroup check_type##_types check_type  */                              \
335   /*! \addtogroup check_type##_types */                                        \
336   /*! @{ */                                                                    \
337   /*! \brief Require type satisfies checker */                                 \
338   /*! and value type satisfies `TypeCheck` */                                  \
339   /*! @tparam TypeCheck The type trait to check the value type against*/       \
340   template <template <class...> class TypeCheck, class... Check>               \
341   using require_##check_type##_vt = require_t<                                 \
342       container_type_check_base<checker, value_type_t, TypeCheck, Check...>>;  \
343                                                                                \
344   /*! \brief Require type does not satisfy checker or */                       \
345   /*! value type does not satisfy `TypeCheck` */                               \
346   /*! @tparam TypeCheck The type trait to check the value type against*/       \
347   template <template <class...> class TypeCheck, class... Check>               \
348   using require_not_##check_type##_vt = require_not_t<                         \
349       container_type_check_base<checker, value_type_t, TypeCheck, Check...>>;  \
350                                                                                \
351   /*! \brief Require any of the types satisfy checker */                       \
352   /*! and any of the value types satisfy `TypeCheck` */                        \
353   /*! @tparam TypeCheck The type trait to check the value type against*/       \
354   template <template <class...> class TypeCheck, class... Check>               \
355   using require_any_##check_type##_vt = require_any_t<                         \
356       container_type_check_base<checker, value_type_t, TypeCheck, Check>...>;  \
357                                                                                \
358   /*! \brief Require at least one of the types does not satisfy checker */     \
359   /*! and none of the value types satisfy `TypeCheck` */                       \
360   /*! @tparam TypeCheck The type trait to check the value type against*/       \
361   template <template <class...> class TypeCheck, class... Check>               \
362   using require_any_not_##check_type##_vt = require_any_not_t<                 \
363       container_type_check_base<checker, value_type_t, TypeCheck, Check>...>;  \
364                                                                                \
365   /*! \brief Require all of the types satisfy checker */                       \
366   /*! and all of the value types satisfy `TypeCheck` */                        \
367   /*! @tparam TypeCheck The type trait to check the value type against*/       \
368   template <template <class...> class TypeCheck, class... Check>               \
369   using require_all_##check_type##_vt = require_all_t<                         \
370       container_type_check_base<checker, value_type_t, TypeCheck, Check>...>;  \
371                                                                                \
372   /*! \brief Require none of the types satisfy checker */                      \
373   /*! and none of the value types satisfy `TypeCheck` */                       \
374   /*! @tparam TypeCheck The type trait to check the value type against*/       \
375   template <template <class...> class TypeCheck, class... Check>               \
376   using require_all_not_##check_type##_vt = require_all_not_t<                 \
377       container_type_check_base<checker, value_type_t, TypeCheck, Check>...>;  \
378                                                                                \
379   /*! \brief Require type satisfies checker */                                 \
380   /*! and scalar type satisfies `TypeCheck` */                                 \
381   /*! @tparam TypeCheck The type trait to check the scalar type against*/      \
382   template <template <class...> class TypeCheck, class... Check>               \
383   using require_##check_type##_st = require_t<                                 \
384       container_type_check_base<checker, scalar_type_t, TypeCheck, Check...>>; \
385                                                                                \
386   /*! \brief Require type does not satisfy checker */                          \
387   /*! or scalar type does not satisfy `TypeCheck` */                           \
388   /*! @tparam TypeCheck The type trait to check the scalar type against*/      \
389   template <template <class...> class TypeCheck, class... Check>               \
390   using require_not_##check_type##_st = require_not_t<                         \
391       container_type_check_base<checker, scalar_type_t, TypeCheck, Check...>>; \
392                                                                                \
393   /*! \brief Require any of the types satisfy checker */                       \
394   /*! and any scalar type satisfies `TypeCheck` */                             \
395   /*! @tparam TypeCheck The type trait to check the scalar type against*/      \
396   template <template <class...> class TypeCheck, class... Check>               \
397   using require_any_##check_type##_st = require_any_t<                         \
398       container_type_check_base<checker, scalar_type_t, TypeCheck, Check>...>; \
399                                                                                \
400   /*! \brief Require at least one of the types does not satisfy checker */     \
401   /*! and any scalar type does not satisfy `TypeCheck` */                      \
402   /*! @tparam TypeCheck The type trait to check the scalar type against*/      \
403   template <template <class...> class TypeCheck, class... Check>               \
404   using require_any_not_##check_type##_st = require_any_not_t<                 \
405       container_type_check_base<checker, scalar_type_t, TypeCheck, Check>...>; \
406                                                                                \
407   /*! \brief Require all of the types does not satisfy checker */              \
408   /*! and all scalar types satisfy `TypeCheck` */                              \
409   /*! @tparam TypeCheck The type trait to check the scalar type against*/      \
410   template <template <class...> class TypeCheck, class... Check>               \
411   using require_all_##check_type##_st = require_all_t<                         \
412       container_type_check_base<checker, scalar_type_t, TypeCheck, Check>...>; \
413                                                                                \
414   /*! \brief Require none of the types satisfy checker */                      \
415   /*! and none of the scalar types satisfy `TypeCheck` */                      \
416   /*! @tparam TypeCheck The type trait to check the scalar type against*/      \
417   template <template <class...> class TypeCheck, class... Check>               \
418   using require_all_not_##check_type##_st = require_all_not_t<                 \
419       container_type_check_base<checker, scalar_type_t, TypeCheck, Check>...>; \
420   /*! @} */
421 
422 }  // namespace stan
423 
424 #endif
425