LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
FindMany.h
Go to the documentation of this file.
1 #ifndef canvas_Persistency_Common_FindMany_h
2 #define canvas_Persistency_Common_FindMany_h
3 // FindMany
5 //
6 // A smart query object used as the main way of accessing associated
7 // objects in an association (one-to-one, one-to-many or many-to-many).
8 //
9 // Given an Assns associating A with B (or B with A) (possibly with an
10 // associated data object D) and a source ACOLL of A objects to be found
11 // in the Assns, allow indexed access to the B and/or D objects
12 // associated with the A objects in ACOLL.
13 //
15 // Interface.
17 //
18 // For ease of understanding, the interface is presented here; reading
19 // the rest of the header is not for the faint of heart. Compare with
20 // the corresponding interface for FindOne.
21 //
22 // Notes:
23 //
24 // * ProdB and Data are the only template arguments that must be
25 // specified when constructing a FindMany. Any other items
26 // are deducible from arguments.
27 //
28 // * The FindMany needs a source of objects of type A, a
29 // data container (e.g. an event) and an input tag corresponding to
30 // the underlying association collection from which to create itself.
31 //
32 // * When constructed, the FindMany will obtain and
33 // interrogate the correct Assns and provide access to the B (and/or D)
34 // object(s) associated with each supplied A object in the order in
35 // which the A objects were specified.
36 //
37 // * If the specified A does not have an associated B or D then the
38 // vector will be empty.
39 //
40 // * If the required association collection has an extra data object D
41 // with each association then it *must* be specified as a template
42 // argument, even if it is not relevant to the current query.
43 //
44 // * *All* indexed accessors (at(), data(), get()) are
45 // bounds-checked. Note that, because of the possible one-to-many
46 // association, these functions all return (or take as a reference in
47 // the case of get()) vectors, viz:
48 // * at() returns a const reference to a vector of const* (FindMany)
49 // or Ptr (FindManyP).
50 // * data returns a const reference to a vector of data objects.
51 // * get() takes references to a vector of const* or Ptr as
52 // appropriate, and a vector of data objects (if the data type is not
53 // void).
54 //
55 // Useful type aliases.
56 //
57 // using assoc_t = ProdB;
58 // using data_t = Data;
59 // using value_type = std::vector<assoc_t const*>; // FindMany
60 // using value_type = std::vector<art::Ptr<assoc_t>>; // FindManyP
61 // using size_type = typename std::vector<value_type>::size_type;
62 // using const_reference = value_type const&;
63 // using reference = value_type&;
64 // using data_const_reference = typename std::vector<data_t const*> const&;
65 // using data_reference = typename std::vector<data_t const*>&;
66 //
67 // Constructors.
68 //
69 // // From Handle or ValidHandle to collection of A.
70 // FindMany<ProdB>(Handle<ProdAColl> const&,
71 // DataContainer const&,
72 // InputTag const&);
73 // FindMany<ProdB, Data>(Handle<ProdAColl> const&,
74 // DataContainer const&,
75 // InputTag const&);
76 //
77 // // From sequence of pointer to A (including View<A>).
78 // FindMany<ProdB>(View<ProdA> const&,
79 // DataContainer const&,
80 // InputTag const&);
81 // FindMany<ProdB, Data>(View<ProdA> const&,
82 // DataContainer const&,
83 // InputTag const&);
84 //
85 // // From arbitrary sequence of Ptr<A>.
86 // FindMany<ProdB>(PtrProdAColl const&,
87 // DataContainer const&,
88 // InputTag const&);
89 // FindMany<ProdB, Data>(PtrProdAColl const&,
90 // DataContainer const&,
91 // InputTag const&);
92 //
93 // // From an initializer list of Ptr<A>.
94 // FindMany<ProdB>(<brace-enclosed initializer list>,
95 // DataContainer const&,
96 // InputTag const&);
97 // FindMany<ProdB, Data>(<brace-enclosed initializer list>,
98 // DataContainer const&,
99 // InputTag const&);
100 //
101 // Modifiers.
102 //
103 // <NONE>.
104 //
105 // Accessors.
106 //
107 // size_type size() const;
108 // const_reference at(size_type) const;
109 // const_data_reference data(size_type) const;
110 // size_type get(size_type,
111 // reference)
112 // const; // Returns number of elements appended.
113 // size_type get(size_type,
114 // reference,
115 // data_reference)
116 // const; // *Must* be used for FindMany<ProdB, Data>.
117 //
118 // Comparison operations.
119 //
120 // bool operator == (FindMany const& other) const;
121 //
123 
129 
130 #include <initializer_list>
131 #include <vector>
132 
133 /* #undef ART_IPR_BY_PTR */
134 
135 namespace art {
136  // General template
137  template <typename ProdB, typename DATA = void>
138  class FindMany;
139 
140  // Specialization.
141  template <typename ProdB>
142  class FindMany<ProdB, void>;
143 }
144 
146 // Implementation of the specialization.
147 template <typename ProdB>
148 class art::FindMany<ProdB, void>
149 {
150 public:
151 #ifdef ART_IPR_BY_PTR
152  using bColl_t = std::vector<std::vector<Ptr<ProdB>>>;
153 #else
154  using bColl_t = std::vector<std::vector<ProdB const*>>;
155 #endif
156  using value_type = typename bColl_t::value_type;
157  using size_type = typename bColl_t::size_type;
158  using difference_type = typename bColl_t::difference_type;
159  using const_reference = typename bColl_t::const_reference;
160  using reference = typename bColl_t::reference;
161 
162  using assoc_t = ProdB;
163 
164  template <typename Handle, typename DataContainer, typename Tag>
165  FindMany(Handle const& aCollection,
166  DataContainer const& dc,
167  Tag const& tag,
168  std::enable_if_t<detail::is_handle_v<Handle>>* = nullptr);
169 
170  template <typename ProdAColl, typename DataContainer, typename Tag>
171  FindMany(ProdAColl const& view,
172  DataContainer const& dc,
173  Tag const& tag,
174  std::enable_if_t<std::is_pointer_v<typename ProdAColl::value_type>>* =
175  nullptr);
176 
177  template <typename PtrProdAColl, typename DataContainer, typename Tag>
178  FindMany(PtrProdAColl const& aPtrColl,
179  DataContainer const& dc,
180  Tag const& tag,
181  std::enable_if_t<std::is_same_v<
182  typename PtrProdAColl::value_type,
184 
185  template <typename ProdA, typename DataContainer, typename Tag>
186  FindMany(std::initializer_list<Ptr<ProdA>> const& ptrs,
187  DataContainer const& dc,
188  Tag const& tag);
189 
190  // Is this a valid query (did we find an Assns)?
191  bool isValid() const;
192 
193  // Number of query results
194  size_type size() const;
195 
196  // Associated item by index (bounds-checked).
197  const_reference at(size_type i) const;
198 
199  size_type get(size_type i, reference item) const;
200 
201  bool operator==(FindMany<ProdB, void> const& other) const;
202 
203 protected:
204  FindMany() = default;
205  bColl_t& bCollection() { return bCollection_; }
206 
207  void setStoredException(std::shared_ptr<art::Exception const>&& e);
208  void throwIfInvalid() const;
209 
210 private:
211  bColl_t bCollection_{};
212  std::shared_ptr<art::Exception const> storedException_{nullptr};
213 };
214 
215 template <typename ProdB, typename Data>
216 class art::FindMany : private art::FindMany<ProdB, void> {
217 private:
219 
220 public:
221  using dataColl_t = std::vector<std::vector<Data const*>>;
222  using value_type = typename base::value_type;
223  using size_type = typename base::size_type;
226  using reference = typename base::reference;
227  using assoc_t = typename base::assoc_t;
228 
229  using data_const_pointer = typename dataColl_t::const_pointer;
230  using data_const_reference = typename dataColl_t::const_reference;
231  using data_reference = typename dataColl_t::reference;
232 
233  using data_t = Data;
234 
235  template <typename Handle, typename DataContainer, typename Tag>
236  FindMany(Handle const& aCollection,
237  DataContainer const& dc,
238  Tag const& tag,
239  std::enable_if_t<detail::is_handle_v<Handle>>* = nullptr);
240 
241  template <typename ProdAColl, typename DataContainer, typename Tag>
242  FindMany(ProdAColl const& view,
243  DataContainer const& dc,
244  Tag const& tag,
245  std::enable_if_t<std::is_pointer_v<typename ProdAColl::value_type>>* =
246  nullptr);
247 
248  template <typename PtrProdAColl, typename DataContainer, typename Tag>
249  FindMany(PtrProdAColl const& aPtrColl,
250  DataContainer const& dc,
251  Tag const& tag,
252  std::enable_if_t<std::is_same_v<
253  typename PtrProdAColl::value_type,
255 
256  template <typename ProdA, typename DataContainer, typename Tag>
257  FindMany(std::initializer_list<Ptr<ProdA>> const& ptrs,
258  DataContainer const& dc,
259  Tag const& tag);
260 
261  using base::at;
262  using base::get;
263  using base::isValid;
264  using base::size;
265 
266  // Association extra-data object by index (bounds-checked).
268 
269  // Associated item and extra-data object by index (bounds-checked).
270  size_type get(size_type i, reference item, data_reference data) const;
271 
272  bool operator==(FindMany<ProdB, Data> const& other) const;
273 
274 private:
276 };
277 
279 // Base class implementation.
280 template <typename ProdB>
281 template <typename Handle, typename DataContainer, typename Tag>
283  DataContainer const& dc,
284  Tag const& tag,
285  std::enable_if_t<detail::is_handle_v<Handle>>*)
286 {
287  using ProdA = typename Handle::element_type::value_type;
289  dc, detail::input_tag<ProdA, ProdB, void>(tag)};
290  storedException_ = finder(*aCollection, bCollection_);
291 }
292 
293 template <typename ProdB>
294 template <typename ProdAColl, typename DataContainer, typename Tag>
296  DataContainer const& dc,
297  Tag const& tag,
298  std::enable_if_t<std::is_pointer_v<typename ProdAColl::value_type>>*)
299 {
300  using ProdA =
301  std::remove_const_t<std::remove_pointer_t<typename ProdAColl::value_type>>;
303  dc, detail::input_tag<ProdA, ProdB, void>(tag)};
304  storedException_ = finder(view, bCollection_);
305 }
306 
307 template <typename ProdB>
308 template <typename PtrProdAColl, typename DataContainer, typename Tag>
309 art::FindMany<ProdB, void>::FindMany(PtrProdAColl const& aPtrColl,
310  DataContainer const& dc,
311  Tag const& tag,
312  std::enable_if_t<
313  std::is_same_v<typename PtrProdAColl::value_type,
315 {
316  using ProdA = typename PtrProdAColl::value_type::value_type;
318  dc, detail::input_tag<ProdA, ProdB, void>(tag)};
319  storedException_ = finder(aPtrColl, bCollection_);
320 }
321 
322 template <typename ProdB>
323 template <typename ProdA, typename DataContainer, typename Tag>
324 art::FindMany<ProdB, void>::FindMany(std::initializer_list<Ptr<ProdA>> const& ptrs,
325  DataContainer const& dc,
326  Tag const& tag)
327 {
329  dc, detail::input_tag<ProdA, ProdB, void>(tag)};
330  storedException_ = finder(ptrs, bCollection_);
331 }
332 
333 template <typename ProdB>
335 {
336  throwIfInvalid();
337  return bCollection_.size();
338 }
339 
340 template <typename ProdB>
342 {
343  return (storedException_.get() == nullptr);
344 }
345 
346 template <typename ProdB>
347 inline auto art::FindMany<ProdB, void>::at(size_type const i) const
348  -> const_reference
349 {
350  throwIfInvalid();
351  return bCollection_.at(i);
352 }
353 
354 template <typename ProdB>
356 {
357  throwIfInvalid();
358  const_reference ref(bCollection_.at(i));
359  item.insert(item.end(), ref.begin(), ref.end());
360  return ref.size();
361 }
362 
363 template <typename ProdB>
365 {
366  throwIfInvalid();
367  return bCollection_ == other.bCollection_;
368 }
369 
370 template <typename ProdB>
371 inline void art::FindMany<ProdB, void>::setStoredException(std::shared_ptr<art::Exception const>&& e)
372 {
373  storedException_ = std::move(e);
374 }
375 
376 template <typename ProdB>
378 {
379  if (!isValid()) {
380  throw Exception(
381  errors::LogicError, "Invalid FindMany", *storedException_)
382  << "Attempt to use a FindMany where the underlying "
383  "art::Assns product was not found.";
384  }
385 }
386 
388 // Derived class implementation.
389 template <typename ProdB, typename Data>
390 template <typename Handle, typename DataContainer, typename Tag>
392  DataContainer const& dc,
393  Tag const& tag,
394  std::enable_if_t<detail::is_handle_v<Handle>>*)
395 {
396  using ProdA = typename Handle::element_type::value_type;
398  dc, detail::input_tag<ProdA, ProdB, void>(tag)};
400  finder(*aCollection, base::bCollection(), dataCollection_));
401 }
402 
403 template <typename ProdB, typename Data>
404 template <typename ProdAColl, typename DataContainer, typename Tag>
406  DataContainer const& dc,
407  Tag const& tag,
408  std::enable_if_t<std::is_pointer_v<typename ProdAColl::value_type>>*)
409 {
410  using ProdA =
411  std::remove_const_t<std::remove_pointer_t<typename ProdAColl::value_type>>;
413  dc, detail::input_tag<ProdA, ProdB, void>(tag)};
415 }
416 
417 template <typename ProdB, typename Data>
418 template <typename PtrProdAColl, typename DataContainer, typename Tag>
419 art::FindMany<ProdB, Data>::FindMany(PtrProdAColl const& aPtrColl,
420  DataContainer const& dc,
421  Tag const& tag,
422  std::enable_if_t<
423  std::is_same_v<typename PtrProdAColl::value_type,
425 {
426  using ProdA = typename PtrProdAColl::value_type::value_type;
428  dc, detail::input_tag<ProdA, ProdB, Data>(tag)};
430  finder(aPtrColl, base::bCollection(), dataCollection_));
431 }
432 
433 template <typename ProdB, typename Data>
434 template <typename ProdA, typename DataContainer, typename Tag>
436  std::initializer_list<Ptr<ProdA>> const& ptrs,
437  DataContainer const& dc,
438  Tag const& tag)
439 {
441  dc, detail::input_tag<ProdA, ProdB, Data>(tag)};
443 }
444 
445 template <typename ProdB, typename Data>
447 {
449  return dataCollection_.at(i);
450 }
451 
452 template <typename ProdB, typename Data>
454  reference item,
455  data_reference data) const -> size_type
456 {
457  size_type result = base::get(i, item); // Will check validity.
459  data.insert(data.end(), ref.begin(), ref.end());
460  ;
461  return result;
462 }
463 
464 template <typename ProdB, typename Data>
466 {
467  return this->base::operator==(other) && // Will check validity.
469 }
470 
471 #undef ART_IPR_BY_PTR
472 
473 #endif /* canvas_Persistency_Common_FindMany_h */
474 
475 // Local Variables:
476 // mode: c++
477 // End:
typename base::const_reference const_reference
Definition: FindMany.h:225
size_type get(size_type i, reference item) const
Definition: FindMany.h:355
typename base::assoc_t assoc_t
Definition: FindMany.h:227
typename dataColl_t::const_pointer data_const_pointer
Definition: FindMany.h:229
size_type size() const
Definition: FindMany.h:334
size_type get(size_type i, reference item, data_reference data) const
Definition: FindMany.h:453
typename base::reference reference
Definition: FindMany.h:226
typename bColl_t::size_type size_type
Definition: FindMany.h:157
typename bColl_t::difference_type difference_type
Definition: FindMany.h:158
bool operator==(FindMany< ProdB, Data > const &other) const
Definition: FindMany.h:465
typename dataColl_t::reference data_reference
Definition: FindMany.h:231
std::vector< std::vector< ProdB const * >> bColl_t
Definition: FindMany.h:154
dataColl_t dataCollection_
Definition: FindMany.h:275
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:101
typename base::size_type size_type
Definition: FindMany.h:223
typename bColl_t::reference reference
Definition: FindMany.h:160
bool operator==(FindMany< ProdB, void > const &other) const
Definition: FindMany.h:364
typename bColl_t::const_reference const_reference
Definition: FindMany.h:159
typename base::difference_type difference_type
Definition: FindMany.h:224
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
void setStoredException(std::shared_ptr< art::Exception const > &&e)
Definition: FindMany.h:371
typename base::value_type value_type
Definition: FindMany.h:222
std::vector< std::vector< Data const * >> dataColl_t
Definition: FindMany.h:221
typename bColl_t::value_type value_type
Definition: FindMany.h:156
FindMany(Handle const &aCollection, DataContainer const &dc, Tag const &tag, std::enable_if_t< detail::is_handle_v< Handle >> *=nullptr)
Definition: FindMany.h:391
Definition: MVAAlg.h:12
void throwIfInvalid() const
Definition: FindMany.h:377
Float_t e
Definition: plot.C:35
const_reference at(size_type i) const
Definition: FindMany.h:347
Definition: fwd.h:26
data_const_reference data(size_type i) const
Definition: FindMany.h:446
typename dataColl_t::const_reference data_const_reference
Definition: FindMany.h:230