ATLAS Offline Software
MultiAssociationToolMulti.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/MultiAssociationToolMulti.icc
6  * @author scott snyder <snyder@bnl.gov>
7  * @date Jun, 2012
8  * @brief A specialization of MultiAssociationTool that can accept one
9  * of several types.
10  */
11 
12 
13 //**************************************************************************
14 // Single-argument specialization
15 //
16 
17 
18 namespace D3PD {
19 
20 
21 /**
22  * @brief Standard Gaudi tool constructor.
23  * @param type The name of the tool type.
24  * @param name The tool name.
25  * @param parent The tool's Gaudi parent.
26  */
27 template <class T0, class TO_T>
28 MultiAssociationTool<Types<T0>, TO_T>::MultiAssociationTool
29  (const std::string& type,
30  const std::string& name,
31  const IInterface* parent)
32  : MultiAssociationToolTo<TO_T> (type, name, parent),
33  m_which(0),
34  m_fromTypeinfo(0)
35 {
36 }
37 
38 
39 /**
40  * @brief Configure during initialization: type-check.
41  * @param tree Our parent for tuple making.
42  * @param ti Gives the type of the object being passed to @c fillUntyped.
43  *
44  * @c configureD3PD should check that the type of the object coming as input
45  * is compatible with what it expects, and raise an error otherwise.
46  */
47 template <class T0, class TO_T>
48 StatusCode
49 MultiAssociationTool<Types<T0>, TO_T>::configureD3PD
50  (IAddVariable* tree,
51  const std::type_info& ti)
52 {
53  std::vector<const std::type_info*> tis;
54  push_ti (tis);
55  StatusCode sc = this->configureMulti (tree, ti, tis, m_which);
56  if (m_which < tis.size())
57  m_fromTypeinfo = tis[m_which];
58  return sc;
59 }
60 
61 
62 /**
63  * @brief Return the @c std::type_info for the source of the association.
64  */
65 template <class T0, class TO_T>
66 const std::type_info&
67 MultiAssociationTool<Types<T0>, TO_T>::fromTypeinfo() const
68 {
69  return *m_fromTypeinfo;
70 }
71 
72 
73 /**
74  * @brief Return the target object.
75  * @param p The source object for the association.
76  *
77  * Return the target of the association, or 0.
78  * Should be of the type given by @c typeinfo.
79  */
80 template <class T0, class TO_T>
81 StatusCode
82 MultiAssociationTool<Types<T0>, TO_T>::resetUntyped
83  (const void* p)
84 {
85  p = this->doConversion (p);
86  if (!p) return StatusCode::FAILURE;
87  return doResetUntyped (p, 0);
88 }
89 
90 
91 /**
92  * @brief Helper to decide which which @c reset method to call.
93  *
94  * This either calls @c reset using the last type
95  * in our template argument list, or chains to the base class.
96  *
97  * It's virtual so that we can call the most-derived one from
98  * @c resetUntyped in the base class, but we also declare it as inline
99  * so that the base class chaining can be inlined.
100  */
101 template <class T0, class TO_T>
102 inline
103 StatusCode
104 MultiAssociationTool<Types<T0>, TO_T>::doResetUntyped (const void* p, size_t /*count*/)
105 {
106  return this->reset (*reinterpret_cast<const T0*> (p));
107 }
108 
109 
110 /**
111  * @brief Helper to collect the list of @c type_info's that we accept.
112  *
113  * This first chains to the base class to pick up its list.
114  * Then we add the @c type_info corresponding to the last type
115  * in the template argument list.
116  */
117 template <class T0, class TO_T>
118 void
119 MultiAssociationTool<Types<T0>, TO_T>::push_ti (std::vector<const std::type_info*>& tis)
120 {
121  tis.reserve (1);
122  tis.push_back (&typeid(T0));
123 }
124 
125 
126 /**
127  * @brief Release an object retrieved from the association.
128  * @param p The object to release.
129  *
130  * Call this when you are done with the object returned by
131  * @c next(). The default implementation is a no-op,
132  * but if the association dynamically allocated the object which
133  * it returned, this gives it a chance to free it.
134  */
135 template <class T0, class U0>
136 inline
137 void
138 MultiAssociationTool<Types<T0>, Types<U0> >::releaseElement
139  (const U0* /*p*/)
140 {
141 }
142 
143 
144 /**
145  * @brief Release an object retrieved from the association.
146  * @param p The object to release.
147  *
148  * Call this when you are done with the object returned by
149  * @c nextUntyped(). The default implementation is a no-op,
150  * but if the association dynamically allocated the object which
151  * it returned, this gives it a chance to free it.
152  */
153 template <class T0, class U0>
154 inline
155 void
156 MultiAssociationTool<Types<T0>, Types<U0> >::releaseElementUntyped (const void* p)
157 {
158  this->releaseElement (reinterpret_cast<const U0*> (p));
159 }
160 
161 
162 //**************************************************************************
163 
164 
165 /**
166  * @brief Standard Gaudi tool constructor.
167  * @param type The name of the tool type.
168  * @param name The tool name.
169  * @param parent The tool's Gaudi parent.
170  */
171 template <class T0, class U0>
172 MultiAssociationTool<Types<T0>, Types<U0> >::MultiAssociationTool
173  (const std::string& type,
174  const std::string& name,
175  const IInterface* parent)
176  : MultiAssociationTool<Types<T0>, U0> (type, name, parent)
177 {
178  // cppcheck-suppress missingReturn; false positive
179 }
180 
181 
182 /**
183  * @brief Return a pointer to the next element in the association.
184  *
185  * This overload is not used for the case where we can return multiple
186  * output types. In this case, @c next takes a dummy pointer to the
187  * input type in order to fix the type.
188  */
189 template <class T0, class U0>
190 const U0*
191 MultiAssociationTool<Types<T0>, Types<U0> >::next()
192 {
193  std::abort();
194 }
195 
196 
197 /**
198  * @brief Return the element type for the target of the association.
199  *
200  * I.e., @c nextUntyped returns a pointer to this type.
201  */
202 template <class T0, class U0>
203 const std::type_info&
204 MultiAssociationTool<Types<T0>, Types<U0> >::elementTypeinfo() const
205 {
206  return typeid (U0);
207 }
208 
209 
210 /**
211  * @brief Return a pointer to the next element in the association.
212  *
213  * Return 0 when the association has been exhausted.
214  */
215 template <class T0, class U0>
216 const void*
217 MultiAssociationTool<Types<T0>, Types<U0> >::nextUntyped ()
218 {
219  return next ((T0*)0);
220 }
221 
222 
223 //**************************************************************************
224 // Multiple-argument specializations
225 //
226 
227 
228 template <class T0, class TO_T>
229 class MaybeNext
230 {
231 public:
232  void next (int) {}
233 };
234 
235 
236 template <class T0, class U0, class... TYPES>
237 class MaybeNext<T0, Types<U0, TYPES...> >
238 {
239 public:
240  virtual const U0* next (const T0* dum) = 0;
241 };
242 
243 
244 /**
245  * @brief A specialization of MultiAssociationTool that can accept one
246  * of several types.
247  *
248  * This specialization is for the case of more than one argument.
249  */
250 template <class TO_T, class T0, class... TYPES>
251 class MultiAssociationTool<Types<T0, TYPES...>, TO_T>
252  : public MultiAssociationTool<Types<TYPES...>, ButFirstType_t<TO_T> >,
253  public MaybeNext<T0, TO_T>
254 {
255 public:
256  using Base = MultiAssociationTool<Types<TYPES...>, ButFirstType_t<TO_T> >;
257 
258  using Base::Base;
259 
260  virtual void push_ti (std::vector<const std::type_info*>& tis) override
261  {
262  tis.reserve (1 + sizeof... (TYPES));
263  tis.push_back (&typeid(T0));
264  Base::push_ti (tis);
265  }
266 
267  using Base::reset;
268  virtual StatusCode reset (const T0& p) = 0;
269 
270  using Base::next;
271  using MaybeNext<T0, TO_T>::next;
272 
273  virtual StatusCode doResetUntyped (const void* p, size_t count) override
274  {
275  if (this->m_which == count)
276  return this->reset (*reinterpret_cast<const T0*> (p));
277  return Base::doResetUntyped (p, count+1);
278  }
279 };
280 
281 
282 } // namespace D3PD