LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
OptionalTuple.h
Go to the documentation of this file.
1 #ifndef fhiclcpp_types_OptionalTuple_h
2 #define fhiclcpp_types_OptionalTuple_h
3 
5 #include "fhiclcpp/type_traits.h"
6 #include "fhiclcpp/types/Atom.h"
14 
15 #include <string>
16 #include <utility>
17 
18 namespace fhicl {
19 
20  class ParameterSet;
21 
22  //==================================================================
23  // e.g. OptionalTuple<int,double,bool> ====> std::tuple<int,double,bool>
24  //
25 
26  template <typename... TYPES>
27  class OptionalTuple final : public detail::SequenceBase,
28  private detail::RegisterIfTableMember {
29  public:
30  using ftype = std::tuple<std::shared_ptr<tt::fhicl_type<TYPES>>...>;
31  using value_type = std::tuple<tt::return_type<TYPES>...>;
32 
33  explicit OptionalTuple(Name&& name);
34  explicit OptionalTuple(Name&& name, Comment&& comment);
35  explicit OptionalTuple(Name&& name,
36  Comment&& comment,
37  std::function<bool()> maybeUse);
38 
39  bool operator()(value_type&) const;
40 
41  bool
42  hasValue() const
43  {
44  return has_value_;
45  }
46 
47  private:
49  bool has_value_{false};
50 
51  std::size_t
52  get_size() const override
53  {
54  return std::tuple_size<ftype>();
55  }
56 
57  //===================================================================
58  // iterate over tuple elements
59  using PW_non_const =
62 
63  void
64  visit_element(PW_non_const&)
65  {}
66 
67  template <typename E, typename... T>
68  void
69  visit_element(PW_non_const& pw, E& elem, T&... others)
70  {
71  using elem_ftype = typename E::element_type;
78  pw.walk_over(*elem);
79  visit_element(pw, others...);
80  }
81 
82  template <std::size_t... I>
83  void
84  iterate_over_tuple(PW_non_const& pw, std::index_sequence<I...>)
85  {
86  visit_element(pw, std::get<I>(value_)...);
87  }
88 
89  void
90  do_prepare_elements_for_validation(std::size_t const n) override
91  {
93  }
94 
95  void
96  do_walk_elements(PW_non_const& pw) override
97  {
98  iterate_over_tuple(pw, std::index_sequence_for<TYPES...>{});
99  }
100 
101  void
103  {}
104 
105  template <typename E, typename... T>
106  void
107  visit_element(PW_const& pw, E const& elem, T const&... others) const
108  {
109  using elem_ftype = typename E::element_type;
116  pw.walk_over(*elem);
117  visit_element(pw, others...);
118  }
119 
120  template <std::size_t... I>
121  void
122  iterate_over_tuple(PW_const& pw, std::index_sequence<I...>) const
123  {
124  visit_element(pw, std::get<I>(value_)...);
125  }
126 
127  void
128  do_walk_elements(PW_const& pw) const override
129  {
130  iterate_over_tuple(pw, std::index_sequence_for<TYPES...>{});
131  }
132 
133  //===================================================================
134  // finalizing tuple elements
135  void finalize_tuple_elements(std::size_t) {}
136 
137  // 'E' and 'T' are shared_ptr's.
138  template <typename E, typename... T>
139  void
140  finalize_tuple_elements(std::size_t i, E& elem, T&... others)
141  {
142  using elem_ftype = typename E::element_type;
149  elem = std::make_shared<elem_ftype>(Name::sequence_element(i));
150  finalize_tuple_elements(++i, others...);
151  }
152 
153  template <std::size_t... I>
154  void
155  finalize_elements(std::index_sequence<I...>)
156  {
157  finalize_tuple_elements(0, std::get<I>(value_)...);
158  }
159 
160  //===================================================================
161  // filling return type
162 
163  using TUPLE = std::tuple<tt::fhicl_type<TYPES>...>;
164 
165  template <size_t I, typename value_type>
166  std::enable_if_t<(I >= std::tuple_size<TUPLE>::value)>
168  {}
169 
170  template <size_t I, typename value_type>
173  {
174  std::get<I>(result) = (*std::get<I>(value_))();
175  fill_return_element<I + 1>(result);
176  }
177 
178  void
179  assemble_rtype(value_type& result) const
180  {
181  fill_return_element<0>(result);
182  }
183 
184  void
186  bool const /*trimParents*/) override
187  {
188  // We do not explicitly set the sequence values here as the
189  // individual elements are set one at a time. However, this
190  // function is reached in the ValidateThenSet algorithm if the
191  // optional parameter is present. Otherwise, this override is
192  // skipped.
193  has_value_ = true;
194  }
195 
196  }; // class OptionalTuple
197 
198  //================= IMPLEMENTATION =========================
199  //
200  template <typename... TYPES>
202  : OptionalTuple{std::move(name), Comment("")}
203  {}
204 
205  template <typename... TYPES>
207  : SequenceBase{std::move(name),
208  std::move(comment),
212  , RegisterIfTableMember{this}
213  {
214  finalize_elements(std::index_sequence_for<TYPES...>{});
216  }
217 
218  template <typename... TYPES>
220  Comment&& comment,
221  std::function<bool()> maybeUse)
222  : SequenceBase{std::move(name),
223  std::move(comment),
226  maybeUse}
227  , RegisterIfTableMember{this}
228  {
229  finalize_elements(std::index_sequence_for<TYPES...>{});
231  }
232 
233  template <typename... TYPES>
234  bool
236  {
237  if (!has_value_)
238  return false;
239  value_type result;
240  assemble_rtype(result);
241  std::swap(result, r);
242  return true;
243  }
244 }
245 
246 #endif /* fhiclcpp_types_OptionalTuple_h */
247 
248 // Local variables:
249 // mode: c++
250 // End:
bool operator()(value_type &) const
std::tuple< std::shared_ptr< tt::fhicl_type< TYPES >>... > ftype
Definition: OptionalTuple.h:30
std::tuple< tt::fhicl_type< TYPES >... > TUPLE
void assemble_rtype(value_type &result) const
Float_t E
Definition: plot.C:23
#define NO_DELEGATED_PARAMETERS
void iterate_over_tuple(PW_non_const &pw, std::index_sequence< I... >)
Definition: OptionalTuple.h:84
void check_nargs_for_bounded_sequences(std::string const &key, std::size_t expected, std::size_t provided)
std::enable_if_t<(I >=std::tuple_size< TUPLE >::value)> fill_return_element(value_type &) const
void do_prepare_elements_for_validation(std::size_t const n) override
Definition: OptionalTuple.h:90
#define NO_OPTIONAL_TYPES
void do_walk_elements(PW_const &pw) const override
void iterate_over_tuple(PW_const &pw, std::index_sequence< I... >) const
std::function< bool()> AlwaysUse()
SequenceBase(Name &&name, Comment &&comment, par_style const vt, par_type const type, std::function< bool()> maybeUse)
Definition: SequenceBase.h:20
std::tuple< tt::return_type< TYPES >... > value_type
Definition: OptionalTuple.h:31
void visit_element(PW_non_const &)
Definition: OptionalTuple.h:64
void walk_over(tt::maybe_const_t< ParameterBase, C > &)
parameter set interface
void finalize_tuple_elements(std::size_t i, E &elem, T &...others)
OptionalTuple(Name &&name)
void visit_element(PW_non_const &pw, E &elem, T &...others)
Definition: OptionalTuple.h:69
std::size_t get_size() const override
Definition: OptionalTuple.h:52
std::enable_if_t<(I< std::tuple_size< TUPLE >::value)> fill_return_element(value_type &result) const
void finalize_elements(std::index_sequence< I... >)
#define NO_NESTED_TABLE_FRAGMENTS
static Name sequence_element(std::size_t const i)
Definition: Name.h:17
std::string value(boost::any const &)
void finalize_tuple_elements(std::size_t)
void do_set_value(fhicl::ParameterSet const &, bool const ) override
std::string name() const
Definition: ParameterBase.h:49
void visit_element(PW_const &pw, E const &elem, T const &...others) const
Char_t n[5]
bool hasValue() const
Definition: OptionalTuple.h:42
void do_walk_elements(PW_non_const &pw) override
Definition: OptionalTuple.h:96
void visit_element(PW_const &) const
std::string key() const
Definition: ParameterBase.h:44
std::string comment() const
Definition: ParameterBase.h:54