LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
ParameterWalker.h
Go to the documentation of this file.
1 #ifndef fhiclcpp_types_detail_ParameterWalker_h
2 #define fhiclcpp_types_detail_ParameterWalker_h
3 
4 /*
5  ======================================================================
6 
7  ParameterWalker
8 
9  ======================================================================
10 
11  The ParameterWalker class makes it possible to traverse the nested
12  configuration for a given parameter. This class is very similar in
13  functionality to the 'ParameterSet::walk_' function.
14 
15  The tree-walking functionality is provided via derivation:
16 
17  class MyWalker : ParameterWalker<tt::const_flavor::require(_non)_const>
18  {
19  // members, functions, etc.
20  };
21 
22  where a provided template argument of
23  'tt::const_flavor::require_const ' makes all virtual functions
24  accept "T const*" arguments, whereas require_non_const makes all
25  virtual functions accept "T*" arguments.
26 
27  Heuristically, it looks like:
28 
29  for (auto p : parameters) {
30  if (!psw.before_action(p))
31  return;
32 
33  if (is_table(param)) {
34  cast_from(p,t)
35  *** psw.enter_table(t)
36  descend_into_table ...
37  psw.exit_table(t)
38  }
39  else if (is_sequence(param)) {
40  cast_from(p,s)
41  *** psw.enter_sequence(s)
42  loop_through_sequence ...
43  psw.exit_sequence(s)
44  }
45  else if (is_atom(param)) {
46  cast_from(p,a)
47  *** psw.atom(a)
48  }
49  else {
50  cast_from(p,dp)
51  *** psw.delegated_parameter(dp)
52  }
53 
54  psw.after_action(p)
55  }
56 
57  The actions that are to be taken per parameter category (table,
58  sequence, or atom) are defined entirely by overrides to the
59  ParameterWalker virtual functions that 'psw' calls (as shown above).
60 
61  The function calls prefaced with '***' correspond to pure virtual
62  functions, which must have corresponding overrides in any derived
63  classes.
64 
65  The 'exit_{table,sequence}' functions are provided if (e.g.) the
66  derived-class state needs to be restored after the table or sequence
67  traversal. The '{before,after}_action' virtual functions are
68  provided so that category-agnostic instructions can be executed
69  before or after the category-specific ones.
70 */
71 
72 #include "cetlib/container_algorithms.h"
73 #include "cetlib_except/demangle.h"
74 #include "fhiclcpp/type_traits.h"
79 
80 namespace fhicl::detail {
81 
82  template <tt::const_flavor C>
84  public:
85  ParameterWalker() = default;
86  virtual ~ParameterWalker() = default;
87 
89 
90  bool
92  {
93  return before_action(p);
94  }
95  void
97  {
98  after_action(p);
99  }
100 
101  void
103  {
104  enter_table(t);
105  }
106  void
108  {
109  exit_table(t);
110  }
111 
112  void
114  {
115  enter_sequence(s);
116  }
117  void
119  {
120  exit_sequence(s);
121  }
122 
123  void
125  {
126  atom(a);
127  }
128 
129  void
131  {
133  }
134 
135  private:
136  virtual void enter_table(tt::maybe_const_t<TableBase, C>&) = 0;
138  virtual void atom(tt::maybe_const_t<AtomBase, C>&) = 0;
140 
141  virtual bool
143  {
144  return true;
145  }
146  virtual void
148  {}
149  virtual void
151  {}
152  virtual void
154  {}
155  };
156 
157  //=============================================================================
158  // IMPLEMENTATION BELOW
159 
160  template <tt::const_flavor C>
161  void
163  {
164  if (!do_before_action(p))
165  return;
166 
167  fhicl::par_type const pt = p.parameter_type();
168 
169  auto& tw = *this;
170 
171  if (is_table(pt)) {
172  using maybe_const_table = tt::maybe_const_t<TableBase, C>;
173  maybe_const_table& t = dynamic_cast<maybe_const_table&>(p);
174  do_enter_table(t);
175  cet::for_all(t.members(), [&tw](auto m) { tw.walk_over(*m); });
176  do_exit_table(t);
177  } else if (is_sequence(pt)) {
178  using maybe_const_sequence = tt::maybe_const_t<SequenceBase, C>;
179  maybe_const_sequence& s = dynamic_cast<maybe_const_sequence&>(p);
181  s.walk_elements(tw);
182  do_exit_sequence(s);
183  } else if (is_atom(pt)) {
184  using maybe_const_atom = tt::maybe_const_t<AtomBase, C>;
185  maybe_const_atom& a = dynamic_cast<maybe_const_atom&>(p);
186  do_atom(a);
187  } else {
188  using maybe_const_delegate = tt::maybe_const_t<DelegateBase, C>;
189  maybe_const_delegate& dp = dynamic_cast<maybe_const_delegate&>(p);
191  }
192 
193  do_after_action(p);
194  }
195 
196  // Explicit instantiations to avoid code bloat
199 }
200 
201 #endif /* fhiclcpp_types_detail_ParameterWalker_h */
202 
203 // Local variables:
204 // mode: c++
205 // End:
bool is_atom(par_type const pt)
void do_delegated_parameter(tt::maybe_const_t< DelegateBase, C > &dp)
virtual void exit_sequence(tt::maybe_const_t< SequenceBase, C > &)
void walk_over(tt::maybe_const_t< ParameterBase, C > &)
void do_after_action(tt::maybe_const_t< ParameterBase, C > &p)
virtual void after_action(tt::maybe_const_t< ParameterBase, C > &)
virtual void enter_table(tt::maybe_const_t< TableBase, C > &)=0
TMarker * pt
Definition: egs.C:25
virtual void atom(tt::maybe_const_t< AtomBase, C > &)=0
virtual ~ParameterWalker()=default
void do_enter_sequence(tt::maybe_const_t< SequenceBase, C > &s)
virtual void exit_table(tt::maybe_const_t< TableBase, C > &)
void do_enter_table(tt::maybe_const_t< TableBase, C > &t)
void do_exit_sequence(tt::maybe_const_t< SequenceBase, C > &s)
typename maybe_const< T, C >::type maybe_const_t
Definition: type_traits.h:112
virtual void delegated_parameter(tt::maybe_const_t< DelegateBase, C > &)=0
bool is_table(std::any const &val)
Definition: coding.h:55
bool do_before_action(tt::maybe_const_t< ParameterBase, C > &p)
void do_atom(tt::maybe_const_t< AtomBase, C > &a)
void do_exit_table(tt::maybe_const_t< TableBase, C > &t)
virtual bool before_action(tt::maybe_const_t< ParameterBase, C > &)
bool is_sequence(std::any const &val)
Definition: coding.h:49
virtual void enter_sequence(tt::maybe_const_t< SequenceBase, C > &)=0