OptionalSequence.h
Go to the documentation of this file.
1 #ifndef fhiclcpp_types_OptionalSequence_h
2 #define fhiclcpp_types_OptionalSequence_h
3 
4 #include "fhiclcpp/type_traits.h"
5 #include "fhiclcpp/types/Atom.h"
14 
15 #include <array>
16 #include <string>
17 #include <type_traits>
18 
19 namespace fhicl {
20 
21  class ParameterSet;
22 
23  //==================================================================
24  // e.g. OptionalSequence<int,4> ====> std::array<int,4>
25  //
26  template <typename T, std::size_t N = -1ull>
27  class OptionalSequence final : public detail::SequenceBase,
28  private detail::RegisterIfTableMember {
29  public:
30  static_assert(!tt::is_table_fragment_v<T>, NO_NESTED_TABLE_FRAGMENTS);
31  static_assert(!tt::is_optional_parameter_v<T>, NO_OPTIONAL_TYPES);
32  static_assert(!tt::is_delegated_parameter_v<T>, NO_DELEGATED_PARAMETERS);
33 
34  using ftype = std::array<std::shared_ptr<tt::fhicl_type<T>>, N>;
35  using value_type = std::array<tt::return_type<T>, N>;
36 
37  explicit OptionalSequence(Name&& name);
38  explicit OptionalSequence(Name&& name, Comment&& comment);
39  explicit OptionalSequence(Name&& name,
40  Comment&& comment,
41  std::function<bool()> maybeUse);
42 
43  bool
45  {
46  if (!has_value_)
47  return false;
48 
51  value_, result.begin(), [](auto const& elem) { return (*elem)(); });
52 
53  std::swap(result, t);
54  return true;
55  }
56 
57  bool
58  hasValue() const noexcept
59  {
60  return has_value_;
61  }
62 
63  private:
65  bool has_value_{false};
66 
67  std::size_t
68  get_size() const noexcept override
69  {
70  return value_.size();
71  }
72 
73  void
74  do_prepare_elements_for_validation(std::size_t const n) override
75  {
77  }
78 
79  void
82  {
83  cet::for_all(value_, [&pw](auto& e) { pw.walk_over(*e); });
84  }
85 
86  void
88  pw) const override
89  {
90  cet::for_all(value_, [&pw](auto const& e) { pw.walk_over(*e); });
91  }
92 
94  bool const trimParents) override;
95  };
96 
97  //==================================================================
98  // e.g. OptionalSequence<int> ====> std::vector<int>
99  //
100  template <typename T>
101  class OptionalSequence<T, -1ull> final
102  : public detail::SequenceBase,
104  public:
105  static_assert(!tt::is_table_fragment_v<T>, NO_NESTED_TABLE_FRAGMENTS);
106  static_assert(!tt::is_optional_parameter_v<T>, NO_OPTIONAL_TYPES);
107  static_assert(!tt::is_delegated_parameter_v<T>, NO_DELEGATED_PARAMETERS);
108 
109  using ftype = std::vector<std::shared_ptr<tt::fhicl_type<T>>>;
110  using value_type = std::vector<tt::return_type<T>>;
111 
112  explicit OptionalSequence(Name&& name);
113  explicit OptionalSequence(Name&& name, Comment&& comment);
114  explicit OptionalSequence(Name&& name,
115  Comment&& comment,
116  std::function<bool()> maybeUse);
117 
118  bool
120  {
121  if (!has_value_)
122  return false;
123 
125  cet::transform_all(value_, std::back_inserter(result), [](auto const& e) {
126  return (*e)();
127  });
128 
129  std::swap(result, t);
130  return true;
131  }
132 
133  bool
134  hasValue() const noexcept
135  {
136  return has_value_;
137  }
138 
139  private:
141  bool has_value_{false};
142 
143  void
144  do_prepare_elements_for_validation(std::size_t const n) override
145  {
146  if (n < value_.size()) {
147  value_.resize(n);
148  } else if (n > value_.size()) {
149 
150  std::string key_fragment{key()};
151  // When emplacing a new element, do not include in the key
152  // argument the current name-stack stem--it will
153  // automatically be prepended.
154  auto const& nsr = NameStackRegistry::instance();
155  if (!nsr.empty()) {
156  std::string const& current_stem = nsr.current();
157  std::size_t const pos =
158  key_fragment.find(current_stem) != std::string::npos ?
159  current_stem.size() + 1ul : // + 1ul to account for the '.'
160  0ul;
161  key_fragment.replace(0ul, pos, "");
162  }
163 
164  for (auto i = value_.size(); i != n; ++i) {
165  value_.emplace_back(
166  new tt::fhicl_type<T>{Name::sequence_element(key_fragment, i)});
167  }
168  }
169  }
170 
171  std::size_t
172  get_size() const noexcept override
173  {
174  return value_.size();
175  }
176 
177  void
180  {
181  cet::for_all(value_, [&pw](auto& e) { pw.walk_over(*e); });
182  }
183 
184  void
186  pw) const override
187  {
188  cet::for_all(value_, [&pw](auto const& e) { pw.walk_over(*e); });
189  }
190 
191  void do_set_value(fhicl::ParameterSet const&,
192  bool const trimParents) override;
193  };
194 }
195 
197 
198 namespace fhicl {
199 
200  //==================================================================
201  // e.g. OptionalSequence<int,4> ====> std::array<int,4>
202  //
203  template <typename T, std::size_t N>
205  : OptionalSequence{std::move(name), Comment("")}
206  {}
207 
208  template <typename T, std::size_t N>
210  : SequenceBase{std::move(name),
211  std::move(comment),
215  , RegisterIfTableMember{this}
216  , value_{{nullptr}}
217  {
218  for (std::size_t i{}; i != N; ++i) {
219  value_.at(i) =
220  std::make_shared<tt::fhicl_type<T>>(Name::sequence_element(i));
221  }
223  }
224 
225  template <typename T, std::size_t N>
227  Comment&& comment,
228  std::function<bool()> maybeUse)
229  : SequenceBase{std::move(name),
230  std::move(comment),
233  maybeUse}
234  , RegisterIfTableMember{this}
235  , value_{{nullptr}}
236  {
237  for (std::size_t i{}; i != N; ++i) {
238  value_.at(i) =
239  std::make_shared<tt::fhicl_type<T>>(Name::sequence_element(i));
240  }
242  }
243 
244  template <typename T, std::size_t N>
245  void
247  bool const /*trimParents*/)
248  {
249  // We do not explicitly set the sequence values here as the
250  // individual elements are set one at a time. However, this
251  // function is reached in the ValidateThenSet algorithm if the
252  // optional parameter is present. Otherwise, this override is
253  // skipped.
254  has_value_ = true;
255  }
256 
257  //==================================================================
258  // e.g. OptionalSequence<int> ====> std::vector<int>
259  //
260 
261  template <typename T>
263  : OptionalSequence{std::move(name), Comment("")}
264  {}
265 
266  template <typename T>
268  : SequenceBase{std::move(name),
269  std::move(comment),
273  , RegisterIfTableMember{this}
274  {
275  value_.emplace_back(new tt::fhicl_type<T>{Name::sequence_element(0ul)});
277  }
278 
279  template <typename T>
281  Comment&& comment,
282  std::function<bool()> maybeUse)
283  : SequenceBase{std::move(name),
284  std::move(comment),
287  maybeUse}
288  , RegisterIfTableMember{this}
289  {
290  value_.emplace_back(new tt::fhicl_type<T>{Name::sequence_element(0ul)});
292  }
293 
294  template <typename T>
295  void
297  bool const /*trimParents*/)
298  {
299  // We do not explicitly set the sequence values here as the
300  // individual elements are set one at a time. However, this
301  // function is reached in the ValidateThenSet algorithm if the
302  // optional parameter is present. Otherwise, this override is
303  // skipped.
304  has_value_ = true;
305  }
306 }
307 
308 #endif /* fhiclcpp_types_OptionalSequence_h */
309 
310 // Local variables:
311 // mode: c++
312 // End:
void do_prepare_elements_for_validation(std::size_t const n) override
const XML_Char * name
Definition: expat.h:151
static NameStackRegistry & instance()
std::array< tt::return_type< T >, N > value_type
#define NO_DELEGATED_PARAMETERS
void check_nargs_for_bounded_sequences(std::string const &key, std::size_t expected, std::size_t provided)
void do_walk_elements(detail::ParameterWalker< tt::const_flavor::require_non_const > &pw) override
std::size_t get_size() const noexcept override
#define NO_OPTIONAL_TYPES
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::array< std::shared_ptr< tt::fhicl_type< T >>, N > ftype
void walk_over(tt::maybe_const_t< ParameterBase, C > &)
typename fhicl_type_impl< T >::type fhicl_type
Definition: type_traits.h:293
std::void_t< T > n
void do_set_value(fhicl::ParameterSet const &, bool const trimParents) override
bool operator()(value_type &t) const
void do_prepare_elements_for_validation(std::size_t const n) override
bool hasValue() const noexcept
auto transform_all(Container &, OutputIt, UnaryOp)
void do_walk_elements(detail::ParameterWalker< tt::const_flavor::require_const > &pw) const override
#define NO_NESTED_TABLE_FRAGMENTS
void do_walk_elements(detail::ParameterWalker< tt::const_flavor::require_non_const > &pw) override
bool operator()(value_type &t) const
std::string const & key() const
Definition: ParameterBase.h:44
static Name sequence_element(std::size_t const i)
Definition: Name.h:17
void do_walk_elements(detail::ParameterWalker< tt::const_flavor::require_const > &pw) const override
auto for_all(FwdCont &, Func)
std::string const & comment() const
Definition: ParameterBase.h:54
std::vector< tt::return_type< T >> value_type
typename return_type_impl< ARGS... >::value_type return_type
Definition: type_traits.h:330
double T
Definition: Xdiff_gwt.C:5
std::vector< std::shared_ptr< tt::fhicl_type< T >>> ftype
Float_t e
Definition: plot.C:35
std::size_t get_size() const noexcept override
enum BeamMode string