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 {
82  namespace detail {
83 
84  template <tt::const_flavor C>
86  public:
87  ParameterWalker() = default;
88  virtual ~ParameterWalker() = default;
89 
91 
92  bool
94  {
95  return before_action(p);
96  }
97  void
99  {
100  after_action(p);
101  }
102 
103  void
105  {
106  enter_table(t);
107  }
108  void
110  {
111  exit_table(t);
112  }
113 
114  void
116  {
117  enter_sequence(s);
118  }
119  void
121  {
122  exit_sequence(s);
123  }
124 
125  void
127  {
128  atom(a);
129  }
130 
131  void
133  {
135  }
136 
137  private:
138  virtual void enter_table(tt::maybe_const_t<TableBase, C>&) = 0;
140  virtual void atom(tt::maybe_const_t<AtomBase, C>&) = 0;
142 
143  virtual bool
145  {
146  return true;
147  }
148  virtual void
150  {}
151  virtual void
153  {}
154  virtual void
156  {}
157  };
158 
159  //=============================================================================
160  // IMPLEMENTATION BELOW
161 
162  template <tt::const_flavor C>
163  void
165  {
166  if (!do_before_action(p))
167  return;
168 
169  fhicl::par_type const pt = p.parameter_type();
170 
171  auto& tw = *this;
172 
173  if (is_table(pt)) {
174  using maybe_const_table = tt::maybe_const_t<TableBase, C>;
175  maybe_const_table& t = dynamic_cast<maybe_const_table&>(p);
176  do_enter_table(t);
177  cet::for_all(t.members(), [&tw](auto m) { tw.walk_over(*m); });
178  do_exit_table(t);
179  } else if (is_sequence(pt)) {
180  using maybe_const_sequence = tt::maybe_const_t<SequenceBase, C>;
181  maybe_const_sequence& s = dynamic_cast<maybe_const_sequence&>(p);
183  s.walk_elements(tw);
184  do_exit_sequence(s);
185  } else if (is_atom(pt)) {
186  using maybe_const_atom = tt::maybe_const_t<AtomBase, C>;
187  maybe_const_atom& a = dynamic_cast<maybe_const_atom&>(p);
188  do_atom(a);
189  } else {
190  using maybe_const_delegate = tt::maybe_const_t<DelegateBase, C>;
191  maybe_const_delegate& dp = dynamic_cast<maybe_const_delegate&>(p);
193  }
194 
195  do_after_action(p);
196  }
197  }
198 }
199 
200 #endif /* fhiclcpp_types_detail_ParameterWalker_h */
201 
202 // Local variables:
203 // mode: c++
204 // End:
bool is_atom(par_type const pt)
const char * p
Definition: xmltok.h:285
void do_delegated_parameter(tt::maybe_const_t< DelegateBase, C > &dp)
virtual void exit_sequence(tt::maybe_const_t< SequenceBase, C > &)
bool is_sequence(boost::any const &val)
Definition: coding.h:50
bool is_table(boost::any const &val)
Definition: coding.h:56
const XML_Char * s
Definition: expat.h:262
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
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:107
virtual void delegated_parameter(tt::maybe_const_t< DelegateBase, C > &)=0
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 > &)
virtual void enter_sequence(tt::maybe_const_t< SequenceBase, C > &)=0