ATLAS Offline Software
ELProxy.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 AthContainers/tools/ELProxy.icc
6  * @author scott snyder <snyder@bnl.gov>
7  * @date Jan, 2024
8  * @brief Helpers for proxying ElementLink for PackedLink accessors.
9  */
10 
11 
12 namespace SG { namespace detail {
13 
14 
15 /**
16  * @brief Constructor.
17  * @param cnv Converter to copy.
18  */
19 template <class CONT>
20 inline
21 ELProxyValBase<CONT>::ELProxyValBase (PackedLinkConverter<CONT>& cnv) :
22  m_cnv (cnv)
23 {
24 }
25 
26 
27 /**
28  * @brief Constructor.
29  * @param container Container holding the variables.
30  * @param auxid The ID of the PackedLink variable.
31  * @param linked_auxid The ID of the linked DataLinks.
32  */
33 template <class CONT>
34 inline
35 ELProxyValBase<CONT>::ELProxyValBase (AuxVectorData& container,
36  SG::auxid_t auxid,
37  SG::auxid_t linked_auxid)
38  : m_cnv (container, auxid, linked_auxid)
39 {
40  // cppcheck-suppress missingReturn; false positive
41 }
42 
43 
44 /**
45  * @brief Constructor.
46  * @param cnv Converter to reference.
47  */
48 template <class CONT>
49 inline
50 ELProxyRefBase<CONT>::ELProxyRefBase (PackedLinkConverter<CONT>& cnv)
51  : m_cnv (cnv)
52 {
53 }
54 
55 
56 /**
57  * @brief Constructor.
58  * @param pl @c PackedLink object to proxy.
59  * @param cnv Converter to use.
60  */
61 template <class BASE>
62 inline
63 ELProxyT<BASE>::ELProxyT (PLink_t& pl, PackedLinkConverter<Cont_t>& cnv)
64  : BASE (cnv),
65  m_pl (pl)
66 {
67 }
68 
69 
70 /**
71  * @brief Constructor.
72  * @param container Container holding the variables.
73  * @param auxid The ID of the PackedLink variable.
74  * @param linked_auxid The ID of the linked DataLinks.
75  *
76  * This constructor can only be used if the converter is being
77  * held by value.
78  */
79 template <class BASE>
80 inline
81 ELProxyT<BASE>::ELProxyT (PLink_t& pl, AuxVectorData& container,
82  SG::auxid_t auxid,
83  SG::auxid_t linked_auxid)
84  : BASE (container, auxid, linked_auxid),
85  m_pl (pl)
86 {
87 }
88 
89 
90 /**
91  * @brief Convert the held @c PackedLink to an @c ElementLink.
92  */
93 template <class BASE>
94 inline
95 ELProxyT<BASE>::operator const Link_t() const
96 {
97  return this->m_cnv (m_pl);
98 }
99 
100 
101 /**
102  * @brief Update the held @c PackedLink from an @c ElementLink.
103  * @param link The @c ElementLink from which to update.
104  */
105 template <class BASE>
106 inline
107 auto ELProxyT<BASE>::operator= (const Link_t& link) -> const Link_t
108 {
109  this->m_cnv.set (m_pl, link);
110  return link;
111 }
112 
113 
114 /**
115  * @brief Equality comparison with ElementLink.
116  * @param l The link with which to compare.
117  *
118  * (Default conversions don't suffice to make this work.)
119  */
120 template <class BASE>
121 inline
122 bool ELProxyT<BASE>::operator== (const Link_t& l) const
123 {
124  return Link_t(*this) == l;
125 }
126 
127 
128 /**
129  * @brief Equality comparison with another proxy.
130  * @param l The proxy with which to compare.
131  *
132  * (Default conversions don't suffice to make this work.)
133  */
134 template <class BASE>
135 inline
136 bool ELProxyT<BASE>::operator== (const ELProxyT& p) const
137 {
138  return m_pl == p.m_pl;
139 }
140 
141 
142 //***************************************************************************
143 
144 
145 /**
146  * @brief Constructor.
147  * @param cnv Converter. We'll make a copy of this.
148  */
149 template <class PROXY>
150 inline
151 ELProxyConverter<PROXY>::ELProxyConverter (const Base& cnv)
152  : Base (cnv)
153 {
154 }
155 
156 
157 /**
158  * @brief Constructor.
159  * @param container Container holding the variables.
160  * @param auxid The ID of the PackedLink variable.
161  * @param linked_auxid The ID of the linked DataLinks.
162  */
163 template <class PROXY>
164 inline
165 ELProxyConverter<PROXY>::ELProxyConverter (AuxVectorData& container,
166  SG::auxid_t auxid,
167  SG::auxid_t linked_auxid)
168  : Base (container, auxid, linked_auxid)
169 {
170 }
171 
172 
173 /**
174  * @brief Produce a proxy object for a given @c PackedLink.
175  * @param pl The @c PackedLink object to proxy.
176  */
177 template <class PROXY>
178 inline
179 PROXY ELProxyConverter<PROXY>::operator() (PLink_t& pl)
180 {
181  return PROXY (pl, *this);
182 }
183 
184 
185 //***************************************************************************
186 
187 
188 /**
189  * @brief Constructor.
190  * @param velt The vector of @c PackedLink that we proxy.
191  * @param container Container holding the variables.
192  * @param auxid The ID of the PackedLink variable.
193  * @param linked_auxid The ID of the linked DataLinks.
194  */
195 template <class CONT, class PLINK_ALLOC>
196 inline
197 ELSpanProxy<CONT, PLINK_ALLOC>::ELSpanProxy (VElt_t& velt,
198  AuxVectorData& container,
199  SG::auxid_t auxid,
200  SG::auxid_t linked_auxid)
201  : Base (PackedLink_span (velt.data(), velt.size()), m_cnv),
202  m_velt (velt),
203  m_cnv (container, auxid, linked_auxid)
204 {
205 }
206 
207 
208 /**
209  * @brief Assign from a range of @c ElementLink.
210  * @param r The range from which to assign.
211  */
212 template <class CONT, class PLINK_ALLOC>
213 template <ElementLinkRange<CONT> RANGE>
214 void ELSpanProxy<CONT, PLINK_ALLOC>::operator= (const RANGE& r)
215 {
216  auto end = m_velt.end();
217 
218  // Update @c m_velt.
219  m_cnv.set (m_velt, r);
220 
221  // Update the range we're proxying if it has changed.
222  if (end != m_velt.end())
223  {
224  *static_cast<Base*> (this) =
225  Base (PackedLink_span (m_velt.data(), m_velt.size()), m_cnv);
226  }
227 }
228 
229 
230 /**
231  * @brief Convert to a vector of @c ElementLink.
232  */
233 template <class CONT, class PLINK_ALLOC>
234 template <class VALLOC>
235 ELSpanProxy<CONT, PLINK_ALLOC>::operator std::vector<Link_t, VALLOC>() const
236 {
237  return std::vector<Link_t, VALLOC> (this->begin(), this->end());
238 }
239 
240 
241 /**
242  * @brief Convert to a vector of @c ElementLink.
243  */
244 template <class CONT, class PLINK_ALLOC>
245 auto ELSpanProxy<CONT, PLINK_ALLOC>::asVector() const
246  -> std::vector<Link_t>
247 {
248  return std::vector<Link_t> (this->begin(), this->end());
249 }
250 
251 
252 /**
253  * @brief Equality testing.
254  */
255 template <class CONT, class PLINK_ALLOC>
256 template <class VALLOC>
257 bool ELSpanProxy<CONT, PLINK_ALLOC>::operator== (const std::vector<Link_t, VALLOC>& v) const
258 {
259  return this->asVector() == v;
260 }
261 
262 
263 /**
264  * @brief Add a new link to this vector of links.
265  * @param l The new link to add.
266  */
267 template <class CONT, class PLINK_ALLOC>
268 void ELSpanProxy<CONT, PLINK_ALLOC>::push_back (const Link_t& l)
269 {
270  insert (this->end(), 1, l);
271 }
272 
273 
274 /**
275  * @brief Clear this vector of links.
276  */
277 template <class CONT, class PLINK_ALLOC>
278 void ELSpanProxy<CONT, PLINK_ALLOC>::clear()
279 {
280  m_velt.clear();
281  *static_cast<Base*> (this) =
282  Base (PackedLink_span (m_velt.data(), m_velt.size()), m_cnv);
283 }
284 
285 
286 /**
287  * @brief Resize this vector of links.
288  * @param n The desired new size.
289  * @param l Value with which to fill any new elements.
290  */
291 template <class CONT, class PLINK_ALLOC>
292 void ELSpanProxy<CONT, PLINK_ALLOC>::resize (size_t n,
293  const Link_t& l /*= Link_t()*/)
294 {
295  size_t sz = this->size();
296  if (n > sz) {
297  PLink_t plink;
298  m_cnv.set (plink, l);
299  m_velt.resize (n, plink);
300  *static_cast<Base*> (this) =
301  Base (PackedLink_span (m_velt.data(), m_velt.size()), m_cnv);
302  }
303  else if (n < sz) {
304  m_velt.resize (n);
305  *static_cast<Base*> (this) =
306  Base (PackedLink_span (m_velt.data(), m_velt.size()), m_cnv);
307  }
308 }
309 
310 
311 /**
312  * @brief Erase one element from this vector of links.
313  * @param pos The element to erase.
314  */
315 template <class CONT, class PLINK_ALLOC>
316 void ELSpanProxy<CONT, PLINK_ALLOC>::erase (iterator pos)
317 {
318  m_velt.erase (m_velt.begin() + (pos - this->begin()));
319  *static_cast<Base*> (this) =
320  Base (PackedLink_span (m_velt.data(), m_velt.size()), m_cnv);
321 }
322 
323 
324 /**
325  * @brief Erase a range of elements from this vector of links.
326  * @param first The first element to erase.
327  * @param last One past the last element to erase.
328  * @param pos The element to erase.
329  */
330 template <class CONT, class PLINK_ALLOC>
331 void ELSpanProxy<CONT, PLINK_ALLOC>::erase (iterator first, iterator last)
332 {
333  m_velt.erase (m_velt.begin() + (first - this->begin()),
334  m_velt.begin() + (last - this->begin()));
335  *static_cast<Base*> (this) =
336  Base (PackedLink_span (m_velt.data(), m_velt.size()), m_cnv);
337 }
338 
339 
340 /**
341  * @brief Insert a new link into this vector of links.
342  * @param pos The position at which to insert the link.
343  * @param l The link to insert.
344  */
345 template <class CONT, class PLINK_ALLOC>
346 void ELSpanProxy<CONT, PLINK_ALLOC>::insert (iterator pos, const Link_t& l)
347 {
348  insert (pos, 1, l);
349 }
350 
351 
352 /**
353  * @brief Insert copies of a new link into this vector of links.
354  * @param pos The position at which to insert the link.
355  * @param n Number of copies to insert.
356  * @param l The link(s) to insert.
357  */
358 template <class CONT, class PLINK_ALLOC>
359 void ELSpanProxy<CONT, PLINK_ALLOC>::insert (iterator pos, size_t n, const Link_t& l)
360 {
361  size_t i = pos - this->begin();
362  PLink_t plink;
363  m_cnv.set (plink, l);
364  m_velt.insert (m_velt.begin() + i, n, plink);
365  *static_cast<Base*> (this) =
366  Base (PackedLink_span (m_velt.data(), m_velt.size()), m_cnv);
367 }
368 
369 
370 /**
371  * @brief Insert a range of links into this vector of links.
372  * @param pos The position at which to insert the links.
373  * @param first The first element to insert.
374  * @param last One past the last element to insert.
375  */
376 template <class CONT, class PLINK_ALLOC>
377 template <CxxUtils::detail::InputValIterator<ElementLink<CONT> > ITERATOR>
378 void ELSpanProxy<CONT, PLINK_ALLOC>::insert (iterator pos,
379  ITERATOR first, ITERATOR last)
380 {
381  insert_range (pos, std::ranges::subrange (first, last));
382 }
383 
384 
385 /**
386  * @brief Insert a range of links into this vector of links.
387  * @param pos The position at which to insert the links.
388  * @param range The range to insert.
389  */
390 template <class CONT, class PLINK_ALLOC>
391 template <ElementLinkRange<CONT> RANGE>
392 void ELSpanProxy<CONT, PLINK_ALLOC>::insert_range (iterator pos,
393  const RANGE& range)
394 {
395  m_cnv.insert (m_velt, pos - this->begin(), range);
396  *static_cast<Base*> (this) =
397  Base (PackedLink_span (m_velt.data(), m_velt.size()), m_cnv);
398 }
399 
400 
401 /**
402  * @brief Append a range of links to the end of this vector of links.
403  * @param range The range to append.
404  */
405 template <class CONT, class PLINK_ALLOC>
406 template <ElementLinkRange<CONT> RANGE>
407 void ELSpanProxy<CONT, PLINK_ALLOC>::append_range (const RANGE& range)
408 {
409  insert_range (this->end(), range);
410 }
411 
412 
413 /**
414  * @brief Remove the last element in this vector of links.
415  */
416 template <class CONT, class PLINK_ALLOC>
417 void ELSpanProxy<CONT, PLINK_ALLOC>::pop_back()
418 {
419  erase (this->end()-1);
420 }
421 
422 
423 /**
424  * @brief Set this vector of links to copies of a new link.
425  * @param n Number of copies to insert.
426  * @param l The link(s) to insert.
427  */
428 template <class CONT, class PLINK_ALLOC>
429 void ELSpanProxy<CONT, PLINK_ALLOC>::assign (size_t n, const Link_t& l)
430 {
431  clear();
432  insert (this->begin(), n, l);
433 }
434 
435 
436 /**
437  * @brief Set this vector of links to a range of links.
438  * @param first The first element to copy.
439  * @param last One past the last element to copy.
440  */
441 template <class CONT, class PLINK_ALLOC>
442 template <CxxUtils::detail::InputValIterator<ElementLink<CONT> > ITERATOR>
443 void ELSpanProxy<CONT, PLINK_ALLOC>::assign (ITERATOR first, ITERATOR last)
444 {
445  assign_range (std::ranges::subrange (first, last));
446 }
447 
448 
449 /**
450  * @brief Set this vector of links to a range of links.
451  * @param range The range of links to copy.
452  * @param last One past the last element to copy.
453  */
454 template <class CONT, class PLINK_ALLOC>
455 template <ElementLinkRange<CONT> RANGE>
456 void ELSpanProxy<CONT, PLINK_ALLOC>::assign_range (const RANGE& range)
457 {
458  clear();
459  insert_range (this->begin(), range);
460 }
461 
462 
463 //***************************************************************************
464 
465 
466 /***
467  * @brief Constructor.
468  * @param container Container holding the variables.
469  * @param auxid The ID of the PackedLink variable.
470  * @param linked_auxid The ID of the linked DataLinks.
471  */
472 template <class CONT, class PLINK_ALLOC>
473 ELSpanConverter<CONT, PLINK_ALLOC>::ELSpanConverter (AuxVectorData& container,
474  auxid_t auxid,
475  auxid_t linked_auxid)
476  : m_container (container),
477  m_auxid (auxid),
478  m_linkedAuxid (linked_auxid)
479 {
480 }
481 
482 
483 /**
484  * @brief Convert from a @c PackedLink vector to a proxy for the span.
485  * @param velt The vector of @c PackedLink that we proxy.
486  */
487 template <class CONT, class PLINK_ALLOC>
488 auto ELSpanConverter<CONT, PLINK_ALLOC>::operator() (VElt_t& velt) const
489  -> value_type
490 {
491  AuxVectorData& container ATLAS_THREAD_SAFE = m_container;
492  return value_type (velt, container, m_auxid, m_linkedAuxid);
493 }
494 
495 
496 }} // namespace SG::detail