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