ATLAS Offline Software
SingleAssociationToolMulti.icc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
4 /**
5  * @file D3PDMakerUtils/SingleAssociationToolMulti.icc
6  * @author scott snyder <snyder@bnl.gov>
7  * @date Jun, 2012
8  * @brief A specialization of SingleAssociationTool 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 SingleAssociationTool<Types<T0>, TO_T>::SingleAssociationTool
29  (const std::string& type,
30  const std::string& name,
31  const IInterface* parent)
32  : SingleAssociationToolTo<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 SingleAssociationTool<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 SingleAssociationTool<Types<T0>, TO_T>::fromTypeinfo() const
68 {
69  return *m_fromTypeinfo;
70 }
71 
72 
73 /**
74  * @brief Return the @c std::type_info for the source of the association.
75  */
76 template <class T0, class TO_T>
77 const std::type_info&
78 SingleAssociationTool<Types<T0>, TO_T>::typeinfo() const
79 {
80  return doTypeinfo (0);
81 }
82 
83 
84 template <class T0, class TO_T>
85 const std::type_info&
86 SingleAssociationTool<Types<T0>, TO_T>::doTypeinfo (size_t /*count*/) const
87 {
88  return typeid (typename SelectType<TO_T, 0>::type);
89 }
90 
91 
92 /**
93  * @brief Release an object retrieved from the association.
94  * @param p The object to release.
95  *
96  * Call this when you are done with the object returned by
97  * @c get(). The default implementation is a no-op,
98  * but if the association dynamically allocated the object which
99  * it returned, this gives it a chance to free it.
100  */
101 template <class T0, class TO_T>
102 inline
103 void
104 SingleAssociationTool<Types<T0>, TO_T>::releaseObject
105  (const typename SelectType<TO_T, 0>::type* /*p*/)
106 {
107 }
108 
109 
110 /**
111  * @brief Release an object retrieved from the association.
112  * @param p The object to release.
113  *
114  * Call this when you are done with the object returned by
115  * @c getUntyped(). The default implementation is a no-op,
116  * but if the association dynamically allocated the object which
117  * it returned, this gives it a chance to free it.
118  */
119 template <class T0, class TO_T>
120 inline
121 void
122 SingleAssociationTool<Types<T0>, TO_T>::releaseObjectUntyped (const void* p)
123 {
124  this->doReleaseObjectUntyped (p, 0);
125 }
126 
127 
128 template <class T0, class TO_T>
129 inline
130 void
131 SingleAssociationTool<Types<T0>, TO_T>::doReleaseObjectUntyped (const void* p, size_t /*count*/)
132 {
133  this->releaseObject (reinterpret_cast<const typename SelectType<TO_T, 0>::type*> (p));
134 }
135 
136 
137 /**
138  * @brief Return the target object.
139  * @param p The source object for the association.
140  *
141  * Return the target of the association, or 0.
142  * Should be of the type given by @c typeinfo.
143  */
144 template <class T0, class TO_T>
145 const void*
146 SingleAssociationTool<Types<T0>, TO_T>::getUntyped
147  (const void* p)
148 {
149  p = this->doConversion (p);
150  if (!p) return 0;
151  return doGetUntyped (p, 0);
152 }
153 
154 
155 /**
156  * @brief Helper to decide which which @c get method to call.
157  *
158  * This either calls @c get using the last type
159  * in our template argument list, or chains to the base class.
160  *
161  * It's virtual so that we can call the most-derived one from
162  * @c getUntyped in the base class, but we also declare it as inline
163  * so that the base class chaining can be inlined.
164  */
165 template <class T0, class TO_T>
166 inline
167 const void*
168 SingleAssociationTool<Types<T0>, TO_T>::doGetUntyped (const void* p, size_t count)
169 {
170  if (this->m_which == count)
171  return this->get (*reinterpret_cast<const T0*> (p));
172  std::abort();
173 }
174 
175 
176 /**
177  * @brief Helper to collect the list of @c type_info's that we accept.
178  *
179  * This first chains to the base class to pick up its list.
180  * Then we add the @c type_info corresponding to the last type
181  * in the template argument list.
182  */
183 template <class T0, class TO_T>
184 void
185 SingleAssociationTool<Types<T0>, TO_T>::push_ti (std::vector<const std::type_info*>& tis)
186 {
187  tis.reserve (1);
188  tis.push_back (&typeid(T0));
189 }
190 
191 
192 /**
193  * @brief A specialization of SingleAssociationTool that can accept one
194  * of several types.
195  *
196  * This specialization is for the case of more than one argument.
197  */
198 template <class TO_T, class T0, class... TYPES>
199 class SingleAssociationTool<Types<T0, TYPES...>, TO_T>
200  : public SingleAssociationTool<Types<TYPES...>, ButFirstType_t<TO_T> >
201 {
202 public:
203  using Base = SingleAssociationTool<Types<TYPES...>, ButFirstType_t<TO_T> >;
204 
205  using Base::Base;
206 
207  virtual void push_ti (std::vector<const std::type_info*>& tis) override
208  {
209  tis.reserve (1 + sizeof... (TYPES));
210  tis.push_back (&typeid(T0));
211  Base::push_ti (tis);
212  }
213 
214  using Base::get;
215  virtual const typename SelectType<TO_T, 0>::type* get (const T0& p) = 0;
216 
217  virtual const void* doGetUntyped (const void* p, size_t count) override
218  {
219  if (this->m_which == count)
220  return this->get (*reinterpret_cast<const T0*> (p));
221  return Base::doGetUntyped (p, count+1);
222  }
223 
224 
225 #ifdef __clang__
226 #pragma GCC diagnostic push
227 #pragma GCC diagnostic ignored "-Winconsistent-missing-override"
228 #endif
229  using Base::releaseObject;
230  virtual void releaseObject (const typename SelectType<TO_T, 0>::type* /*p*/) /*override*/ {}
231 #ifdef __clang__
232 #pragma GCC diagnostic pop
233 #endif
234 
235  virtual void doReleaseObjectUntyped (const void* p, size_t count) override
236  {
237  if (this->m_which == count) {
238  this->releaseObject (reinterpret_cast<const typename SelectType<TO_T, 0>::type*>(p));
239  return;
240  }
241  Base::doReleaseObjectUntyped (p, count+1);
242  }
243 
244 
245  virtual const std::type_info&
246  doTypeinfo (size_t count) const override
247  {
248  if (count == this->m_which)
249  return typeid (typename SelectType<TO_T, 0>::type);
250  return Base::doTypeinfo (count+1);
251  }
252 };
253 
254 
255 } // namespace D3PD