ATLAS Offline Software
CollectionGetterTool.icc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 /**
5  * @file D3PDMakerUtils/CollectionGetterTool.h
6  * @author scott snyder <snyder@bnl.gov>
7  * @date Aug, 2009
8  * @brief Type-safe wrapper for collection getter tools.
9  */
10 
11 
12 #include <type_traits>
13 
14 
15 namespace D3PD {
16 
17 
18 /****************************************************************************
19  * Helpers to deal with dereferencing container iterators.
20  *
21  * We want to return a pointer to an element. For an ordinary CONT<T>,
22  * it's easy, we just need &*it.
23  *
24  * However, a DataVector<T> actually contains T*'s, so in this case,
25  * we need to return the container element directly, not a pointer to it.
26  * (Note that null pointers in a DV will automatically be skipped in the
27  * iteration.) Similarly, if we have containers of @c ElementLink
28  * or @c DataLink, then we don't want to return a pointer to the link;
29  * we want to dereference the link and return a pointer to the target.
30  * ??? Is this really the proper behavior for a link?
31  */
32 
33 
34 template <class CONT, class T = typename CONT::value_type>
35 struct Deref
36 {
37  typedef typename CONT::const_iterator iterator;
38  typedef T type;
39  static const type* deref (const iterator& it) { return &*it; }
40 };
41 
42 template <class CONT, class T>
43 struct Deref<CONT, T*>
44 {
45  typedef typename CONT::const_iterator iterator;
46  typedef T type;
47  static const type* deref (const iterator& p) { return *p; }
48 };
49 
50 template <class CONT, class T>
51 struct Deref<CONT, ElementLink<T> >
52 {
53  typedef typename CONT::const_iterator iterator;
54  typedef typename ElementLink<T>::ElementType ElementType;
55  typedef typename std::remove_pointer<ElementType>::type type;
56  static const type* deref (const iterator& p) { return *(p->cptr()); }
57 };
58 
59 template <class CONT, class T>
60 struct Deref<CONT, DataLink<T> >
61 {
62  typedef typename CONT::const_iterator iterator;
63  typedef T type;
64  static const type* deref (const iterator& p) { return **p; }
65 };
66 
67 
68 /****************************************************************************/
69 
70 
71 /**
72  * @brief Return the target object.
73  * @param allowMissing If true, then we should not generate errors
74  * if the requested object is missing.
75  *
76  * Should be of the type given by @c typeinfo.
77  * Return 0 on failure.
78  *
79  * This is implemented by calling @c get().
80  */
81 template <class CONT>
82 const void*
83 CollectionGetterTool<CONT>::getUntyped (bool allowMissing /*= false*/)
84 {
85  return get (allowMissing);
86 }
87 
88 
89 /**
90  * @brief Return the type of the collection object retrieved by this tool.
91  */
92 template <class CONT>
93 const std::type_info& CollectionGetterTool<CONT>::typeinfo() const
94 {
95  return typeid(CONT);
96 }
97 
98 
99 /**
100  * @brief Return the element type of the collection.
101  *
102  * I.e., @c nextUntyped returns a pointer to this type.
103  */
104 template <class CONT>
105 const std::type_info&
106 CollectionGetterTool<CONT>::elementTypeinfo() const
107 {
108  return typeid(typename Deref<CONT>::type);
109 }
110 
111 
112 /**
113  * @brief Reset the iteration to the start of the collection.
114  * @param allowMissing If true, then we should not generate errors
115  * if the requested object is missing.
116  *
117  * Return failure if the container cannot be retrieved.
118  */
119 template <class CONT>
120 StatusCode CollectionGetterTool<CONT>::reset (bool allowMissing /*= false*/)
121 {
122  const CONT* cont = get (allowMissing);
123  if (!cont) {
124  m_it = m_end;
125  return allowMissing ? StatusCode::SUCCESS : StatusCode::FAILURE;
126  }
127 
128  m_it = cont->begin();
129  m_end = cont->end();
130  return StatusCode::SUCCESS;
131 }
132 
133 
134 /**
135  * @brief Return a pointer to the next element in the collection.
136  *
137  * Return 0 when the collection has been exhausted.
138  */
139 template <class CONT>
140 const void* CollectionGetterTool<CONT>::nextUntyped()
141 {
142  // Don't return 0 until we get to the end of the iteration.
143  while (m_it != m_end) {
144  const void* ret = Deref<CONT>::deref (m_it);
145  ++m_it;
146  if (ret) return ret;
147  }
148  return 0;
149 }
150 
151 
152 /**
153  * @brief Return an estimate of the number of elements in the iteration.
154  * @param allowMissing If true, then we should not generate errors
155  * if the requested object is missing.
156  *
157  * This can be used to pre-allocate memory.
158  * (It's possible that this isn't known in advance of
159  * iterating over the entire collection, for example
160  * if a selection is being applied, so this is only a hint.)
161  */
162 template <class CONT>
163 size_t CollectionGetterTool<CONT>::sizeHint (bool allowMissing /*= false*/)
164 {
165  const CONT* cont = get (allowMissing);
166  if (cont)
167  return cont->size();
168  return 0;
169 }
170 
171 
172 /**
173  * @brief Release an object retrieved from the getter.
174  * @param p The object to release.
175  *
176  * Call this when you are done with the object returned by
177  * @c get(). The default implementation is a no-op,
178  * but if the getter dynamically allocated the object which
179  * it returned, this gives it a chance to free it.
180  */
181 template <class CONT>
182 void CollectionGetterTool<CONT>::releaseObject (const CONT* /*p*/)
183 {
184 }
185 
186 
187 /**
188  * @brief Release an object retrieved from the getter.
189  * @param p The object to release.
190  *
191  * Call this when you are done with the object returned by
192  * @c getUntyped(). The default implementation is a no-op,
193  * but if the getter dynamically allocated the object which
194  * it returned, this gives it a chance to free it.
195  */
196 template <class CONT>
197 void CollectionGetterTool<CONT>::releaseObjectUntyped (const void* p)
198 {
199  releaseObject (reinterpret_cast<const CONT*> (p));
200 }
201 
202 
203 } // namespace D3PD