LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
Handle.h
Go to the documentation of this file.
1 #ifndef art_Framework_Principal_Handle_h
2 #define art_Framework_Principal_Handle_h
3 
4 // ======================================================================
5 //
6 // Handle: Non-owning "smart pointer" for reference to EDProducts and
7 // their Provenances.
8 //
9 // ValidHandle: A Handle that can not be invalid, and thus does not check
10 // for validity upon dereferencing.
11 //
12 // If the pointed-to EDProduct or Provenance is destroyed, use of the
13 // Handle becomes undefined. There is no way to query the Handle to
14 // discover if this has happened.
15 //
16 // Handles can have:
17 // -- Product and Provenance pointers both null;
18 // -- Both pointers valid
19 //
20 // ValidHandles must have Product and Provenance pointers valid.
21 //
22 // To check validity, one can use the Handle::isValid() function.
23 // ValidHandles cannot be invalid, and so have no validity checks.
24 //
25 // If failedToGet() returns true then the requested data is not available
26 // If failedToGet() returns false but isValid() is also false then no
27 // attempt to get data has occurred
28 //
29 // ======================================================================
30 
37 #include "cetlib_except/demangle.h"
38 #include "cetlib_except/exception.h"
39 
40 #include <memory>
41 #include <typeinfo>
42 
43 namespace art {
44  // defined herein:
45  template <typename T>
46  class Handle;
47  template <typename T>
48  class ValidHandle;
49  template <class T>
50  void swap(Handle<T>& a, Handle<T>& b);
51  template <class T>
52  void swap(ValidHandle<T>& a, ValidHandle<T>& b);
53  template <class T>
55 
56  // forward declarations:
57  class EDProduct;
58  template <typename T>
59  class Wrapper;
60 
61  namespace detail {
62  inline void
63  throw_if_invalid(std::string const&)
64  {}
65 
66  template <typename H, typename... T>
67  void
68  throw_if_invalid(std::string const& msg, H const& h, T const&... t)
69  {
70  if (!h.isValid())
71  throw Exception{art::errors::NullPointerError} << msg << '\n';
72  throw_if_invalid(msg, t...);
73  }
74  }
75 
76  template <class T>
78  range_of_validity(T const& h);
79 
80  template <class T, class U>
82  T const& a,
83  U const& b);
84 
85  template <class T, class U>
87  T const& a,
88  U const& b);
89 
90  template <class T, class U>
92  T const& a,
93  U const& b);
94 }
95 
96 // ======================================================================
97 
98 template <typename T>
99 class art::Handle {
100 public:
101  using element_type = T;
102  class HandleTag {
103  };
104 
105  // c'tors:
106  explicit constexpr Handle() =
107  default; // Default-constructed handles are invalid.
108  explicit Handle(GroupQueryResult const&);
109 
110  // pointer behaviors:
111  T const& operator*() const;
112  T const* operator->() const; // alias for product()
113  T const* product() const;
114 
115  // inspectors:
116  bool isValid() const;
117  bool failedToGet()
118  const; // was Handle used in a 'get' call whose data could not be found?
119  Provenance const* provenance() const;
120  ProductID id() const;
121  std::shared_ptr<art::Exception const> whyFailed() const;
122 
123  // mutators:
124  void swap(Handle<T>& other);
125  void clear();
126 
127 private:
128  T const* prod_{nullptr};
129  Provenance prov_{};
130  std::shared_ptr<art::Exception const> whyFailed_{nullptr};
131 }; // Handle<>
132 
133 // ----------------------------------------------------------------------
134 // c'tors:
135 
136 template <class T>
138  : prod_{nullptr}, prov_{gqr.result()}, whyFailed_{gqr.whyFailed()}
139 {
140  if (gqr.succeeded()) {
141  auto const wrapperPtr = dynamic_cast<Wrapper<T> const*>(
142  gqr.result()->uniqueProduct(TypeID{typeid(Wrapper<T>)}));
143  if (wrapperPtr == nullptr) {
145  e << "Product retrieval via Handle<T> succeeded for product:\n"
147  << "but an attempt to interpret it as an object of type '"
148  << cet::demangle_symbol(typeid(T).name()) << "' failed.\n";
149  whyFailed_ = std::make_shared<art::Exception const>(std::move(e));
150  } else {
151  prod_ = wrapperPtr->product();
152  }
153  }
154 }
155 
156 // ----------------------------------------------------------------------
157 // pointer behaviors:
158 
159 template <class T>
160 inline T const& art::Handle<T>::operator*() const
161 {
162  return *product();
163 }
164 
165 template <class T>
166 T const*
168 {
169  if (failedToGet())
170  throw *whyFailed_;
171 
172  if (prod_ == nullptr)
174  << "Attempt to de-reference product that points to 'nullptr'";
175 
176  return prod_;
177 }
178 
179 template <class T>
180 inline T const* art::Handle<T>::operator->() const
181 {
182  return product();
183 }
184 
185 // ----------------------------------------------------------------------
186 // inspectors:
187 
188 template <class T>
189 bool
191 {
192  return prod_ && prov_.isValid();
193 }
194 
195 template <class T>
196 bool
198 {
199  return whyFailed_.get();
200 }
201 
202 template <class T>
203 inline art::Provenance const*
205 {
206  return &prov_;
207 }
208 
209 template <class T>
210 inline art::ProductID
212 {
213  // FIXME: returning prov_.productID() should be sufficient since
214  // ProductID{} is invalid anyway.
215  return prov_.isValid() ? prov_.productID() : ProductID{};
216 }
217 
218 template <class T>
219 inline std::shared_ptr<art::Exception const>
221 {
222  return whyFailed_;
223 }
224 
225 // ----------------------------------------------------------------------
226 // mutators:
227 
228 template <class T>
229 void
231 {
232  std::swap(*this, other);
233 }
234 
235 template <class T>
236 void
238 {
239  Handle<T> tmp;
240  swap(tmp);
241 }
242 
243 // ======================================================================
244 // Non-members:
245 
246 // Convert from handle-to-EDProduct to handle-to-T
247 template <class T>
248 void
250 {
251  Handle<T> h{orig};
252  result.swap(h);
253 }
254 
255 // ======================================================================
256 template <typename T>
257 class art::ValidHandle {
258 public:
259  typedef T element_type;
260  class HandleTag {
261  };
262 
263  ValidHandle() = delete;
264  explicit ValidHandle(T const* prod, Provenance prov);
265 
266  ValidHandle(ValidHandle const&) = default;
267  ValidHandle& operator=(ValidHandle const&) & = default;
268 
269  // pointer behaviors
270  operator T const*() const; // conversion to T const*
271  T const& operator*() const;
272  T const* operator->() const; // alias for product()
273  T const* product() const;
274 
275  // inspectors
276  bool isValid() const; // always true
277  bool failedToGet() const; // always false
278  Provenance const* provenance() const;
279  ProductID id() const;
280  std::shared_ptr<art::Exception const> whyFailed() const; // always null
281 
282  // mutators
283  void swap(ValidHandle<T>& other);
284  // No clear() function, because a ValidHandle may not have an invalid
285  // state, and that is what clear() would obtain.
286 
287 private:
288  T const* prod_;
290 };
291 
292 template <class T>
294  : prod_{prod}, prov_{prov}
295 {
296  if (prod == nullptr)
298  << "Attempt to create ValidHandle with null pointer";
299 }
300 
301 template <class T>
302 inline art::ValidHandle<T>::operator T const*() const
303 {
304  return prod_;
305 }
306 
307 template <class T>
308 inline T const& art::ValidHandle<T>::operator*() const
309 {
310  return *prod_;
311 }
312 
313 template <class T>
314 inline T const* art::ValidHandle<T>::operator->() const
315 {
316  return prod_;
317 }
318 
319 template <class T>
320 inline T const*
322 {
323  return prod_;
324 }
325 
326 template <class T>
327 inline bool
329 {
330  return true;
331 }
332 
333 template <class T>
334 inline bool
336 {
337  return false;
338 }
339 
340 template <class T>
341 inline art::Provenance const*
343 {
344  return &prov_;
345 }
346 
347 template <class T>
348 inline art::ProductID
350 {
351  return prov_.productID();
352 }
353 
354 template <class T>
355 inline std::shared_ptr<art::Exception const>
357 {
358  return std::shared_ptr<art::Exception const>();
359 }
360 
361 template <class T>
362 inline void
364 {
365  std::swap(*this, other);
366 }
367 
368 // ======================================================================
369 // Non-members:
370 
371 template <class T>
373 art::range_of_validity(T const& h)
374 {
375  std::string const& errMsg =
376  "Attempt to retrieve range set from invalid handle.";
377  detail::throw_if_invalid(errMsg, h);
378  return h.provenance()->rangeOfValidity();
379 }
380 
381 template <class T, class U>
383 art::same_ranges(T const& a, U const& b)
384 {
385  std::string const& errMsg =
386  "Attempt to compare range sets where one or both handles are invalid.";
387  detail::throw_if_invalid(errMsg, a, b);
389 }
390 
391 template <class T, class U>
393 art::disjoint_ranges(T const& a, U const& b)
394 {
395  std::string const& errMsg =
396  "Attempt to compare range sets where one or both handles are invalid.";
397  detail::throw_if_invalid(errMsg, a, b);
399 }
400 
401 template <class T, class U>
403 art::overlapping_ranges(T const& a, U const& b)
404 {
405  std::string const& errMsg =
406  "Attempt to compare range sets where one or both handles are invalid.";
407  detail::throw_if_invalid(errMsg, a, b);
409 }
410 
411 #endif /* art_Framework_Principal_Handle_h */
412 
413 // Local Variables:
414 // mode: c++
415 // End:
Provenance prov_
Definition: Handle.h:289
std::enable_if_t< detail::is_handle< T >::value, RangeSet const & > range_of_validity(T const &h)
T const * prod_
Definition: Handle.h:128
void throw_if_invalid(std::string const &)
Definition: Handle.h:63
std::shared_ptr< art::Exception const > whyFailed_
Definition: Handle.h:130
void swap(Handle< T > &other)
Definition: Handle.h:230
T const & operator*() const
Definition: Handle.h:308
Float_t tmp
Definition: plot.C:37
bool isValid() const
Definition: Provenance.h:120
T const * product() const
Definition: Handle.h:321
ProductID const & productID() const
Definition: Provenance.h:113
ValidHandle()=delete
bool isValid() const
Definition: Handle.h:190
T const * product() const
Definition: Handle.h:167
ProductID id() const
Definition: Handle.h:349
void swap(Handle< T > &a, Handle< T > &b)
Provenance const * provenance() const
Definition: Handle.h:204
T const * operator->() const
Definition: Handle.h:314
void convert_handle(GroupQueryResult const &, Handle< T > &)
Definition: Handle.h:249
art::art::TriggerResults element_type
Definition: Handle.h:101
std::enable_if_t< detail::are_handles< T, U >::value, bool > disjoint_ranges(T const &a, U const &b)
Provenance const * provenance() const
Definition: Handle.h:342
constexpr Handle()=default
Provenance prov_
Definition: Handle.h:129
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
std::string value(boost::any const &)
T const * operator->() const
Definition: Handle.h:180
void swap(ValidHandle< T > &a, ValidHandle< T > &b)
T const & operator*() const
Definition: Handle.h:160
T const * prod_
Definition: Handle.h:288
void clear()
Definition: Handle.h:237
std::enable_if_t< detail::are_handles< T, U >::value, bool > overlapping_ranges(T const &a, U const &b)
std::enable_if_t< detail::are_handles< T, U >::value, bool > same_ranges(T const &a, U const &b)
HLT enums.
bool failedToGet() const
Definition: Handle.h:335
std::shared_ptr< art::Exception const > whyFailed() const
Definition: Handle.h:356
std::shared_ptr< art::Exception const > whyFailed() const
Definition: Handle.h:220
BranchDescription const & productDescription() const
Definition: Provenance.h:46
Float_t e
Definition: plot.C:34
QuadExpr operator*(double v, const QuadExpr &e)
Definition: QuadExpr.h:39
ProductID id() const
Definition: Handle.h:211
void swap(ValidHandle< T > &other)
Definition: Handle.h:363
vec_iX clear()
bool failedToGet() const
Definition: Handle.h:197
bool isValid() const
Definition: Handle.h:328