Handle.h
Go to the documentation of this file.
1 #ifndef art_Framework_Principal_Handle_h
2 #define art_Framework_Principal_Handle_h
3 // vim: set sw=2 expandtab :
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, the art::Handle is implicitly convertible to
23 // bool. One can also use the Handle::isValid() function.
24 // ValidHandles cannot be invalid, and so have no validity checks.
25 //
26 // If failedToGet() returns true then the requested data is not available
27 // If failedToGet() returns false but isValid() is also false then no
28 // attempt to get data has occurred
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 
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>
53  template <class T>
55 
56  class EDProduct;
57  template <typename T>
58  class Wrapper;
59 
60  namespace detail {
61  template <typename... T>
62  void
63  throw_if_invalid(std::string const& msg, T const&... t)
64  {
65  bool const all_valid = true && (... && t.isValid());
66  if (!all_valid) {
67  throw Exception{art::errors::NullPointerError} << msg << '\n';
68  }
69  }
70  } // namespace detail
71 
72  template <class T>
74  range_of_validity(T const& h);
75  template <class T, class U>
77  T const& a,
78  U const& b);
79  template <class T, class U>
81  T const& a,
82  U const& b);
83  template <class T, class U>
85  T const& a,
86  U const& b);
87 
88 } // namespace art
89 
90 template <typename T>
91 class art::Handle {
92 public:
93  using element_type = T;
94  class HandleTag {};
95 
96  ~Handle() = default;
97  explicit constexpr Handle() =
98  default; // Default-constructed handles are invalid.
99  explicit Handle(GroupQueryResult const&);
100  Handle(Handle const&) = default;
101  Handle(Handle&&) = default;
102  Handle& operator=(Handle const&) = default;
103  Handle& operator=(Handle&&) = default;
104 
105  // pointer behaviors:
106  T const& operator*() const;
107  T const* operator->() const; // alias for product()
108  T const* product() const;
109 
110  // inspectors:
111  explicit operator bool() const noexcept;
112  bool isValid() const noexcept;
113  bool failedToGet()
114  const; // was Handle used in a 'get' call whose data could not be found?
115  Provenance const* provenance() const;
116  ProductID id() const;
117  std::shared_ptr<art::Exception const> whyFailed() const;
118 
119  // mutators:
120  void swap(Handle<T>& other);
121  void clear();
122 
123 private:
124  T const* prod_{nullptr};
125  Provenance prov_{};
126  std::shared_ptr<art::Exception const> whyFailed_{nullptr};
127 }; // Handle<>
128 
129 // ----------------------------------------------------------------------
130 // c'tors:
131 
132 template <class T>
134  : prod_{nullptr}, prov_{gqr.result()}, whyFailed_{gqr.whyFailed()}
135 {
136  if (gqr.succeeded()) {
137  auto const wrapperPtr = dynamic_cast<Wrapper<T> const*>(
138  gqr.result()->uniqueProduct(TypeID{typeid(Wrapper<T>)}));
139  if (wrapperPtr != nullptr) {
140  prod_ = wrapperPtr->product();
141  } else {
143  e << "Product retrieval via Handle<T> succeeded for product:\n"
145  << "but an attempt to interpret it as an object of type '"
146  << cet::demangle_symbol(typeid(T).name()) << "' failed.\n";
147  whyFailed_ = std::make_shared<art::Exception const>(std::move(e));
148  }
149  }
150 }
151 
152 // ----------------------------------------------------------------------
153 // pointer behaviors:
154 
155 template <class T>
156 inline T const& art::Handle<T>::operator*() const
157 {
158  return *product();
159 }
160 
161 template <class T>
162 T const*
164 {
165  if (failedToGet()) {
166  throw *whyFailed_;
167  }
168  if (prod_ == nullptr)
170  << "Attempt to de-reference product that points to 'nullptr'.\n";
171  return prod_;
172 }
173 
174 template <class T>
175 inline T const* art::Handle<T>::operator->() const
176 {
177  return product();
178 }
179 
180 // ----------------------------------------------------------------------
181 // inspectors:
182 
183 template <class T>
185 {
186  return isValid();
187 }
188 
189 template <class T>
190 bool
192 {
193  return prod_ && prov_.isValid();
194 }
195 
196 template <class T>
197 bool
199 {
200  return whyFailed_.get();
201 }
202 
203 template <class T>
204 inline art::Provenance const*
206 {
207  return &prov_;
208 }
209 
210 template <class T>
211 inline art::ProductID
213 {
214  return prov_.isValid() ? prov_.productID() : ProductID{};
215 }
216 
217 template <class T>
218 inline std::shared_ptr<art::Exception const>
220 {
221  return whyFailed_;
222 }
223 
224 // ----------------------------------------------------------------------
225 // mutators:
226 
227 template <class T>
228 void
230 {
231  std::swap(*this, other);
232 }
233 
234 template <class T>
235 void
237 {
238  Handle<T> tmp;
239  swap(tmp);
240 }
241 
242 // ======================================================================
243 // Non-members:
244 
245 // Convert from handle-to-EDProduct to handle-to-T
246 template <class T>
247 void
249 {
250  Handle<T> h{orig};
251  result.swap(h);
252 }
253 
254 // ======================================================================
255 template <typename T>
256 class art::ValidHandle {
257 public:
258  typedef T element_type;
259  class HandleTag {};
260 
261  ~ValidHandle() = default;
262  ValidHandle() = delete;
263  explicit ValidHandle(T const* prod, Provenance prov);
264  ValidHandle(ValidHandle const&) = default;
265  ValidHandle(ValidHandle&&) = default;
266  ValidHandle& operator=(ValidHandle const&) & = default;
267  ValidHandle& operator=(ValidHandle&&) & = 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 
285  // No clear() function, because a ValidHandle does not have an invalid
286  // state, and that is what the result of clear() would have to be.
287 
288 private:
289  T const* prod_;
291 };
292 
293 template <class T>
295  : prod_{prod}, prov_{prov}
296 {
297  if (prod == nullptr) {
299  << "Attempt to create ValidHandle with null pointer";
300  }
301 }
302 
303 template <class T>
304 inline art::ValidHandle<T>::operator T const*() const
305 {
306  return prod_;
307 }
308 
309 template <class T>
310 inline T const& art::ValidHandle<T>::operator*() const
311 {
312  return *prod_;
313 }
314 
315 template <class T>
316 inline T const* art::ValidHandle<T>::operator->() const
317 {
318  return prod_;
319 }
320 
321 template <class T>
322 inline T const*
324 {
325  return prod_;
326 }
327 
328 template <class T>
329 inline bool
331 {
332  return true;
333 }
334 
335 template <class T>
336 inline bool
338 {
339  return false;
340 }
341 
342 template <class T>
343 inline art::Provenance const*
345 {
346  return &prov_;
347 }
348 
349 template <class T>
350 inline art::ProductID
352 {
353  return prov_.productID();
354 }
355 
356 template <class T>
357 inline std::shared_ptr<art::Exception const>
359 {
360  return std::shared_ptr<art::Exception const>();
361 }
362 
363 template <class T>
364 inline void
366 {
367  std::swap(*this, other);
368 }
369 
370 // ======================================================================
371 // Non-members:
372 
373 template <class T>
375 art::range_of_validity(T const& h)
376 {
377  std::string const& errMsg =
378  "Attempt to retrieve range set from invalid handle.";
379  detail::throw_if_invalid(errMsg, h);
380  return h.provenance()->rangeOfValidity();
381 }
382 
383 template <class T, class U>
385 art::same_ranges(T const& a, U const& b)
386 {
387  std::string const& errMsg =
388  "Attempt to compare range sets where one or both handles are invalid.";
389  detail::throw_if_invalid(errMsg, a, b);
391 }
392 
393 template <class T, class U>
395 art::disjoint_ranges(T const& a, U const& b)
396 {
397  std::string const& errMsg =
398  "Attempt to compare range sets where one or both handles are invalid.";
399  detail::throw_if_invalid(errMsg, a, b);
401 }
402 
403 template <class T, class U>
405 art::overlapping_ranges(T const& a, U const& b)
406 {
407  std::string const& errMsg =
408  "Attempt to compare range sets where one or both handles are invalid.";
409  detail::throw_if_invalid(errMsg, a, b);
411 }
412 
413 #endif /* art_Framework_Principal_Handle_h */
414 
415 // Local Variables:
416 // mode: c++
417 // End:
static QCString name
Definition: declinfo.cpp:673
Handle & operator=(Handle const &)=default
Provenance prov_
Definition: Handle.h:290
std::enable_if_t< detail::is_handle< T >::value, RangeSet const & > range_of_validity(T const &h)
BranchDescription const & productDescription() const noexcept
Definition: Provenance.cc:24
static QCString result
bool isValid() const noexcept
Definition: Provenance.cc:18
void msg(const char *fmt,...)
Definition: message.cpp:107
ProductID productID() const noexcept
Definition: Provenance.cc:72
std::string string
Definition: nybbler.cc:12
T const * prod_
Definition: Handle.h:124
std::shared_ptr< art::Exception const > whyFailed_
Definition: Handle.h:126
void swap(Handle< T > &other)
Definition: Handle.h:229
T const & operator*() const
Definition: Handle.h:310
T const * product() const
Definition: Handle.h:323
bool isValid() const noexcept
Definition: Handle.h:191
ValidHandle()=delete
const double e
T const * product() const
Definition: Handle.h:163
ProductID id() const
Definition: Handle.h:351
void swap(Handle< T > &a, Handle< T > &b)
Provenance const * provenance() const
Definition: Handle.h:205
const double a
def move(depos, offset)
Definition: depos.py:107
T const * operator->() const
Definition: Handle.h:316
void convert_handle(GroupQueryResult const &, Handle< T > &)
Definition: Handle.h:248
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:344
constexpr Handle()=default
void throw_if_invalid(std::string const &msg, T const &...t)
Definition: Handle.h:63
string tmp
Definition: languages.py:63
Provenance prov_
Definition: Handle.h:125
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
T const * operator->() const
Definition: Handle.h:175
void swap(ValidHandle< T > &a, ValidHandle< T > &b)
T const & operator*() const
Definition: Handle.h:156
T const * prod_
Definition: Handle.h:289
void clear()
Definition: Handle.h:236
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)
static bool * b
Definition: config.cpp:1043
bool failedToGet() const
Definition: Handle.h:337
std::shared_ptr< art::Exception const > whyFailed() const
Definition: Handle.h:358
std::shared_ptr< art::Exception const > whyFailed() const
Definition: Handle.h:219
vector< vector< double > > clear
QuadExpr operator*(double v, const QuadExpr &e)
Definition: QuadExpr.h:39
ProductID id() const
Definition: Handle.h:212
int bool
Definition: qglobal.h:345
void swap(ValidHandle< T > &other)
Definition: Handle.h:365
bool failedToGet() const
Definition: Handle.h:198
bool isValid() const
Definition: Handle.h:330