LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
Sequence.h
Go to the documentation of this file.
1 #ifndef fhiclcpp_types_Sequence_h
2 #define fhiclcpp_types_Sequence_h
3 
4 #include "cetlib/container_algorithms.h"
5 #include "fhiclcpp/type_traits.h"
6 #include "fhiclcpp/types/Atom.h"
14 
15 #include <array>
16 #include <initializer_list>
17 #include <memory>
18 #include <string>
19 #include <type_traits>
20 #include <variant>
21 
22 namespace fhicl {
23 
24  namespace sequence_detail {
25 
26  // Auxiliary struct for accepting either
27  //
28  // (1) {1, 3, 5} or
29  // (2) std::array<int,3>{2, 4, 6}
30  //
31  // default values for Sequence<T,N>
32 
33  template <typename T>
34  class ValueHolder {
35  public:
36  ValueHolder(std::initializer_list<T> list) : holder_{list} {}
37 
38  template <std::size_t N>
39  ValueHolder(std::array<T, N> const& array)
40  : holder_(array.cbegin(), array.cend())
41  {}
42 
43  auto
44  begin() const noexcept
45  {
46  return holder_.cbegin();
47  }
48  auto
49  end() const noexcept
50  {
51  return holder_.cend();
52  }
53  auto
54  cbegin() const noexcept
55  {
56  return holder_.cbegin();
57  }
58  auto
59  cend() const noexcept
60  {
61  return holder_.cend();
62  }
63 
64  private:
65  std::vector<T> const holder_;
66  };
67  }
68 
69  class ParameterSet;
70 
71  //==================================================================
72  // e.g. Sequence<int,4> ====> std::array<int,4>
73  //
74  template <typename T, std::size_t N = -1ull>
75  class Sequence final : public detail::SequenceBase,
77  public:
78  static_assert(!tt::is_table_fragment_v<T>, NO_NESTED_TABLE_FRAGMENTS);
79  static_assert(!tt::is_optional_parameter_v<T>, NO_OPTIONAL_TYPES);
80  static_assert(!tt::is_delegated_parameter_v<T>, NO_DELEGATED_PARAMETERS);
81 
82  using default_type =
84  using ftype = std::array<std::shared_ptr<tt::fhicl_type<T>>, N>;
85  using value_type = std::array<tt::return_type<T>, N>;
86 
87  explicit Sequence(Name&& name);
88  explicit Sequence(Name&& name, Comment&& comment);
89  explicit Sequence(Name&& name,
90  Comment&& comment,
91  std::function<bool()> maybeUse);
92 
93  // c'tors that support defaults
94  explicit Sequence(Name&& name, default_type const& defaults);
95  explicit Sequence(Name&& name,
96  Comment&& comment,
97  default_type const& defaults);
98  explicit Sequence(Name&& name,
99  Comment&& comment,
100  std::function<bool()> maybeUse,
101  default_type const& defaults);
102 
103  auto
104  operator()() const
105  {
106  if (auto value = std::get_if<value_type>(&value_)) {
107  return *value;
108  }
109  value_type result = {{tt::return_type<T>()}};
110  cet::transform_all(std::get<ftype>(value_),
111  result.begin(),
112  [](auto const& elem) { return (*elem)(); });
113  return result;
114  }
115 
116  auto
117  operator()(std::size_t const i) const
118  {
119  if (auto value = std::get_if<value_type>(&value_)) {
120  return value->at(i);
121  }
122  return (*std::get<ftype>(value_).at(i))();
123  }
124 
125  private:
126  std::variant<ftype, value_type> value_;
127 
128  std::size_t
129  get_size() const noexcept override
130  {
131  if (auto value = std::get_if<value_type>(&value_)) {
132  return value->size();
133  }
134  return std::get<ftype>(value_).size();
135  }
136 
137  void
138  do_prepare_elements_for_validation(std::size_t const n) override
139  {
140  detail::check_nargs_for_bounded_sequences(key(), get_size(), n);
141  }
142 
143  void
146  {
147  // We only enter here if we do not have a preset value.
148  cet::for_all(std::get<ftype>(value_),
149  [&pw](auto& e) { pw.walk_over(*e); });
150  }
151 
152  void
154  pw) const override
155  {
156  // We only enter here if we do not have a preset value.
157  cet::for_all(std::get<ftype>(value_),
158  [&pw](auto const& e) { pw.walk_over(*e); });
159  }
160 
161  bool
163  {
164  if constexpr (std::is_same_v<tt::fhicl_type<T>, Atom<T>>) {
165  auto const trimmed_key = detail::strip_first_containing_name(key());
166  value_ = ps.get<value_type>(trimmed_key);
167  return true;
168  }
169  return false;
170  }
171 
172  void
174  {}
175  };
176 
177  //==================================================================
178  // e.g. Sequence<int> ====> std::vector<int>
179  //
180  template <typename T>
181  class Sequence<T, -1ull> final : public detail::SequenceBase,
183  public:
184  static_assert(!tt::is_table_fragment_v<T>, NO_NESTED_TABLE_FRAGMENTS);
185  static_assert(!tt::is_optional_parameter_v<T>, NO_OPTIONAL_TYPES);
186  static_assert(!tt::is_delegated_parameter_v<T>, NO_DELEGATED_PARAMETERS);
187 
188  using default_type = std::vector<typename tt::fhicl_type<T>::default_type>;
189  using ftype = std::vector<std::shared_ptr<tt::fhicl_type<T>>>;
190  using value_type = std::vector<tt::return_type<T>>;
191 
192  explicit Sequence(Name&& name);
193  explicit Sequence(Name&& name, Comment&& comment);
194  explicit Sequence(Name&& name,
195  Comment&& comment,
196  std::function<bool()> maybeUse);
197 
198  // c'tors supporting default values
199  explicit Sequence(Name&& name, default_type const& defaults);
200  explicit Sequence(Name&& name,
201  Comment&& comment,
202  default_type const& defaults);
203  explicit Sequence(Name&& name,
204  Comment&& comment,
205  std::function<bool()> maybeUse,
206  default_type const& defaults);
207 
208  auto
209  operator()() const
210  {
211  if (auto value = std::get_if<value_type>(&value_)) {
212  return *value;
213  }
214  value_type result;
215  cet::transform_all(std::get<ftype>(value_),
216  std::back_inserter(result),
217  [](auto const& e) { return (*e)(); });
218  return result;
219  }
220 
221  auto
222  operator()(std::size_t const i) const
223  {
224  if (auto value = std::get_if<value_type>(&value_)) {
225  return value->at(i);
226  }
227  return (*std::get<ftype>(value_).at(i))();
228  }
229 
230  private:
231  std::variant<ftype, value_type> value_;
232 
233  void
234  do_prepare_elements_for_validation(std::size_t const n) override
235  {
236  // We only enter here if we do not have a preset value.
237  auto& value = std::get<ftype>(value_);
238 
239  // For an unbounded sequence, we need to resize it so that any
240  // nested parameters of the elements can be checked.
241  if (n < value.size()) {
242  value.resize(n);
243  } else if (n > value.size()) {
244  std::string key_fragment{key()};
245  // When emplacing a new element, do not include in the key
246  // argument the current name-stack stem--it will automatically
247  // be prepended.
248  if (!NameStackRegistry::empty()) {
249  std::string const& current_stem = NameStackRegistry::current();
250  std::size_t const pos =
251  key_fragment.find(current_stem) != std::string::npos ?
252  current_stem.size() + 1ul : // + 1ul to account for the '.'
253  0ul;
254  key_fragment.replace(0ul, pos, "");
255  }
256 
257  for (auto i = value.size(); i != n; ++i) {
258  value.push_back(std::make_shared<tt::fhicl_type<T>>(
259  Name::sequence_element(key_fragment, i)));
260  }
261  }
262  }
263 
264  std::size_t
265  get_size() const noexcept override
266  {
267  if (auto value = std::get_if<value_type>(&value_)) {
268  return value->size();
269  }
270  return std::get<ftype>(value_).size();
271  }
272 
273  void
276  {
277  // We only enter here if we do not have a preset value.
278  cet::for_all(std::get<ftype>(value_),
279  [&pw](auto& e) { pw.walk_over(*e); });
280  }
281 
282  void
284  pw) const override
285  {
286  // We only enter here if we do not have a preset value.
287  cet::for_all(std::get<ftype>(value_),
288  [&pw](auto const& e) { pw.walk_over(*e); });
289  }
290 
291  bool
293  {
294  if constexpr (std::is_same_v<tt::fhicl_type<T>, Atom<T>>) {
295  auto const trimmed_key = detail::strip_first_containing_name(key());
296  value_ = ps.get<value_type>(trimmed_key);
297  return true;
298  }
299  return false;
300  }
301 
302  void
304  {}
305  };
306 }
307 
308 #include "cetlib/container_algorithms.h"
309 #include "cetlib_except/demangle.h"
311 #include "fhiclcpp/type_traits.h"
315 
316 #include <iostream>
317 #include <string>
318 
319 namespace fhicl {
320 
321  //==================================================================
322  // e.g. Sequence<int,4> ====> std::array<int,4>
323  //
324 
325  template <typename T, std::size_t N>
326  Sequence<T, N>::Sequence(Name&& name) : Sequence{std::move(name), Comment("")}
327  {}
328 
329  template <typename T, std::size_t N>
331  : SequenceBase{std::move(name),
332  std::move(comment),
336  , RegisterIfTableMember{this}
337  , value_{ftype{nullptr}}
338  {
339  auto& value = std::get<ftype>(value_);
340  for (std::size_t i{}; i != N; ++i) {
341  value.at(i) =
342  std::make_shared<tt::fhicl_type<T>>(Name::sequence_element(i));
343  }
345  }
346 
347  template <typename T, std::size_t N>
349  Comment&& comment,
350  std::function<bool()> maybeUse)
351  : SequenceBase{std::move(name),
352  std::move(comment),
355  maybeUse}
356  , RegisterIfTableMember{this}
357  , value_{ftype{nullptr}}
358  {
359  auto& value = std::get<ftype>(value_);
360  for (std::size_t i{}; i != N; ++i) {
361  value.at(i) =
362  std::make_shared<tt::fhicl_type<T>>(Name::sequence_element(i));
363  }
365  }
366 
367  // c'tors that support defaults
368  template <typename T, std::size_t N>
370  : Sequence{std::move(name), Comment{""}, defaults}
371  {}
372 
373  template <typename T, std::size_t N>
375  Comment&& comment,
376  default_type const& defaults)
377  : SequenceBase{std::move(name),
378  std::move(comment),
382  , RegisterIfTableMember{this}
383  , value_{ftype{nullptr}}
384  {
385  std::size_t i{};
386  auto& value = std::get<ftype>(value_);
387  for (auto const& arg : defaults) {
388  value.at(i) =
389  std::make_shared<tt::fhicl_type<T>>(Name::sequence_element(i), arg);
390  ++i;
391  }
393  }
394 
395  template <typename T, std::size_t N>
397  Comment&& comment,
398  std::function<bool()> maybeUse,
399  default_type const& defaults)
400  : SequenceBase{std::move(name),
401  std::move(comment),
404  maybeUse}
405  , RegisterIfTableMember{this}
406  , value_{ftype{nullptr}}
407  {
408  std::size_t i{};
409  auto& value = std::get<ftype>(value_);
410  for (auto const& arg : defaults) {
411  value.at(i) =
412  std::make_shared<tt::fhicl_type<T>>(Name::sequence_element(i), arg);
413  ++i;
414  }
416  }
417 
418  //==================================================================
419  // e.g. Sequence<int> ====> std::vector<int>
420  //
421  template <typename T>
423  : Sequence{std::move(name), Comment{""}}
424  {}
425 
426  template <typename T>
428  : SequenceBase{std::move(name),
429  std::move(comment),
433  , RegisterIfTableMember{this}
434  , value_{
435  ftype{std::make_shared<tt::fhicl_type<T>>(Name::sequence_element(0ul))}}
436  {
438  }
439 
440  template <typename T>
442  Comment&& comment,
443  std::function<bool()> maybeUse)
444  : SequenceBase{std::move(name),
445  std::move(comment),
448  maybeUse}
449  , RegisterIfTableMember{this}
450  , value_{
451  ftype{std::make_shared<tt::fhicl_type<T>>(Name::sequence_element(0ul))}}
452  {
454  }
455 
456  // c'tors that support defaults
457  template <typename T>
459  : Sequence{std::move(name), Comment{""}, defaults}
460  {}
461 
462  template <typename T>
464  Comment&& comment,
465  default_type const& defaults)
466  : SequenceBase{std::move(name),
467  std::move(comment),
471  , RegisterIfTableMember{this}
472  {
473  static_assert(!tt::is_table_v<T>, NO_DEFAULTS_FOR_TABLE);
474  std::size_t i{};
475  auto& value = std::get<ftype>(value_);
476  for (auto const& t : defaults) {
477  value.push_back(
478  std::make_shared<tt::fhicl_type<T>>(Name::sequence_element(i), t));
479  ++i;
480  }
482  }
483 
484  template <typename T>
486  Comment&& comment,
487  std::function<bool()> maybeUse,
488  default_type const& defaults)
489  : SequenceBase{std::move(name),
490  std::move(comment),
493  maybeUse}
494  , RegisterIfTableMember{this}
495  {
496  static_assert(!tt::is_table_v<T>, NO_DEFAULTS_FOR_TABLE);
497  std::size_t i{};
498  auto& value = std::get<ftype>(value_);
499  for (auto const& t : defaults) {
500  value.emplace_back(
501  std::make_shared<tt::fhicl_type<T>>(Name::sequence_element(i), t));
502  ++i;
503  }
505  }
506 }
507 
508 #endif /* fhiclcpp_types_Sequence_h */
509 
510 // Local variables:
511 // mode: c++
512 // End:
std::array< tt::return_type< float >, N > value_type
Definition: Sequence.h:85
std::vector< T > const holder_
Definition: Sequence.h:65
void do_walk_elements(detail::ParameterWalker< tt::const_flavor::require_const > &pw) const override
Definition: Sequence.h:283
void do_prepare_elements_for_validation(std::size_t const n) override
Definition: Sequence.h:138
std::variant< ftype, value_type > value_
Definition: Sequence.h:231
#define NO_DELEGATED_PARAMETERS
void check_nargs_for_bounded_sequences(std::string const &key, std::size_t expected, std::size_t provided)
auto operator()(std::size_t const i) const
Definition: Sequence.h:222
bool do_preset_value(fhicl::ParameterSet const &ps) override
Definition: Sequence.h:162
auto operator()(std::size_t const i) const
Definition: Sequence.h:117
auto operator()() const
Definition: Sequence.h:209
#define NO_OPTIONAL_TYPES
ValueHolder(std::array< T, N > const &array)
Definition: Sequence.h:39
std::function< bool()> AlwaysUse()
SequenceBase(Name &&name, Comment &&comment, par_style const vt, par_type const type, std::function< bool()> maybeUse)
Definition: SequenceBase.h:19
void do_walk_elements(detail::ParameterWalker< tt::const_flavor::require_non_const > &pw) override
Definition: Sequence.h:274
void do_prepare_elements_for_validation(std::size_t const n) override
Definition: Sequence.h:234
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:101
std::string strip_first_containing_name(std::string const &key)
bool do_preset_value(fhicl::ParameterSet const &ps) override
Definition: Sequence.h:292
void walk_over(tt::maybe_const_t< ParameterBase, C > &)
auto operator()() const
Definition: Sequence.h:104
auto array(Array const &a)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:250
static std::string current()
auto end() const noexcept
Definition: Sequence.h:49
typename fhicl_type_impl< T >::type fhicl_type
Definition: type_traits.h:315
auto begin() const noexcept
Definition: Sequence.h:44
std::vector< typename tt::fhicl_type< T >::default_type > default_type
Definition: Sequence.h:188
std::vector< std::shared_ptr< tt::fhicl_type< T >>> ftype
Definition: Sequence.h:189
parameter set interface
void do_walk_elements(detail::ParameterWalker< tt::const_flavor::require_const > &pw) const override
Definition: Sequence.h:153
T get(std::string const &key) const
Definition: ParameterSet.h:314
void do_set_value(fhicl::ParameterSet const &) override
Definition: Sequence.h:173
std::string const & name() const
auto cend() const noexcept
Definition: Sequence.h:59
Sequence(Name &&name)
Definition: Sequence.h:326
void do_walk_elements(detail::ParameterWalker< tt::const_flavor::require_non_const > &pw) override
Definition: Sequence.h:144
void do_set_value(fhicl::ParameterSet const &) override
Definition: Sequence.h:303
#define NO_NESTED_TABLE_FRAGMENTS
std::vector< tt::return_type< T >> value_type
Definition: Sequence.h:190
double value
Definition: spectrum.C:18
std::array< std::shared_ptr< tt::fhicl_type< float >>, N > ftype
Definition: Sequence.h:84
static Name sequence_element(std::size_t const i)
Definition: Name.h:16
std::size_t get_size() const noexcept override
Definition: Sequence.h:265
ValueHolder(std::initializer_list< T > list)
Definition: Sequence.h:36
Char_t n[5]
typename return_type_impl< ARGS... >::value_type return_type
Definition: type_traits.h:357
auto cbegin() const noexcept
Definition: Sequence.h:54
#define NO_DEFAULTS_FOR_TABLE
std::string const & comment() const
std::variant< ftype, value_type > value_
Definition: Sequence.h:126
Float_t e
Definition: plot.C:35
std::size_t get_size() const noexcept override
Definition: Sequence.h:129