parameter_set.h Source File

CPP API: parameter_set.h Source File
parameter_set.h
Go to the documentation of this file.
1 /*
2 * Copyright (C) 2020-2026 MEmilio
3 *
4 * Authors: Jan Kleinert, Daniel Abele
5 *
6 * Contact: Martin J. Kuehn <Martin.Kuehn@DLR.de>
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20 #ifndef MIO_UTILS_PARAMETER_SET_H
21 #define MIO_UTILS_PARAMETER_SET_H
22 
23 #include "memilio/io/io.h"
24 
25 #include <tuple>
26 #include <utility>
27 #include <type_traits>
28 
29 namespace mio
30 {
31 
32 namespace details
33 {
34 
35 //helpers for get_default
36 template <class X, class = void, class... Args>
37 struct has_get_default_member_function : std::false_type {
38 };
39 
40 template <class T, class... Args>
41 struct has_get_default_member_function<T, std::void_t<decltype(T::get_default(std::declval<Args>()...))>, Args...>
42  : std::true_type {
43 };
44 
45 } // namespace details
46 
51 template <class T, class... Args>
53 
58 template <class Tag>
60  using Type = typename Tag::Type;
61 
62  //get_default either with get_default member function or fallback on default constructor
63  template <class Dummy = Tag, class... Ts>
64  static std::enable_if_t<has_get_default_member_function<Dummy, Ts...>::value, Type> get_default(Ts&&... args)
65  {
66  return Tag::get_default(std::forward<Ts>(args)...);
67  }
68 
69  template <class Dummy = Tag, class... Ts>
70  static std::enable_if_t<
72  get_default(Ts&&...)
73  {
74  return Type{};
75  }
76 };
77 
78 namespace details
79 {
80 //stores a parameter and tags it so it can be unambiguously found in a tuple
81 template <class TagT>
83 {
84 public:
85  using Tag = TagT;
87  using Type = typename Traits::Type;
88 
89  template <class... Ts, class Dummy1 = void,
90  class = std::enable_if_t<std::is_constructible<Type, Ts...>::value, Dummy1>>
91  TaggedParameter(Ts&&... args)
92  : m_value(std::forward<Ts>(args)...)
93  {
94  }
95 
96  operator Type&()
97  {
98  return get();
99  }
100 
101  operator const Type&() const
102  {
103  return get();
104  }
105 
106  const Type& get() const
107  {
108  return m_value;
109  }
110 
112  {
113  return m_value;
114  }
115 
116  template <class T>
117  bool operator==(const TaggedParameter<T>& other) const
118  {
119  return m_value == other.m_value;
120  }
121 
122  template <class T>
123  bool operator!=(const TaggedParameter<T>& other) const
124  {
125  return m_value != other.m_value;
126  }
127 
128 private:
130 };
131 
132 //defines value = true if predicate defines value=true for all types in parameter pack
133 template <template <class...> class Pred, class... Tail>
134 struct AllOf;
135 
136 template <template <class...> class Pred>
137 struct AllOf<Pred> : public std::true_type {
138 };
139 
140 template <template <class...> class Pred, class Head, class... Tail>
141 struct AllOf<Pred, Head, Tail...> {
142  static const constexpr bool value = Pred<Head>::value && AllOf<Pred, Tail...>::value;
143 };
144 
145 //defines value = true if predicate defines value=true for any type in parameter pack
146 template <template <class...> class Pred, class... Tail>
147 struct AnyOf;
148 
149 template <template <class...> class Pred>
150 struct AnyOf<Pred> : public std::false_type {
151 };
152 
153 template <template <class...> class Pred, class Head, class... Tail>
154 struct AnyOf<Pred, Head, Tail...> {
155  static const constexpr bool value = Pred<Head>::value || AnyOf<Pred, Tail...>::value;
156 };
157 
158 //for X = template<T1, T2> X => BindTail<X, A>::type<B> = X<B, A>
159 template <template <class...> class F, class... Tail>
160 struct BindTail {
161  template <class... Head>
162  struct type : F<Head..., Tail...> {
163  };
164  //according to the standard, this must be a real type, can't be an alias of F.
165  //An alias is immediately replaced and discarded when the compiler sees it, but this could leave the template F with some
166  //parameters bound and some free, which is not allowed. A struct that derives from F is persistent during compilation.
167 };
168 
169 //for template<T1, T2> X => BindHead<X, A>::type<B> = X<A, B>
170 template <template <class...> class F, class... Head>
171 struct BindHead {
172  template <class... Tail>
173  struct type : F<Head..., Tail...> {
174  };
175  //can't be an alias, see BindTail
176 };
177 
178 } // namespace details
179 
186 };
187 
188 template <typename T>
189 using is_no_default_init_tag = std::is_same<NoDefaultInit, T>;
190 
203 template <class... Tags>
205 {
206 public:
215  template <
216  class Dummy = void,
217  class = std::enable_if_t<details::AllOf<std::is_default_constructible, typename Tags::Type...>::value, Dummy>>
219  {
220  }
221 
227  template <class Dummy = void,
228  class = std::enable_if_t<
231  : m_tup(ParameterTagTraits<Tags>::get_default()...)
232  {
233  }
234 
243  template <
244  class T1, class... TN,
245  class = std::enable_if_t<
246  // Avoid erroneous template deduction for T1=ParameterSet as this constructor could falsely be considered
247  // as a copy constructor for non-const lvalue references.
248  !std::is_same_v<std::decay_t<T1>, ParameterSet> &&
251  explicit ParameterSet(T1&& arg1, TN&&... argn)
252  : m_tup(ParameterTagTraits<Tags>::get_default(arg1, argn...)...)
253  {
254  }
255 
261  template <class Tag>
262  const typename ParameterTagTraits<Tag>::Type& get() const
263  {
264  return std::get<details::TaggedParameter<Tag>>(m_tup).get();
265  }
266 
272  template <class Tag>
274  {
275  return std::get<details::TaggedParameter<Tag>>(m_tup).get();
276  }
277 
282  template <class Tag>
284  {
285  get<Tag>() = value;
286  }
287 
292  template <class Tag, class T>
293  void set(T&& arg)
294  {
295  get<Tag>() = std::forward<T>(arg);
296  }
297 
305  template <class Tag, class... T>
306  std::enable_if_t<has_get_default_member_function<ParameterTagTraits<Tag>, T...>::value, void> set_default(T&&... ts)
307  {
308  get<Tag>() = ParameterTagTraits<Tag>::get_default(std::forward<T>(ts)...);
309  }
310 
315  static constexpr size_t size()
316  {
317  return sizeof...(Tags);
318  }
319 
320  bool operator==(const ParameterSet& b) const
321  {
322  return m_tup == b.m_tup;
323  }
324 
325  bool operator!=(const ParameterSet& b) const
326  {
327  return m_tup != b.m_tup;
328  }
329 
334  template <class IOContext>
335  void serialize(IOContext& io) const
336  {
337  auto obj = io.create_object("ParameterSet");
338  foreach (*this, [&obj](auto& p, auto t) mutable {
339  using Tag = decltype(t);
340  obj.add_element(Tag::name(), p);
341  })
342  ;
343  }
344 
345 private:
352  template <class Dummy = void, class = std::enable_if_t<(sizeof...(Tags) > 0), Dummy>, class = Dummy>
353  ParameterSet(const typename Tags::Type&... t)
354  : m_tup(t...)
355  {
356  }
357 
358  //entry to recursively deserialize all parameters in the ParameterSet
359  //IOContext: serializer
360  //IOObject: object that stores the serialized ParameterSet
361  //Rs: IOResult<T> for each Parameter Tag that has already been deserialized
362  template <class IOContext, class IOObject, class... Rs,
363  std::enable_if_t<(sizeof...(Rs) < sizeof...(Tags)), void*> = nullptr>
364  static IOResult<ParameterSet> deserialize_recursive(IOContext& io, IOObject& obj, Rs&&... rs)
365  {
366  //read current parameter, append result to results of previous parameters, recurse to next parameter
367  using TaggedParameter = std::tuple_element_t<sizeof...(Rs), decltype(ParameterSet::m_tup)>;
368  auto r = obj.expect_element(TaggedParameter::Tag::name(), mio::Tag<typename TaggedParameter::Type>{});
369  return deserialize_recursive(io, obj, std::forward<Rs>(rs)..., std::move(r));
370  }
371 
372  //end of recursion to deserialize parameters in the ParameterSet
373  template <class IOContext, class IOObject, class... Rs,
374  std::enable_if_t<(sizeof...(Rs) == sizeof...(Tags)), void*> = nullptr>
375  static IOResult<ParameterSet> deserialize_recursive(IOContext& io, IOObject& /*obj*/, Rs&&... rs)
376  {
377  //one result for each parameters, so no more parameters to read
378  //expand results, build finished ParameterSet, stop recursion
379  return mio::apply(
380  io,
381  [](const typename Tags::Type&... t) {
382  return ParameterSet(t...);
383  },
384  std::forward<Rs>(rs)...);
385  }
386 
387 public:
392  template <class IOContext>
393  static IOResult<ParameterSet> deserialize(IOContext& io)
394  {
395  auto obj = io.expect_object("ParameterSet");
396  return deserialize_recursive(io, obj);
397  }
398 
399 private:
400  std::tuple<details::TaggedParameter<Tags>...> m_tup;
401 };
402 
403 namespace details
404 {
405 //helpers for ParameterTag
406 template <size_t I, class ParamSet>
408 
409 template <size_t I, class Head, class... Tail>
410 struct ParameterTag<I, ParameterSet<Head, Tail...>> : public ParameterTag<I - 1, ParameterSet<Tail...>> {
411 };
412 
413 template <class Head, class... Tail>
414 struct ParameterTag<0, ParameterSet<Head, Tail...>> {
415  using Type = Head;
416 };
417 } // namespace details
418 
422 template <size_t I, class ParamSet>
424 
425 template <size_t I, class ParamSet>
427 
428 namespace details
429 {
430 //helpers for foreach
431 template <class... Tail, class Params, class F>
432 std::enable_if_t<sizeof...(Tail) == 0, void> foreach_impl(Params&&, F)
433 {
434 }
435 
436 template <class Head, class... Tail, class Params, class F>
437 void foreach_impl(Params&& p, F f)
438 {
439  f(p.template get<Head>(), Head{});
440  foreach_impl<Tail...>(p, f);
441 }
442 
443 template <class Params, size_t... Tail, class F>
444 std::enable_if_t<sizeof...(Tail) == 0, void> foreach_tag_impl(F, std::index_sequence<Tail...>)
445 {
446 }
447 
448 template <class Params, size_t Head, size_t... Tail, class F>
449 void foreach_tag_impl(F f, std::index_sequence<Head, Tail...>)
450 {
452  foreach_tag_impl<Params, Tail...>(f, std::index_sequence<Tail...>{});
453 }
454 } // namespace details
455 
464 template <class Params, class F>
465 void foreach_tag(F f)
466 {
467  details::foreach_tag_impl<Params>(f, std::make_index_sequence<Params::size()>{});
468 }
469 
480 template <class F, class... Tags>
481 void foreach (const ParameterSet<Tags...>& p, F f)
482 {
483  details::foreach_impl<Tags...>(p, f);
484 }
485 
486 template <class F, class... Tags>
487 void foreach (ParameterSet<Tags...>& p, F f)
488 {
489  details::foreach_impl<Tags...>(p, f);
490 }
491 
492 } // namespace mio
493 
494 #endif // MIO_UTILS_PARAMETER_SET_H
a set of parameters defined at compile time
Definition: parameter_set.h:205
void set(const typename ParameterTagTraits< Tag >::Type &value)
set value of a parameter
Definition: parameter_set.h:283
static IOResult< ParameterSet > deserialize_recursive(IOContext &io, IOObject &, Rs &&... rs)
Definition: parameter_set.h:375
std::tuple< details::TaggedParameter< Tags >... > m_tup
Definition: parameter_set.h:400
std::enable_if_t< has_get_default_member_function< ParameterTagTraits< Tag >, T... >::value, void > set_default(T &&... ts)
(re)set parameter to its default value
Definition: parameter_set.h:306
static constexpr size_t size()
returns the number of parameters
Definition: parameter_set.h:315
ParameterSet(T1 &&arg1, TN &&... argn)
default initializing constructor.
Definition: parameter_set.h:251
bool operator!=(const ParameterSet &b) const
Definition: parameter_set.h:325
static IOResult< ParameterSet > deserialize(IOContext &io)
deserialize an object of this class.
Definition: parameter_set.h:393
ParameterSet()
default initializing constructor Initializes each parameter using either the get_default function def...
Definition: parameter_set.h:230
static IOResult< ParameterSet > deserialize_recursive(IOContext &io, IOObject &obj, Rs &&... rs)
Definition: parameter_set.h:364
bool operator==(const ParameterSet &b) const
Definition: parameter_set.h:320
void serialize(IOContext &io) const
serialize this.
Definition: parameter_set.h:335
ParameterSet(NoDefaultInit)
Non-initializing default constructor.
Definition: parameter_set.h:218
ParameterTagTraits< Tag >::Type & get()
get value of a parameter
Definition: parameter_set.h:273
void set(T &&arg)
set value of a parameter
Definition: parameter_set.h:293
const ParameterTagTraits< Tag >::Type & get() const
get value of a parameter
Definition: parameter_set.h:262
ParameterSet(const typename Tags::Type &... t)
Internal constructor taking a value for each parameter, and initializing it.
Definition: parameter_set.h:353
Definition: parameter_set.h:83
const Type & get() const
Definition: parameter_set.h:106
TagT Tag
Definition: parameter_set.h:85
bool operator==(const TaggedParameter< T > &other) const
Definition: parameter_set.h:117
TaggedParameter(Ts &&... args)
Definition: parameter_set.h:91
typename Traits::Type Type
Definition: parameter_set.h:87
Type & get()
Definition: parameter_set.h:111
Type m_value
Definition: parameter_set.h:129
bool operator!=(const TaggedParameter< T > &other) const
Definition: parameter_set.h:123
trait_value< T >::RETURN_TYPE & value(T &x)
Definition: ad.hpp:3308
std::enable_if_t< sizeof...(Tail)==0, void > foreach_impl(Params &&, F)
Definition: parameter_set.h:432
std::enable_if_t< sizeof...(Tail)==0, void > foreach_tag_impl(F, std::index_sequence< Tail... >)
Definition: parameter_set.h:444
int size(Comm comm)
Return the size of the given communicator.
Definition: miompi.cpp:75
A collection of classes to simplify handling of matrix shapes in meta programming.
Definition: models/abm/analyze_result.h:30
details::ParameterTag< I, ParamSet > ParameterTag
get the the tag of the I-th parameter in a set
Definition: parameter_set.h:423
boost::outcome_v2::in_place_type_t< T > Tag
Type that is used for overload resolution.
Definition: io.h:407
void foreach_tag(F f)
call f(t) for all parameters in a ParameterSet with t a default constructed parameter tag
Definition: parameter_set.h:465
details::ApplyResultT< F, T... > apply(IOContext &io, F f, const IOResult< T > &... rs)
Evaluate a function with zero or more unpacked IOResults as arguments.
Definition: io.h:481
typename ParameterTag< I, ParamSet >::Type ParameterTagT
Definition: parameter_set.h:426
std::is_same< NoDefaultInit, T > is_no_default_init_tag
Definition: parameter_set.h:189
details::has_get_default_member_function< T, void, Args... > has_get_default_member_function
check whether a get_default function exists
Definition: parameter_set.h:52
boost::outcome_v2::unchecked< T, IOStatus > IOResult
Value-or-error type for operations that return a value but can fail.
Definition: io.h:353
Definition: io.h:94
A tag used for tag-dispatching the Constructor of ParameterSet, triggering default initialization of ...
Definition: parameter_set.h:185
the properties of a parameter
Definition: parameter_set.h:59
static std::enable_if_t< !has_get_default_member_function< Dummy, Ts... >::value &&std::is_default_constructible< Type >::value, Type > get_default(Ts &&...)
Definition: parameter_set.h:72
static std::enable_if_t< has_get_default_member_function< Dummy, Ts... >::value, Type > get_default(Ts &&... args)
Definition: parameter_set.h:64
typename Tag::Type Type
Definition: parameter_set.h:60
Definition: parameter_set.h:134
Definition: parameter_set.h:147
Definition: parameter_set.h:173
Definition: parameter_set.h:171
Definition: parameter_set.h:162
Definition: parameter_set.h:160
Definition: parameter_set.h:407
Definition: parameter_set.h:37