2222
2323#include " memilio/config.h"
2424#include " memilio/math/eigen.h"
25- #include " memilio/utils/custom_index_array.h"
26- #include " memilio/utils/metaprogramming.h"
27- #include < cstddef>
28- #include < type_traits>
29- #include < vector>
30- #include < functional>
25+ #include < concepts>
3126
3227namespace mio
3328{
3429
35- namespace details
36- {
37- // helpers for check_constraint
38- template <class T >
39- using check_constraints_expr_t = decltype (std::declval<T>().check_constraints());
40-
41- // helpers for apply_constraints
30+ // / @brief Check that the given type has a check_constraints member function.
4231template <class T >
43- using apply_constraints_expr_t = decltype (std::declval<T>().apply_constraints());
44-
45- } // namespace details
46-
47- /* *
48- * @brief Check whether a check_constraints function exists.
49- * @tparam The type to check for the existence of the member function.
50- */
51- template <class T >
52- using has_check_constraints_member_function = is_expression_valid<details::check_constraints_expr_t , T>;
32+ concept HasCheckConstraints = requires (T t) {
33+ { t.check_constraints () } -> std::same_as<bool >;
34+ };
5335
54- /* *
55- * @brief Check whether a apply_constraints function exists.
56- * @tparam The type to check for the existence of the member function.
57- */
36+ // / @brief Check that the given type has an apply_constraints member function.
5837template <class T >
59- using has_apply_constraints_member_function = is_expression_valid<details::apply_constraints_expr_t , T>;
38+ concept HasApplyConstraints = requires (T t) {
39+ { t.apply_constraints () } -> std::same_as<bool >;
40+ };
6041
6142/* *
6243 * @brief CompartmentalModel is a template for a compartmental model for an
6344 * array of initial populations and a parameter set.
64- * @tparam FP floating point type, e.g., double.
45+ * @tparam FP A floating point type, e.g., double.
6546 *
6647 * The Populations must be a concrete class derived from the Populations template,
6748 * i.e. a multi-dimensional array of compartment populations where each dimension
@@ -148,7 +129,7 @@ struct CompartmentalModel {
148129 */
149130 bool apply_constraints ()
150131 {
151- if constexpr (has_apply_constraints_member_function <ParameterSet>::value ) {
132+ if constexpr (HasApplyConstraints <ParameterSet>) {
152133 // use bitwise instead of logical or, so that both apply_constraint functions are called
153134 return ((int )parameters.apply_constraints () | (int )populations.apply_constraints ());
154135 }
@@ -163,7 +144,7 @@ struct CompartmentalModel {
163144 */
164145 bool check_constraints () const
165146 {
166- if constexpr (has_check_constraints_member_function <ParameterSet>::value ) {
147+ if constexpr (HasCheckConstraints <ParameterSet>) {
167148 return (parameters.check_constraints () || populations.check_constraints ());
168149 }
169150 else {
@@ -176,42 +157,17 @@ struct CompartmentalModel {
176157};
177158
178159/* *
179- * Detect the eval_right_hand_side member function of a compartment model.
180- * If the eval_right_hand_side member function exists in the type M, this template when instatiated
181- * will be equal to the return type of the function.
182- * Otherwise the template is invalid.
183- * @tparam FP, floating point type, e.g., double.
184- * @tparam M a type that has a eval_right_hand_side member function, e.g. a compartment model type.
185- */
186- template <typename FP, class M >
187- using eval_right_hand_side_expr_t = decltype (std::declval<const M&>().eval_right_hand_side(
188- std::declval<Eigen::Ref<const Eigen::VectorX<FP>>>(), std::declval<Eigen::Ref<const Eigen::VectorX<FP>>>(),
189- std::declval<FP>(), std::declval<Eigen::Ref<Eigen::VectorX<FP>>>()));
190-
191- /* *
192- * Detect the get_initial_values member function of a compartment model.
193- * If the detect_initial_values member function exists in the type M, this template when instatiated
194- * will be equal to the return type of the function.
195- * Otherwise the template is invalid.
196- * @tparam FP, floating point type, e.g., double.
197- * @tparam M a type that has a get_initial_values member function, e.g. a compartment model type.
198- */
199- template <typename FP, class M >
200- using get_initial_values_expr_t =
201- decltype (std::declval<Eigen::VectorX<FP>&>() = std::declval<const M&>().get_initial_values());
202-
203- /* *
204- * Template meta function to check if a type is a valid compartment model.
205- * Defines a static constant of name `value`.
206- * The constant `value` will be equal to true if M is a valid compartment model type.
207- * Otherwise, `value` will be equal to false.
208- * @tparam FP, floating point type, e.g., double.
209- * @tparam M a type that may or may not be a compartment model.
160+ * @brief Concept to check if a type is a valid compartment model.
161+ * Note that Model must be the first template argument
162+ * @tparam Model A type that may or may not be a compartment model.
163+ * @tparam FP A floating point type, e.g. double.
210164 */
211- template <typename FP, class M >
212- using is_compartment_model =
213- std::integral_constant<bool , (is_expression_valid<eval_right_hand_side_expr_t , FP, M>::value &&
214- is_expression_valid<get_initial_values_expr_t , FP, M>::value)>;
165+ template <class Model , typename FP>
166+ concept IsCompartmentalModel =
167+ requires (Model m, Eigen::Ref<const Eigen::VectorX<FP>> pop_y, Eigen::Ref<Eigen::VectorX<FP>> dydt, FP t) {
168+ { m.get_initial_values () } -> std::convertible_to<Eigen::VectorX<FP>>;
169+ m.eval_right_hand_side (pop_y, pop_y, t, dydt);
170+ };
215171
216172} // namespace mio
217173
0 commit comments