LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
Ptr.h
Go to the documentation of this file.
1 #ifndef canvas_Persistency_Common_Ptr_h
2 #define canvas_Persistency_Common_Ptr_h
3 
5 // Ptr and related functions.
6 //
7 // A Ptr is a persistent smart pointer to an item in a collection where
8 // the collection is in the art::Event.
9 //
10 // How to construct a Ptr<T>:
11 //
12 // 1. Default constructor.
13 // Ptr();
14 //
15 // Constructs an invalid Ptr.
16 //
17 // 2. From a handle to a collection and an index into that collection.
18 // template <typename H>
19 // Ptr(H const&, key_type);
20 //
21 // 3. From a ProductID.
22 // Ptr(ProductID); // Invalid ("null") Ptr.
23 //
24 // Ptr(ProductID, key_type, EDProductGetter const*);
25 //
26 // Obtain the ProductID from the collection handle or the result of
27 // Event::put(). Obtain the EDProductGetter from the event using the
28 // ProductID.
29 //
30 // 4. From a Ptr<U> where U is a base or sub class of T.
31 // Ptr(Ptr<U> const&);
32 //
33 // 5. From a ProductID and an existing resolved pointer.
34 // Ptr(ProductID, T const*, key_type)
35 //
36 // This signature is for expert-level or internal use only: it is a
37 // pre-condition that the pointer must be the item at the index
38 // specified in product with the given ID. Errors will *not* be
39 // detected.
40 //
50 #include "cetlib_except/demangle.h"
51 
52 #include <cassert>
53 #include <cstddef>
54 #include <functional> // for std::hash
55 #include <list>
56 #include <ostream>
57 #include <type_traits>
58 #include <vector>
59 
60 namespace art {
61  template <typename T>
62  class Ptr;
63 
64  template <typename T, typename U>
67  bool>
68  operator==(Ptr<T> const& lhs, Ptr<U> const& rhs);
69  template <typename T, typename U>
72  bool>
73  operator!=(Ptr<T> const& lhs, Ptr<U> const& rhs);
74  template <typename T, typename U>
77  bool>
78  operator<(Ptr<T> const& lhs, Ptr<U> const& rhs);
79 
80  // Fill a vector of Ptrs from a persistent collection. Alternatively,
81  // construct a PtrVector.
82  template <typename T, typename H>
83  void fill_ptr_vector(std::vector<Ptr<T>>& ptrs, H const& h);
84 
85  // Fill a list of Ptrs from a persistent collection.
86  template <typename T, typename H>
87  void fill_ptr_list(std::list<Ptr<T>>& ptrs, H const& h);
88 
89  // Specialize EnsurePointer for Ptr.
90  namespace detail {
91  template <typename TO, typename PTRVAL>
92  struct EnsurePointer<TO, Ptr<PTRVAL>>;
93  }
94 
95  template <typename T>
96  std::ostream& operator<<(std::ostream&, Ptr<T> const&);
97 }
98 
99 template <typename T>
100 class art::Ptr {
101 public:
102  typedef std::size_t key_type;
103  typedef T value_type;
104  typedef T const* const_pointer;
105  typedef T const& const_reference;
106 
107  // 1.
108  Ptr() = default;
109 
110  // 2.
111  template <typename H>
112  Ptr(H const& handle, key_type idx);
113 
114  // 3A.
115  explicit Ptr(ProductID const id);
116 
117  // 3B.
118  Ptr(ProductID const productID,
119  key_type itemKey,
120  EDProductGetter const* prodGetter);
121 
122  // 4.
123  template <typename U>
124  Ptr(Ptr<U> const& iOther,
125  std::enable_if_t<std::is_base_of<T, U>::value>* dummy = nullptr);
126 
127  template <typename U>
128  Ptr(Ptr<U> const& iOther,
129  std::enable_if_t<std::is_base_of<U, T>::value>* dummy = nullptr);
130 
131  // 5. See notes above.
132  Ptr(ProductID const productID, T const* item, key_type itemKey);
133 
134  // Accessors.
135  T const& operator*() const;
136  T const* operator->() const;
137  T const* get() const;
138  bool isNull() const; // Checks for valid key.
139  bool isNonnull() const;
140 
141  // Checks if collection is in memory or available
142  // in the event. No type checking is done.
143  bool isAvailable() const;
144 
145  ProductID id() const;
146  key_type key() const;
147  bool hasCache() const;
148  RefCore const& refCore() const;
149 
150  explicit operator bool() const;
151  EDProductGetter const* productGetter() const;
152 
153  // MUST UPDATE WHEN CLASS IS CHANGED!
154  static short
156  {
157  return 10;
158  }
159 
160 private:
161  template <typename C>
162  T const* getItem_(C const* product, key_type iKey);
163  void getData_() const;
164 
165  RefCore core_{};
167 };
168 
169 template <typename TO, typename PTRVAL>
170 struct art::detail::EnsurePointer<TO, art::Ptr<PTRVAL>> {
171  TO operator()(Ptr<PTRVAL>& from) const;
172  TO operator()(Ptr<PTRVAL> const& from) const;
173 };
174 
175 namespace art {
176  namespace detail {
177  // FIXME: The code of ItemGetter, including specializations, would
178  // be completely unnecessary if Handle were to provide access to
179  // the setPtr() function of wrapper. As it is, some
180  // container-specific code is duplicated between here and
181  // art::Wrapper, leading to multiple points of maintenance (and
182  // failure).
183  template <typename T, typename C>
184  class ItemGetter;
185  template <typename T>
186  class ItemGetter<T, cet::map_vector<T>>;
187  template <typename T>
188  class ItemGetter<std::pair<cet::map_vector_key, T>, cet::map_vector<T>>;
189  }
190 }
191 
192 template <typename T, typename C>
194 public:
195  T const* operator()(C const* product, typename Ptr<T>::key_type iKey) const;
196 };
197 
198 template <typename T, typename C>
199 inline T const*
201  typename Ptr<T>::key_type iKey) const
202 {
203  assert(product != nullptr);
204  auto it = product->begin();
205  advance(it, iKey);
206  T const* address = detail::GetProduct<C>::address(it);
207  return address;
208 }
209 
210 template <typename T>
211 class art::detail::ItemGetter<T, cet::map_vector<T>> {
212 public:
213  T const* operator()(cet::map_vector<T> const* product,
214  typename Ptr<T>::key_type iKey) const;
215 };
216 
217 template <typename T>
218 inline T const*
220  cet::map_vector<T> const* product,
221  typename Ptr<T>::key_type iKey) const
222 {
223  assert(product != nullptr);
224  cet::map_vector_key k(iKey);
225  return product->getOrNull(k);
226 }
227 
228 template <typename T>
229 class art::detail::ItemGetter<std::pair<cet::map_vector_key, T>,
230  cet::map_vector<T>> {
231 public:
232  std::pair<cet::map_vector_key, T> const* operator()(
233  cet::map_vector<T> const* product,
234  typename Ptr<T>::key_type iKey) const;
235 };
236 
237 template <typename T>
238 inline std::pair<cet::map_vector_key, T> const*
240 operator()(cet::map_vector<T> const* product,
241  typename Ptr<T>::key_type const iKey) const
242 {
243  assert(product != nullptr);
244  cet::map_vector_key k(static_cast<unsigned>(iKey));
245  auto it = product->find(k);
246  if (it == product->end()) {
247  return nullptr;
248  } else {
249  return &(*it);
250  }
251 }
252 
254 // Ptr implementation.
255 
256 template <typename T>
257 template <typename H>
258 inline art::Ptr<T>::Ptr(H const& handle, typename Ptr<T>::key_type const idx)
259  : core_{handle.id(), getItem_(handle.product(), idx), nullptr}, key_{idx}
260 {
261  if (core_.isNull()) {
263  << "Attempt to construct a Ptr from a Handle with invalid ProductID. "
264  "Perhaps a\ndefault-constructed Ptr is what you want?";
265  }
266 }
267 
268 template <typename T>
269 inline art::Ptr<T>::Ptr(ProductID const productID)
270  : core_{productID, 0, nullptr}, key_{key_traits<key_type>::value}
271 {}
272 
273 template <typename T>
274 inline art::Ptr<T>::Ptr(ProductID const productID,
275  key_type const itemKey,
276  EDProductGetter const* prodGetter)
277  : core_{productID, 0, prodGetter}, key_{itemKey}
278 {}
279 
280 template <typename T>
281 template <typename U>
282 inline art::Ptr<T>::Ptr(Ptr<U> const& iOther,
283  std::enable_if_t<std::is_base_of<T, U>::value>*)
284  : core_(iOther.id(),
285  (iOther.hasCache() ? static_cast<T const*>(iOther.get()) :
286  static_cast<T const*>(nullptr)),
287  iOther.productGetter())
288  , key_{iOther.key()}
289 {}
290 
291 template <typename T>
292 template <typename U>
293 inline art::Ptr<T>::Ptr(Ptr<U> const& iOther,
294  std::enable_if_t<std::is_base_of<U, T>::value>*)
295  : core_{iOther.id(), dynamic_cast<T const*>(iOther.get()), nullptr}
296  , key_{iOther.key()}
297 {}
298 
299 template <typename T>
300 inline art::Ptr<T>::Ptr(ProductID const productID,
301  T const* item,
302  key_type const itemKey)
303  : core_{productID, item, nullptr}, key_{itemKey}
304 {}
305 
306 template <typename T>
307 inline T const& art::Ptr<T>::operator*() const
308 {
309  return *get();
310 }
311 
312 template <typename T>
313 inline T const* art::Ptr<T>::operator->() const
314 {
315  getData_();
316  return reinterpret_cast<T const*>(core_.productPtr());
317 }
318 
319 template <typename T>
320 inline T const*
322 {
323  return isNull() ? nullptr : this->operator->();
324 }
325 
326 template <typename T>
327 inline bool
329 {
330  return !isNonnull();
331 }
332 
333 template <typename T>
334 inline bool
336 {
338 }
339 
340 template <typename T>
341 inline bool
343 {
344  return core_.isAvailable();
345 }
346 
347 template <typename T>
348 inline auto
350 {
351  return core_.id();
352 }
353 
354 template <typename T>
355 inline auto
357 {
358  return key_;
359 }
360 
361 template <typename T>
362 inline bool
364 {
365  return nullptr != core_.productPtr();
366 }
367 
368 template <typename T>
369 inline auto
370 art::Ptr<T>::refCore() const -> RefCore const&
371 {
372  return core_;
373 }
374 
375 template <typename T>
376 inline art::Ptr<T>::operator bool() const
377 {
378  return isNonnull() && isAvailable();
379 }
380 
381 template <typename T>
382 inline auto
384 {
385  return core_.productGetter();
386 }
387 
388 template <typename T>
389 template <typename C>
390 inline T const*
391 art::Ptr<T>::getItem_(C const* product, key_type iKey)
392 {
393  return detail::ItemGetter<T, C>()(product, iKey);
394 }
395 
396 template <typename T>
397 void
399 {
400  if (!hasCache()) {
401  EDProduct const* prod =
402  productGetter() ? productGetter()->getIt() : nullptr;
403  if (prod == nullptr) {
405  e << "A request to resolve an art::Ptr to a product containing items of "
406  "type: "
407  << cet::demangle_symbol(typeid(T).name()) << " with ProductID "
408  << core_.id()
409  << "\ncannot be satisfied because the product cannot be found.\n";
410  if (productGetter() == nullptr) {
411  e << "The productGetter was not set -- are you trying to dereference a "
412  "Ptr during mixing?\n";
413  } else {
414  e << "Probably the branch containing the product is not stored in the "
415  "input file.\n";
416  }
417  throw e;
418  }
419  void const* ad = nullptr;
420  prod->setPtr(typeid(T), key_, ad);
421  core_.setProductPtr(ad);
422  }
423 }
424 
425 template <typename T, typename U>
426 inline auto
427 art::operator==(Ptr<T> const& lhs, Ptr<U> const& rhs)
431  bool>
432 {
433  return lhs.refCore() == rhs.refCore() && lhs.key() == rhs.key();
434 }
435 
436 template <typename T, typename U>
437 inline auto
438 art::operator!=(Ptr<T> const& lhs, Ptr<U> const& rhs)
442  bool>
443 {
444  return !(lhs == rhs);
445 }
446 
447 template <typename T, typename U>
448 inline auto
449 art::operator<(Ptr<T> const& lhs, Ptr<U> const& rhs)
450  -> std::enable_if_t<std::is_same<T, U>::value ||
453  bool>
454 {
455  // The ordering of integer keys guarantees that the ordering of Ptrs within
456  // a collection will be identical to the ordering of the referenced objects in
457  // the collection.
458  return (lhs.refCore() == rhs.refCore() ? lhs.key() < rhs.key() :
459  lhs.refCore() < rhs.refCore());
460 }
461 
462 template <typename T, typename H>
463 void
465 {
466  for (std::size_t i = 0, sz = h->size(); i != sz; ++i) {
467  ptrs.emplace_back(h, i);
468  }
469 }
470 
471 template <typename T, typename H>
472 void
473 art::fill_ptr_list(std::list<Ptr<T>>& ptrs, H const& h)
474 {
475  for (std::size_t i = 0, sz = h->size(); i != sz; ++i) {
476  ptrs.emplace_back(h, i);
477  }
478 }
479 
480 template <typename TO, typename PTRVAL>
481 TO
483  Ptr<PTRVAL>& from) const
484 {
485  return detail::addr<TO, PTRVAL const>(*from);
486 }
487 
488 template <typename TO, typename PTRVAL>
489 TO
491  Ptr<PTRVAL> const& from) const
492 {
493  return detail::addr<TO, PTRVAL const>(*from);
494 }
495 
496 template <typename T>
497 std::ostream&
498 art::operator<<(std::ostream& os, Ptr<T> const& p)
499 {
500  os << "(" << p.id() << ", " << p.key() << ")";
501  return os;
502 }
503 
504 // Specialization of std::hash for art::Ptr
505 namespace std {
506  template <class T>
507  struct hash<art::Ptr<T>> {
509  using key_t = typename ptr_t::key_type;
510 
511  size_t
512  operator()(ptr_t const& p) const
513  {
514  return std::hash<art::ProductID>()(p.id()) ^ std::hash<key_t>()(p.key());
515  }
516  };
517 }
518 
519 #endif /* canvas_Persistency_Common_Ptr_h */
520 
521 // Local Variables:
522 // mode: c++
523 // End:
key_type key() const
Definition: Ptr.h:356
virtual EDProduct const * getIt() const =0
RefCore core_
Definition: Ptr.h:165
bool isNonnull() const
Definition: Ptr.h:335
Ptr()=default
EDProductGetter const * productGetter() const
Definition: Ptr.h:383
static element_type const * address(iter const &i)
Definition: GetProduct.h:11
STL namespace.
key_type key_
Definition: Ptr.h:166
bool isAvailable() const
Definition: RefCore.cc:15
bool operator!=(debugging_allocator< X > const &, debugging_allocator< Y > const &)
T const * operator->() const
Definition: Ptr.h:313
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
EDProductGetter const * productGetter() const
Definition: RefCore.h:105
RefCore const & refCore() const
Definition: Ptr.h:370
bool hasCache() const
Definition: Ptr.h:363
T const & operator*() const
Definition: Ptr.h:307
typename ptr_t::key_type key_t
Definition: Ptr.h:509
T const * getItem_(C const *product, key_type iKey)
Definition: Ptr.h:391
ProductID id() const
Definition: Ptr.h:349
void getData_() const
Definition: Ptr.h:398
T value_type
Definition: Ptr.h:103
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
void const * productPtr() const
Definition: RefCore.h:99
void fill_ptr_list(std::list< Ptr< T >> &ptrs, H const &h)
Definition: Ptr.h:473
ProductID id() const
Definition: RefCore.h:93
bool isNull() const
Definition: RefCore.h:82
std::string value(boost::any const &)
T const * get() const
Definition: Ptr.h:321
T const * operator()(C const *product, typename Ptr< T >::key_type iKey) const
Definition: Ptr.h:200
static short Class_Version()
Definition: Ptr.h:155
bool isAvailable() const
Definition: Ptr.h:342
std::size_t key_type
Definition: Ptr.h:102
HLT enums.
bool isNull() const
Definition: Ptr.h:328
size_t operator()(ptr_t const &p) const
Definition: Ptr.h:512
void fill_ptr_vector(std::vector< Ptr< T >> &ptrs, H const &h)
Definition: Ptr.h:464
bool operator==(Provenance const &a, Provenance const &b)
Definition: Provenance.h:168
Float_t e
Definition: plot.C:34
QuadExpr operator*(double v, const QuadExpr &e)
Definition: QuadExpr.h:39
Definition: fwd.h:25
void setPtr(std::type_info const &toType, unsigned long index, void const *&ptr) const
Definition: EDProduct.cc:15
T const & const_reference
Definition: Ptr.h:105
T const * const_pointer
Definition: Ptr.h:104
void setProductPtr(void const *prodPtr) const
Definition: RefCore.h:111