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 Standard Gaudi tool constructor.
73  * @param type The name of the tool type.
74  * @param name The tool name.
75  * @param parent The tool's Gaudi parent.
76  */
77 template <class CONT>
78 CollectionGetterTool<CONT>::CollectionGetterTool (const std::string& type,
79  const std::string& name,
80  const IInterface* parent)
81  : CollectionGetterToolImpl (type, name, parent)
82 {
83  // cppcheck-suppress missingReturn; false positive
84 }
85 
86 
87 /**
88  * @brief Return the target object.
89  * @param allowMissing If true, then we should not generate errors
90  * if the requested object is missing.
91  *
92  * Should be of the type given by @c typeinfo.
93  * Return 0 on failure.
94  *
95  * This is implemented by calling @c get().
96  */
97 template <class CONT>
98 const void*
99 CollectionGetterTool<CONT>::getUntyped (bool allowMissing /*= false*/)
100 {
101  return get (allowMissing);
102 }
103 
104 
105 /**
106  * @brief Return the type of the collection object retrieved by this tool.
107  */
108 template <class CONT>
109 const std::type_info& CollectionGetterTool<CONT>::typeinfo() const
110 {
111  return typeid(CONT);
112 }
113 
114 
115 /**
116  * @brief Return the element type of the collection.
117  *
118  * I.e., @c nextUntyped returns a pointer to this type.
119  */
120 template <class CONT>
121 const std::type_info&
122 CollectionGetterTool<CONT>::elementTypeinfo() const
123 {
124  return typeid(typename Deref<CONT>::type);
125 }
126 
127 
128 /**
129  * @brief Reset the iteration to the start of the collection.
130  * @param allowMissing If true, then we should not generate errors
131  * if the requested object is missing.
132  *
133  * Return failure if the container cannot be retrieved.
134  */
135 template <class CONT>
136 StatusCode CollectionGetterTool<CONT>::reset (bool allowMissing /*= false*/)
137 {
138  const CONT* cont = get (allowMissing);
139  if (!cont) {
140  m_it = m_end;
141  return allowMissing ? StatusCode::SUCCESS : StatusCode::FAILURE;
142  }
143 
144  m_it = cont->begin();
145  m_end = cont->end();
146  return StatusCode::SUCCESS;
147 }
148 
149 
150 /**
151  * @brief Return a pointer to the next element in the collection.
152  *
153  * Return 0 when the collection has been exhausted.
154  */
155 template <class CONT>
156 const void* CollectionGetterTool<CONT>::nextUntyped()
157 {
158  // Don't return 0 until we get to the end of the iteration.
159  while (m_it != m_end) {
160  const void* ret = Deref<CONT>::deref (m_it);
161  ++m_it;
162  if (ret) return ret;
163  }
164  return 0;
165 }
166 
167 
168 /**
169  * @brief Return an estimate of the number of elements in the iteration.
170  * @param allowMissing If true, then we should not generate errors
171  * if the requested object is missing.
172  *
173  * This can be used to pre-allocate memory.
174  * (It's possible that this isn't known in advance of
175  * iterating over the entire collection, for example
176  * if a selection is being applied, so this is only a hint.)
177  */
178 template <class CONT>
179 size_t CollectionGetterTool<CONT>::sizeHint (bool allowMissing /*= false*/)
180 {
181  const CONT* cont = get (allowMissing);
182  if (cont)
183  return cont->size();
184  return 0;
185 }
186 
187 
188 /**
189  * @brief Release an object retrieved from the getter.
190  * @param p The object to release.
191  *
192  * Call this when you are done with the object returned by
193  * @c get(). The default implementation is a no-op,
194  * but if the getter dynamically allocated the object which
195  * it returned, this gives it a chance to free it.
196  */
197 template <class CONT>
198 void CollectionGetterTool<CONT>::releaseObject (const CONT* /*p*/)
199 {
200 }
201 
202 
203 /**
204  * @brief Release an object retrieved from the getter.
205  * @param p The object to release.
206  *
207  * Call this when you are done with the object returned by
208  * @c getUntyped(). The default implementation is a no-op,
209  * but if the getter dynamically allocated the object which
210  * it returned, this gives it a chance to free it.
211  */
212 template <class CONT>
213 void CollectionGetterTool<CONT>::releaseObjectUntyped (const void* p)
214 {
215  releaseObject (reinterpret_cast<const CONT*> (p));
216 }
217 
218 
219 } // namespace D3PD