LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
ProductPtr.h
Go to the documentation of this file.
1 #ifndef canvas_Persistency_Common_ProductPtr_h
2 #define canvas_Persistency_Common_ProductPtr_h
3 // vim: set sw=2 expandtab :
4 
5 //
6 // ProductPtr and related functions.
7 //
8 // A ProductPtr is a persistent smart pointer to a data product.
9 //
10 // How to construct a ProductPtr<T>:
11 //
12 // 1. Default constructor.
13 // ProductPtr();
14 //
15 // Constructs an invalid ProductPtr.
16 //
17 // 2. From a handle to a product.
18 // template<typename H>
19 // ProductPtr(H const&);
20 //
21 // 3. From a ProductID.
22 // ProductPtr(Product ID const&, EDProductGetter const*);
23 //
24 // Obtain the ProductID from the handle or the result of
25 // Event::put(). Obtain the EDProductGetter from the event using
26 // the ProductID.
27 //
28 // 4. From a ProductPtr<U> where U is a base or sub class of T.
29 // ProductPtr(ProductPtr<U> const&);
30 //
31 
38 #include "cetlib_except/demangle.h"
39 
40 #include <cstddef>
41 #include <ostream>
42 #include <type_traits>
43 
44 namespace art {
45 
46  template <typename T>
47  class ProductPtr {
48  public:
49  using value_type = T;
50  using const_pointer = T const*;
51  using const_reference = T const&;
52 
53  // 1.
54  ProductPtr() = default;
55 
56  template <typename H>
57  explicit ProductPtr(H const& handle)
58  : core_{handle.id(), handle.product(), nullptr}
59  {
60  if (core_.isNull()) {
62  << "Attempt to construct a ProductPtr from a Handle with invalid "
63  "ProductID. "
64  "Perhaps a\n"
65  "default-constructed ProductPtr is what you want?";
66  }
67  }
68 
69  // 3.
70  ProductPtr(ProductID const& productID, EDProductGetter const* prodGetter)
71  : core_{productID, nullptr, prodGetter}
72  {}
73 
74  // 4.
75  template <typename U>
77  std::enable_if_t<std::is_base_of_v<T, U>>* = nullptr)
78  : core_{pu.id(),
79  (pu.hasCache() ? static_cast<T const*>(pu.get()) : nullptr),
80  pu.productGetter()}
81  {}
82 
83  template <typename U>
85  std::enable_if_t<std::is_base_of_v<U, T>>* = nullptr)
86  : core_{pu.id(), static_cast<T const*>(pu.get()), nullptr}
87  {}
88 
89  //
90  // Accessors.
91  //
92 
93  T const&
94  operator*() const
95  {
96  // Warning: This causes a nullptr dereference if isNull!
97  return *get();
98  }
99 
100  T const*
101  get() const
102  {
103  return core_.isNull() ? nullptr : operator->();
104  }
105 
106  T const*
107  operator->() const
108  {
109  if (core_.productPtr() == nullptr) {
111  }
112  return reinterpret_cast<T const*>(core_.productPtr());
113  }
114 
115  explicit operator bool() const { return core_.isAvailable(); }
116 
117  RefCore const&
118  refCore() const noexcept
119  {
120  return core_;
121  }
122 
123  ProductID
124  id() const noexcept
125  {
126  return core_.id();
127  }
128 
129  EDProductGetter const*
130  productGetter() const noexcept
131  {
132  return core_.productGetter();
133  }
134 
135  // Checks if collection is in memory or available
136  // in the event. No type checking is done.
137  bool
138  isAvailable() const
139  {
140  return core_.isAvailable();
141  }
142 
143  bool
144  hasCache() const noexcept
145  {
146  return core_.productPtr() != nullptr;
147  }
148 
149  // MUST UPDATE WHEN CLASS IS CHANGED!
150  static constexpr short
151  Class_Version() noexcept
152  {
153  return 10;
154  }
155 
156  private:
157  T const*
158  product_() const
159  {
160  EDProduct const* product{nullptr};
161  if (productGetter()) {
162  product = productGetter()->getIt();
163  }
164  if (product == nullptr) {
166  e << "A request to resolve a ProductPtr to a product of type: "
167  << cet::demangle_symbol(typeid(T).name()) << " with ProductID "
168  << core_.id()
169  << "\ncannot be satisfied because the product cannot be found.\n";
170  if (productGetter() == nullptr) {
171  e << "The productGetter was not set -- are you trying to "
172  "dereference a ProductPtr during mixing?\n";
173  } else {
174  e << "Probably the branch containing the product is not stored in "
175  "the input file.\n";
176  }
177  throw e;
178  }
179  auto wrapped_product = dynamic_cast<Wrapper<T> const*>(product);
180  if (wrapped_product == nullptr) {
182  << "A request to resolve a Product Ptr to a product of type: "
183  << cet::demangle_symbol(typeid(T).name()) << " with ProductID"
184  << core_.id() << "\ncannot be satisfied due to a type mismatch.\n";
185  }
186  return wrapped_product->product();
187  }
188 
189  // Used to fetch the container product.
191  };
192 
193  // Deduction guide for handles
194  template <typename H>
196 
197  template <typename T, typename U>
198  std::enable_if_t<std::is_same_v<T, U> || std::is_base_of_v<T, U> ||
199  std::is_base_of_v<U, T>,
200  bool>
201  operator==(ProductPtr<T> const& lhs, ProductPtr<U> const& rhs)
202  {
203  return lhs.refCore() == rhs.refCore();
204  }
205 
206  template <typename T, typename U>
207  std::enable_if_t<std::is_same_v<T, U> || std::is_base_of_v<T, U> ||
208  std::is_base_of_v<U, T>,
209  bool>
210  operator!=(ProductPtr<T> const& lhs, ProductPtr<U> const& rhs)
211  {
212  return !(lhs == rhs);
213  }
214 
215  template <typename T, typename U>
216  std::enable_if_t<std::is_same_v<T, U> || std::is_base_of_v<T, U> ||
217  std::is_base_of_v<U, T>,
218  bool>
219  operator<(ProductPtr<T> const& lhs, ProductPtr<U> const& rhs)
220  {
221  return lhs.refCore() < rhs.refCore();
222  }
223 
224  template <typename T>
225  std::ostream&
226  operator<<(std::ostream& os, ProductPtr<T> const& p)
227  {
228  os << "(" << p.id() << ")";
229  return os;
230  }
231 
232 } // namespace art
233 
234 #endif /* canvas_Persistency_Common_ProductPtr_h */
235 
236 // Local Variables:
237 // mode: c++
238 // End:
EDProduct const * getIt() const
EDProductGetter const * productGetter() const noexcept
Definition: RefCore.cc:41
ProductPtr(H) -> ProductPtr< typename H::element_type >
bool operator==(Provenance const &a, Provenance const &b) noexcept
Definition: Provenance.cc:141
bool isAvailable() const
Definition: ProductPtr.h:138
ProductPtr(ProductPtr< U > const &pu, std::enable_if_t< std::is_base_of_v< T, U >> *=nullptr)
Definition: ProductPtr.h:76
T const * const_pointer
Definition: ProductPtr.h:50
ProductPtr(H const &handle)
Definition: ProductPtr.h:57
ProductPtr()=default
bool isAvailable() const
Definition: RefCore.cc:24
bool operator!=(ScheduleID const left, ScheduleID const right) noexcept
Definition: ScheduleID.cc:41
T const & operator*() const
Definition: ProductPtr.h:94
ProductPtr(ProductID const &productID, EDProductGetter const *prodGetter)
Definition: ProductPtr.h:70
constexpr bool isNull() const noexcept
Definition: RefCore.h:33
T const & const_reference
Definition: ProductPtr.h:51
T const * product_() const
Definition: ProductPtr.h:158
bool hasCache() const noexcept
Definition: ProductPtr.h:144
EDProductGetter const * productGetter() const noexcept
Definition: ProductPtr.h:130
static constexpr short Class_Version() noexcept
Definition: ProductPtr.h:151
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
RefCore const & refCore() const noexcept
Definition: ProductPtr.h:118
void const * productPtr() const noexcept
Definition: RefCore.cc:34
Definition: MVAAlg.h:12
void setProductPtr(void const *prodPtr) const noexcept
Definition: RefCore.cc:48
constexpr ProductID id() const noexcept
Definition: RefCore.h:50
ProductID id() const noexcept
Definition: ProductPtr.h:124
T const * operator->() const
Definition: ProductPtr.h:107
Float_t e
Definition: plot.C:35
ProductPtr(ProductPtr< U > const &pu, std::enable_if_t< std::is_base_of_v< U, T >> *=nullptr)
Definition: ProductPtr.h:84