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 
31  psw.before_action(p)
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 
58  The actions that are to be taken per parameter category (table,
59  sequence, or atom) are defined entirely by overrides to the
60  ParameterWalker virtual functions that 'psw' calls (as shown above).
61 
62  The function calls prefaced with '***' correspond to pure virtual
63  functions, which must have corresponding overrides in any derived
64  classes.
65 
66  The 'exit_{table,sequence}' functions are provided if (e.g.) the
67  derived-class state needs to be restored after the table or sequence
68  traversal. The '{before,after}_action' virtual functions are
69  provided so that category-agnostic instructions can be executed
70  before or after the category-specific ones.
71 */
72 
74 #include "cetlib_except/demangle.h"
75 #include "fhiclcpp/type_traits.h"
80 
81 namespace fhicl::detail {
82 
83  template <tt::const_flavor C>
85  public:
86  ParameterWalker() = default;
87  virtual ~ParameterWalker() = default;
88 
90 
91  bool
93  {
94  return before_action(p);
95  }
96  void
98  {
99  after_action(p);
100  }
101 
102  void
104  {
105  enter_table(t);
106  }
107  void
109  {
110  exit_table(t);
111  }
112 
113  void
115  {
116  enter_sequence(s);
117  }
118  void
120  {
121  exit_sequence(s);
122  }
123 
124  void
126  {
127  atom(a);
128  }
129 
130  void
132  {
134  }
135 
136  private:
137  virtual void enter_table(tt::maybe_const_t<TableBase, C>&) = 0;
139  virtual void atom(tt::maybe_const_t<AtomBase, C>&) = 0;
141 
142  virtual bool
144  {
145  return true;
146  }
147  virtual void
149  {}
150  virtual void
152  {}
153  virtual void
155  {}
156  };
157 
158  //=============================================================================
159  // IMPLEMENTATION BELOW
160 
161  template <tt::const_flavor C>
162  void
164  {
165  if (!do_before_action(p))
166  return;
167 
168  fhicl::par_type const pt = p.parameter_type();
169 
170  auto& tw = *this;
171 
172  if (is_table(pt)) {
173  using maybe_const_table = tt::maybe_const_t<TableBase, C>;
174  maybe_const_table& t = dynamic_cast<maybe_const_table&>(p);
175  do_enter_table(t);
176  cet::for_all(t.members(), [&tw](auto m) { tw.walk_over(*m); });
177  do_exit_table(t);
178  } else if (is_sequence(pt)) {
179  using maybe_const_sequence = tt::maybe_const_t<SequenceBase, C>;
180  maybe_const_sequence& s = dynamic_cast<maybe_const_sequence&>(p);
182  s.walk_elements(tw);
183  do_exit_sequence(s);
184  } else if (is_atom(pt)) {
185  using maybe_const_atom = tt::maybe_const_t<AtomBase, C>;
186  maybe_const_atom& a = dynamic_cast<maybe_const_atom&>(p);
187  do_atom(a);
188  } else {
189  using maybe_const_delegate = tt::maybe_const_t<DelegateBase, C>;
190  maybe_const_delegate& dp = dynamic_cast<maybe_const_delegate&>(p);
192  }
193 
194  do_after_action(p);
195  }
196 }
197 
198 #endif /* fhiclcpp_types_detail_ParameterWalker_h */
199 
200 // Local variables:
201 // mode: c++
202 // 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)
const double a
virtual void after_action(tt::maybe_const_t< ParameterBase, C > &)
virtual void enter_table(tt::maybe_const_t< TableBase, C > &)=0
virtual void atom(tt::maybe_const_t< AtomBase, C > &)=0
p
Definition: test.py:223
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)
auto for_all(FwdCont &, Func)
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)
static QCString * s
Definition: config.cpp:1042
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