LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
FindOne.h
Go to the documentation of this file.
1 #ifndef canvas_Persistency_Common_FindOne_h
2 #define canvas_Persistency_Common_FindOne_h
3 // FindOne
5 //
6 // A smart query object used as the main way of accessing associated
7 // objects in a one-to-one association.
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
11 // found 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.
20 //
21 // Notes:
22 //
23 // * ProdB and Data (if needed) are the only template arguments that
24 // must be specified when constructing a FindOne. Any other
25 // items are deducible from arguments.
26 //
27 // * An attempt to create a FindOne where one of the listed
28 // A objects actually has multiple B objects associated with it will
29 // result in an exception: use FindMany{,P} instead.
30 //
31 // * The FindOne needs a source of objects of type A, a
32 // data container (e.g. event and an input tag corresponding to the
33 // underlying association collection from which to create itself.
34 //
35 // * When constructed, the FindOne will obtain and
36 // interrogate the correct Assns and provide access to the B (and/or D)
37 // object(s) associated with each supplied A object in the order in
38 // which the A objects were specified.
39 //
40 // * If the specified A does not have an associated B or D then the
41 // cet::maybe_ref will be invalid.
42 //
43 // * If the required association collection has an extra data object D
44 // with each association then it *must* be specified as a template
45 // argument, even if it is not relevant to the current query.
46 //
47 // * *All* indexed accessors (at(), data(), get()) are bounds-checked.
48 //
49 // Useful type aliases.
50 //
51 // using assoc_t = ProdB;
52 // using data_t = Data;
53 // using size_type = typename std::vector<assoc_t const*>::size_type; // FindOne
54 // using size_type = typename std::vector<art::Ptr<assoc_t> >::size_type; // FindOneP
55 //
56 // Constructors.
57 //
58 // // From Handle or ValidHandle to collection of A.
59 // FindOne<ProdB>(Handle<ProdAColl> const&,
60 // DataContainer const&,
61 // InputTag const&);
62 // FindOne<ProdB, Data>(Handle<ProdAColl> const&,
63 // DataContainer const&,
64 // InputTag const&);
65 //
66 // // From sequence of pointer to A (including View<A>).
67 // FindOne<ProdB>(View<ProdA> const&,
68 // DataContainer const&,
69 // InputTag const&);
70 // FindOne<ProdB, Data>(View<ProdA> const&,
71 // DataContainer const&,
72 // InputTag const&);
73 //
74 // // From arbitrary sequence of Ptr<A>.
75 // FindOne<ProdB>(PtrProdAColl const&,
76 // DataContainer const&,
77 // InputTag const&);
78 // FindOne<ProdB, Data>(PtrProdAColl const&,
79 // DataContainer const&,
80 // InputTag const&);
81 //
82 // // From an initializer list of Ptr<A>.
83 // FindOne<ProdB>(<brace-enclosed initializer list>,
84 // DataContainer const&,
85 // InputTag const&);
86 // FindOne<ProdB, Data>(<brace-enclosed initializer list>,
87 // DataContainer const&,
88 // InputTag const&);
89 //
90 // Modifiers.
91 //
92 // <NONE>.
93 //
94 // Accessors.
95 //
96 // size_type size() const;
97 // cet::maybe_ref<assoc_t const> at(size_type) const; // FindOne
98 // art::Ptr<assoc_t> const& at(size_type) const; // FindOneP
99 // cet::maybe_ref<data_t const> data(size_type) const;
100 // void get(size_type,
101 // cet::maybe_ref<assoc_t const>&) const; // FindOne
102 // void get(size_type,
103 // art::Ptr<assoc_t>&) const; // FindOneP
104 // void get(size_type,
105 // cet::maybe_ref<assoc_t const>&,
106 // cet::maybe_ref<data_t const>&)
107 // const; // *Must* be used for FindOne<ProdB, Data>.
108 // void get(size_type,
109 // art::Ptr<assoc_t>&,
110 // cet::maybe_ref<data_t const>&)
111 // const; // *Must* be used for FindOneP<ProdB, Data>.
112 //
113 // Comparison operations.
114 //
115 // bool operator == (FindOne const& other) const;
116 //
123 #include "cetlib/maybe_ref.h"
124 
125 #include <initializer_list>
126 #include <vector>
127 
128 /* #undef ART_IPR_BY_PTR */
129 
130 namespace art {
131  // General template
132  template <typename ProdB, typename DATA = void>
133  class FindOne;
134 
135  // Specialization.
136  template <typename ProdB>
137  class FindOne<ProdB, void>;
138 }
139 
141 // Implementation of the specialization.
142 template <typename ProdB>
143 class art::FindOne<ProdB, void>
144 {
145 public:
146  using assoc_t = ProdB;
147 
148 #ifdef ART_IPR_BY_PTR
149  using bColl_t = std::vector<Ptr<assoc_t>>;
150 #else
151  using bColl_t = std::vector<ProdB const*>;
152 #endif
153  using value_type = typename bColl_t::value_type;
154  using size_type = typename bColl_t::size_type;
155  using difference_type = typename bColl_t::difference_type;
156  using const_reference = typename bColl_t::const_reference;
157  using reference = typename bColl_t::reference;
158 
159  template <typename Handle, typename DataContainer, typename Tag>
160  FindOne(
161  Handle const& aCollection,
162  DataContainer const& dc,
163  Tag const& tag,
164  std::enable_if_t<detail::is_handle_v<Handle>>* = nullptr);
165 
166  template <typename ProdAColl, typename DataContainer, typename Tag>
167  FindOne(
168  ProdAColl const& view,
169  DataContainer const& dc,
170  Tag const& tag,
171  std::enable_if_t<std::is_pointer_v<typename ProdAColl::value_type>>* =
172  nullptr);
173 
174  template <typename PtrProdAColl, typename DataContainer, typename Tag>
175  FindOne(
176  PtrProdAColl const& aPtrColl,
177  DataContainer const& dc,
178  Tag const& tag,
179  std::enable_if_t<std::is_same_v<
180  typename PtrProdAColl::value_type,
182  nullptr);
183 
184  template <typename ProdA, typename DataContainer, typename Tag>
185  FindOne(std::initializer_list<Ptr<ProdA>> const& ptrs,
186  DataContainer const& dc,
187  Tag const& tag);
188 
189  // Is this a valid query (did we find an Assns)?
190  bool isValid() const;
191 
192  // Number of query results
193  size_type size() const;
194 
195  // Associated item by index (bounds-checked).
196 #ifdef ART_IPR_BY_PTR
197  Ptr<assoc_t> const& at(size_type i) const;
198  void get(size_type i, Ptr<assoc_t> & item) const;
199 #else
200  cet::maybe_ref<assoc_t const> at(size_type i) const;
201  void get(size_type i, cet::maybe_ref<assoc_t const> & item) const;
202 #endif
203  bool operator==(FindOne<ProdB, void> const& other) const;
204 
205 protected:
206  FindOne() = default;
207  bColl_t& bCollection() { return bCollection_; }
208 
209  void setStoredException(std::shared_ptr<art::Exception const> && e);
210  void throwIfInvalid() const;
211 
212 private:
213  bColl_t bCollection_{};
214  std::shared_ptr<art::Exception const> storedException_{};
215 };
216 
217 template <typename ProdB, typename Data>
218 class art::FindOne : private art::FindOne<ProdB, void>
219 {
220 private:
222 
223 public:
224  using dataColl_t = std::vector<Data const*>;
225  using value_type = typename base::value_type;
226  using size_type = typename base::size_type;
229  using reference = typename base::reference;
230  using assoc_t = typename base::assoc_t;
231 
232  using data_const_pointer = Data const*;
233  using data_const_reference = Data const&;
234  using data_reference = Data&;
235  using data_t = Data;
236 
237  template <typename Handle, typename DataContainer, typename Tag>
238  FindOne(
239  Handle const& aCollection,
240  DataContainer const& dc,
241  Tag const& tag,
242  std::enable_if_t<detail::is_handle_v<Handle>>* = nullptr);
243 
244  template <typename ProdAColl, typename DataContainer, typename Tag>
245  FindOne(
246  ProdAColl const& view,
247  DataContainer const& dc,
248  Tag const& tag,
249  std::enable_if_t<std::is_pointer_v<typename ProdAColl::value_type>>* =
250  nullptr);
251 
252  template <typename PtrProdAColl, typename DataContainer, typename Tag>
253  FindOne(
254  PtrProdAColl const& aPtrColl,
255  DataContainer const& dc,
256  Tag const& tag,
257  std::enable_if_t<std::is_same_v<
258  typename PtrProdAColl::value_type,
260 
261  template <typename ProdA, typename DataContainer, typename Tag>
262  FindOne(std::initializer_list<Ptr<ProdA>> const& ptrs,
263  DataContainer const& dc,
264  Tag const& tag);
265 
266  using base::at;
267  using base::get;
268  using base::isValid;
269  using base::size;
270 
271  // Association extra-data object by index (bounds-checked).
272  cet::maybe_ref<Data const> data(size_type i) const;
273 
274  // Associated item and extra-data object by index (bounds-checked).
275  void get(size_type i,
276 #ifdef ART_IPR_BY_PTR
277  art::Ptr<assoc_t> & item,
278 #else
279  cet::maybe_ref<assoc_t const> & item,
280 #endif
281  cet::maybe_ref<Data const> & data) const;
282 
283  bool operator==(FindOne<ProdB, Data> const& other) const;
284 
285 private:
287 };
288 
290 // Base class implementation.
291 template <typename ProdB>
292 template <typename Handle, typename DataContainer, typename Tag>
294  Handle const& aCollection,
295  DataContainer const& dc,
296  Tag const& tag,
297  std::enable_if_t<detail::is_handle_v<Handle>>*)
298 {
299  using ProdA = typename Handle::element_type::value_type;
301  dc, detail::input_tag<ProdA, ProdB, void>(tag)};
302  storedException_ = finder(*aCollection, bCollection_);
303 }
304 
305 template <typename ProdB>
306 template <typename ProdAColl, typename DataContainer, typename Tag>
308  ProdAColl const& view,
309  DataContainer const& dc,
310  Tag const& tag,
311  std::enable_if_t<std::is_pointer_v<typename ProdAColl::value_type>>*)
312 {
313  using ProdA =
314  std::remove_const_t<std::remove_pointer_t<typename ProdAColl::value_type>>;
316  dc, detail::input_tag<ProdA, ProdB, void>(tag)};
317  storedException_ = finder(view, bCollection_);
318 }
319 
320 template <typename ProdB>
321 template <typename PtrProdAColl, typename DataContainer, typename Tag>
323  PtrProdAColl const& aPtrColl,
324  DataContainer const& dc,
325  Tag const& tag,
326  std::enable_if_t<std::is_same_v<
327  typename PtrProdAColl::value_type,
329 {
330  using ProdA = typename PtrProdAColl::value_type::value_type;
332  dc, detail::input_tag<ProdA, ProdB, void>(tag)};
333  storedException_ = finder(aPtrColl, bCollection_);
334 }
335 
336 template <typename ProdB>
337 template <typename ProdA, typename DataContainer, typename Tag>
339  std::initializer_list<Ptr<ProdA>> const& ptrs,
340  DataContainer const& dc,
341  Tag const& tag)
342 {
344  dc, detail::input_tag<ProdA, ProdB, void>(tag)};
345  storedException_ = finder(ptrs, bCollection_);
346 }
347 
348 template <typename ProdB>
349 inline auto
351 {
352  throwIfInvalid();
353  return bCollection_.size();
354 }
355 
356 template <typename ProdB>
357 inline bool
359 {
360  return storedException_.get() == nullptr;
361 }
362 
363 template <typename ProdB>
364 inline auto
366  ->
367 #ifdef ART_IPR_BY_PTR
368  art::Ptr<assoc_t> const&
369 #else
370  cet::maybe_ref<assoc_t const>
371 #endif
372 {
373  throwIfInvalid();
374 #ifdef ART_IPR_BY_PTR
375  return bCollection_.at(i);
376 #else
377  return cet::maybe_ref<assoc_t const>{*bCollection_.at(i)};
378 #endif
379 }
380 
381 template <typename ProdB>
382 inline void
384 #ifdef ART_IPR_BY_PTR
385  Ptr<assoc_t>& item
386 #else
387  cet::maybe_ref<assoc_t const>& item
388 #endif
389  ) const
390 {
391  throwIfInvalid();
392 #ifdef ART_IPR_BY_PTR
393  item = bCollection_.at(i);
394 #else
395  item.reseat(*bCollection_.at(i));
396 #endif
397 }
398 
399 template <typename ProdB>
400 inline bool
402  FindOne<ProdB, void> const& other) const
403 {
404  throwIfInvalid();
405  return bCollection_ == other.bCollection_;
406 }
407 
408 template <typename ProdB>
409 inline void
411  std::shared_ptr<art::Exception const>&& e)
412 {
413  storedException_ = std::move(e);
414 }
415 
416 template <typename ProdB>
417 inline void
419 {
420  if (!isValid()) {
421  throw Exception(
422  errors::LogicError, "Invalid FindOne", *storedException_)
423  << "Attempt to use a FindOne where the underlying "
424  "art::Assns product was not found.";
425  }
426 }
427 
429 // Derived class implementation.
430 template <typename ProdB, typename Data>
431 template <typename Handle, typename DataContainer, typename Tag>
433  Handle const& aCollection,
434  DataContainer const& dc,
435  Tag const& tag,
436  std::enable_if_t<detail::is_handle_v<Handle>>*)
437 {
438  using ProdA = typename Handle::element_type::value_type;
440  dc, detail::input_tag<ProdA, ProdB, Data>(tag)};
442  finder(*aCollection, base::bCollection(), dataCollection_));
443 }
444 
445 template <typename ProdB, typename Data>
446 template <typename ProdAColl, typename DataContainer, typename Tag>
448  ProdAColl const& view,
449  DataContainer const& dc,
450  Tag const& tag,
451  std::enable_if_t<std::is_pointer_v<typename ProdAColl::value_type>>*)
452 {
453  using ProdA =
454  std::remove_const_t<std::remove_pointer_t<typename ProdAColl::value_type>>;
456  dc, detail::input_tag<ProdA, ProdB, Data>(tag)};
458 }
459 
460 template <typename ProdB, typename Data>
461 template <typename PtrProdAColl, typename DataContainer, typename Tag>
463  PtrProdAColl const& aPtrColl,
464  DataContainer const& dc,
465  Tag const& tag,
466  std::enable_if_t<std::is_same_v<
467  typename PtrProdAColl::value_type,
469 {
470  using ProdA = typename PtrProdAColl::value_type::value_type;
472  dc, detail::input_tag<ProdA, ProdB, Data>(tag)};
474  finder(aPtrColl, base::bCollection(), dataCollection_));
475 }
476 
477 template <typename ProdB, typename Data>
478 template <typename ProdA, typename DataContainer, typename Tag>
480  std::initializer_list<Ptr<ProdA>> const& ptrs,
481  DataContainer const& dc,
482  Tag const& tag)
483 {
485  dc, detail::input_tag<ProdA, ProdB, Data>(tag)};
487 }
488 
489 template <typename ProdB, typename Data>
490 inline cet::maybe_ref<Data const>
492 {
494  return cet::maybe_ref<Data const>{*dataCollection_.at(i)};
495 }
496 
497 template <typename ProdB, typename Data>
498 inline void
500 #ifdef ART_IPR_BY_PTR
501  Ptr<assoc_t>& item,
502 #else
503  cet::maybe_ref<assoc_t const>& item,
504 #endif
505  cet::maybe_ref<Data const>& data) const
506 {
507  base::get(i, item); // Will check validity.
508  data.reseat(*dataCollection_.at(i));
509 }
510 
511 template <typename ProdB, typename Data>
512 inline bool
514 {
515  return this->base::operator==(other) && // Will check validity.
517 }
518 
519 #undef ART_IPR_BY_PTR
520 
521 #endif /* canvas_Persistency_Common_FindOne_h */
522 
523 // Local Variables:
524 // mode: c++
525 // End:
bool isValid() const
Definition: FindOne.h:358
void get(size_type i, cet::maybe_ref< assoc_t const > &item) const
Definition: FindOne.h:383
typename base::size_type size_type
Definition: FindOne.h:226
void get(size_type i, cet::maybe_ref< assoc_t const > &item, cet::maybe_ref< Data const > &data) const
Definition: FindOne.h:499
#define ART_IPR_BY_PTR
Definition: FindManyP.h:133
bool operator==(FindOne< ProdB, Data > const &other) const
Definition: FindOne.h:513
bool operator==(FindOne< ProdB, void > const &other) const
Definition: FindOne.h:401
std::vector< ProdB const * > bColl_t
Definition: FindOne.h:151
typename bColl_t::size_type size_type
Definition: FindOne.h:154
typename base::const_reference const_reference
Definition: FindOne.h:228
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:101
typename base::reference reference
Definition: FindOne.h:229
size_type size() const
Definition: FindOne.h:350
typename bColl_t::value_type value_type
Definition: FindOne.h:153
std::vector< Data const * > dataColl_t
Definition: FindOne.h:224
typename base::assoc_t assoc_t
Definition: FindOne.h:230
dataColl_t dataCollection_
Definition: FindOne.h:286
cet::maybe_ref< assoc_t const > at(size_type i) const
Definition: FindOne.h:365
Data & data_reference
Definition: FindOne.h:234
Data data_t
Definition: FindOne.h:235
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
cet::maybe_ref< Data const > data(size_type i) const
Definition: FindOne.h:491
typename base::value_type value_type
Definition: FindOne.h:225
FindOne(Handle const &aCollection, DataContainer const &dc, Tag const &tag, std::enable_if_t< detail::is_handle_v< Handle >> *=nullptr)
Definition: FindOne.h:432
typename bColl_t::reference reference
Definition: FindOne.h:157
Definition: MVAAlg.h:12
Data const & data_const_reference
Definition: FindOne.h:233
void throwIfInvalid() const
Definition: FindOne.h:418
typename bColl_t::const_reference const_reference
Definition: FindOne.h:156
Float_t e
Definition: plot.C:35
void setStoredException(std::shared_ptr< art::Exception const > &&e)
Definition: FindOne.h:410
typename base::difference_type difference_type
Definition: FindOne.h:227
Definition: fwd.h:26
Data const * data_const_pointer
Definition: FindOne.h:232
typename bColl_t::difference_type difference_type
Definition: FindOne.h:155