ATLAS Offline Software
Loading...
Searching...
No Matches
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
18namespace 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 */
27template <class T0, class TO_T>
28MultiAssociationTool<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 */
48template <class T0, class TO_T>
49StatusCode
50MultiAssociationTool<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 */
66template <class T0, class TO_T>
67const std::type_info&
68MultiAssociationTool<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 */
81template <class T0, class TO_T>
82StatusCode
83MultiAssociationTool<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 */
102template <class T0, class TO_T>
103inline
104StatusCode
105MultiAssociationTool<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 */
118template <class T0, class TO_T>
119void
120MultiAssociationTool<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 */
136template <class T0, class U0>
137inline
138void
139MultiAssociationTool<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 */
154template <class T0, class U0>
155inline
156void
157MultiAssociationTool<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 */
173template <class T0, class U0>
174const U0*
175MultiAssociationTool<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 */
186template <class T0, class U0>
187const std::type_info&
188MultiAssociationTool<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 */
199template <class T0, class U0>
200const void*
201MultiAssociationTool<Types<T0>, Types<U0> >::nextUntyped ()
202{
203 return next ((T0*)0);
204}
205
206
207//**************************************************************************
208// Multiple-argument specializations
209//
210
211
212template <class T0, class TO_T>
213class MaybeNext
214{
215public:
216 void next (int) {}
217};
218
219
220template <class T0, class U0, class... TYPES>
221class MaybeNext<T0, Types<U0, TYPES...> >
222{
223public:
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 */
234template <class TO_T, class T0, class... TYPES>
235class MultiAssociationTool<Types<T0, TYPES...>, TO_T>
236 : public MultiAssociationTool<Types<TYPES...>, ButFirstType_t<TO_T> >,
237 public MaybeNext<T0, TO_T>
238{
239public:
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