ATLAS Offline Software
Loading...
Searching...
No Matches
ConstDataVector.icc
Go to the documentation of this file.
1// Dear emacs, this is -*- c++ -*-
2/*
3 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
4*/
5/**
6 * @file AthContainers/ConstDataVector.icc
7 * @author scott snyder <snyder@bnl.gov>
8 * @date Sep, 2011
9 * @brief @c DataVector adapter that acts like it holds const pointers.
10 */
11
12
13#include "CxxUtils/checker_macros.h"
14#include "CxxUtils/throw_out_of_range.h"
15#include <functional>
16#include <ranges>
17
18
19namespace ConstDataVector_detail {
20
21
22/// Functional to cast const away.
23template <class T>
24class remove_const
25{
26public:
27 T* operator() (const T* p) const {
28 T* pp ATLAS_THREAD_SAFE = const_cast<T*> (p);
29 return pp;
30 }
31};
32
33
34} // namespace ConstDataVector_detail
35
36
37//=== Constructors, destructors, assignment.
38
39
40/**
41 * @brief Default constructor.
42 * @param ownPolicy The ownership mode for the container.
43 *
44 * By default, a @c DataVector will own its elements.
45 * To avoid this, pass @c SG::VIEW_ELEMENTS for @a ownPolicy.
46 */
47template <class DV>
48inline
49ConstDataVector<DV>::ConstDataVector
50 (SG::OwnershipPolicy ownPolicy /*= SG::OWN_ELEMENTS*/)
51 : DV (ownPolicy)
52{
53 base_data_vector::clear (ownPolicy, SG::NEVER_TRACK_INDICES);
54}
55
56
57/**
58 * @brief Constructor with argument forwarding.
59 * @param ownPolicy The ownership mode for the container.
60 *
61 * All arguments are forwarded to the base class constructor.
62 */
63template <class DV>
64template <typename... ARGS>
65inline
66ConstDataVector<DV>::ConstDataVector (SG::OwnershipPolicy ownPolicy,
67 ARGS&&... args)
68 : DV (ownPolicy, std::forward<ARGS>(args)...)
69{
70 base_data_vector::clear (ownPolicy, SG::NEVER_TRACK_INDICES);
71}
72
73
74/**
75 * @brief Sized constructor.
76 * @param n The size of the container.
77 * @param ownPolicy The ownership mode for the container.
78 *
79 * Note that unlike the standard vector constructor, you can't specify
80 * an initial value here. The container will be initialized with 0's.
81 *
82 * By default, a @c DataVector will own its elements.
83 * To avoid this, pass @c SG::VIEW_ELEMENTS for @a ownPolicy.
84 */
85template <class DV>
86inline
87ConstDataVector<DV>::ConstDataVector
88 (size_type n,
89 SG::OwnershipPolicy ownPolicy /*= SG::OWN_ELEMENTS*/)
90 : DV (n, ownPolicy)
91{
92 base_data_vector::clear (ownPolicy, SG::NEVER_TRACK_INDICES);
93 DV::resize (n);
94}
95
96
97/**
98 * @brief Constructor from iterators.
99 * @param first The start of the range to put in the new container.
100 * @param last The end of the range to put in the new container.
101 * @param ownPolicy The ownership mode for the container.
102 *
103 * By default, a @c DataVector will own its elements (and take ownership
104 * of the pointers passed to this constructor).
105 * To avoid this, pass @c SG::VIEW_ELEMENTS for @a ownPolicy.
106 */
107template <class DV>
108template <class InputIterator>
109inline
110ConstDataVector<DV>::ConstDataVector
111 (InputIterator first,
112 InputIterator last,
113 SG::OwnershipPolicy ownPolicy /*= SG::VIEW_ELEMENTS*/)
114 : DV (ownPolicy)
115{
116 base_data_vector::clear (ownPolicy, SG::NEVER_TRACK_INDICES);
117 reserve (std::distance (first, last));
118 while (first != last)
119 push_back (*first++);
120}
121
122
123/**
124 * @brief Move constructor.
125 * @param rhs The container from which to move.
126 *
127 * Any auxiliary data will be moved along with the container contents.
128 */
129template <class DV>
130inline
131ConstDataVector<DV>::ConstDataVector (ConstDataVector&& rhs)
132 : DV (std::move (rhs))
133{
134}
135
136
137/**
138 * @brief Constructor from an initializer list.
139 * @param l An initializer list.
140 * @param last The end of the range to put in the new container.
141 * @param ownPolicy The ownership mode for the container.
142 *
143 * By default, a @c DataVector will own its elements (and take ownership
144 * of the pointers passed to this constructor).
145 * To avoid this, pass @c SG::VIEW_ELEMENTS for @a ownPolicy.
146 */
147template <class DV>
148inline
149ConstDataVector<DV>::ConstDataVector
150 (std::initializer_list<value_type> l,
151 SG::OwnershipPolicy ownPolicy /*= SG::VIEW_ELEMENTS*/)
152 : ConstDataVector (l.begin(), l.end(), ownPolicy)
153{
154}
155
156
157/**
158 * @brief Constructor from a vector of ElementLinks.
159 * @param v The vector from which to initialize.
160 *
161 * This will make a view container.
162 */
163template <class DV>
164template <class CONTAINER>
165ConstDataVector<DV>::ConstDataVector
166 (const std::vector<ElementLink<CONTAINER> >& v)
167 : DV (SG::VIEW_ELEMENTS)
168{
169 this->reserve (v.size());
170 for (const ElementLink<CONTAINER>& el : v)
171 this->push_back (*el);
172}
173
174
175/**
176 * @brief Assignment operator.
177 * @param rhs The DataVector from which to assign.
178 * @return This object.
179 *
180 * This is a `shallow' copy; after the completion of this, the DataVector
181 * will not own its elements. Any elements it owned prior to this call
182 * will be released.
183 *
184 * Note: this method may only be called using the most derived
185 * @c DataVector in the hierarchy.
186 */
187template <class DV>
188inline
189ConstDataVector<DV>&
190ConstDataVector<DV>::operator= (const ConstDataVector& rhs)
191{
192 *static_cast<DV*>(this) = rhs;
193 return *this;
194}
195
196
197/**
198 * @brief Move assignment.
199 * @param rhs The container from which to move.
200 *
201 * Any auxiliary data will be moved along with the container contents.
202 */
203template <class DV>
204inline
205ConstDataVector<DV>&
206ConstDataVector<DV>::operator= (ConstDataVector&& rhs)
207{
208 if (this != &rhs) {
209 DV::operator= (std::move (rhs));
210 }
211 return *this;
212}
213
214
215/**
216 * @brief Assignment operator, from an initializer list.
217 * @param l An initializer list.
218 * @return This object.
219 *
220 * This is equivalent to @c assign.
221 * Any existing owned elements will be released.
222 * The @c DataVector's ownership policy determines whether it will take
223 * ownership of the new elements.
224 */
225template <class DV>
226inline
227ConstDataVector<DV>&
228ConstDataVector<DV>::operator= (std::initializer_list<value_type> l)
229{
230 this->assign (l.begin(), l.end());
231 return *this;
232}
233
234
235/**
236 * @brief Assign from iterators.
237 * @param first The start of the range to put in the container.
238 * @param last The end of the range to put in the container.
239 *
240 * Any existing owned elements will be released.
241 * The @c DataVector's ownership policy determines whether it will take
242 * ownership of the new elements.
243 */
244template <class DV>
245template <class InputIterator>
246inline
247void ConstDataVector<DV>::assign(InputIterator first, InputIterator last)
248{
249 clear();
250 reserve (std::distance (first, last));
251 while (first != last)
252 push_back (*first++);
253}
254
255
256/**
257 * @brief Assign from an initializer list.
258 * @param l An initializer list.
259 *
260 * Any existing owned elements will be released.
261 * The @c DataVector's ownership policy determines whether it will take
262 * ownership of the new elements.
263 */
264template <class DV>
265inline
266void ConstDataVector<DV>::assign(std::initializer_list<value_type> l)
267{
268 this->assign (l.begin(), l.end());
269}
270
271
272/**
273 * @brief Assign from a vector of ElementLinks.
274 * @param v The vector from which to initialize.
275 *
276 * This will change the container to a view container.
277 */
278template <class DV>
279template <class CONTAINER>
280void ConstDataVector<DV>::assign (const std::vector<ElementLink<CONTAINER> >& v)
281{
282 this->clear(SG::VIEW_ELEMENTS);
283 this->reserve (v.size());
284 for (const ElementLink<CONTAINER>& el : v)
285 this->push_back (*el);
286}
287
288
289//=== Element access.
290
291
292/**
293 * @brief Access an element, as an lvalue.
294 * @param n Array index to access.
295 * @return Proxy to the element at @a n.
296 *
297 * No bounds checking is done.
298 * Note that we return a proxy object rather than a reference;
299 * the proxy will handle deleting an owned element if it's assigned to.
300 */
301template <class DV>
302inline
303typename ConstDataVector<DV>::ElementProxy
304ConstDataVector<DV>::operator[] (size_type n)
305{
306 return to_element_proxy (this->m_pCont.begin() + n);
307}
308
309
310/**
311 * @brief Access an element, as an lvalue.
312 * @param n Array index to access.
313 * @return Proxy to the element at @a n.
314 *
315 * Will raise @c std::out_of_range if the index is out-of-bounds.
316 * Note that we return a proxy object rather than a reference;
317 * the proxy will handle deleting an owned element if it's assigned to.
318 */
319template <class DV>
320inline
321typename ConstDataVector<DV>::ElementProxy
322ConstDataVector<DV>::at (size_type n)
323{
324 if (n >= this->size())
325 CxxUtils::throw_out_of_range (__PRETTY_FUNCTION__, n, this->size(), this);
326 return to_element_proxy (this->m_pCont.begin() + n);
327}
328
329
330/**
331 * @brief Access the first element in the collection as an lvalue.
332 * @return Proxy to the first element in the collection.
333 *
334 * No checking is done to ensure that the container is not empty.
335 * Note that we return a proxy object rather than a reference;
336 * the proxy will handle deleting an owned element if it's assigned to.
337 */
338template <class DV>
339inline
340typename ConstDataVector<DV>::ElementProxy
341ConstDataVector<DV>::front ()
342{
343 return to_element_proxy (this->m_pCont.begin());
344}
345
346
347/**
348 * @brief Access the last element in the collection as an lvalue.
349 * @return Proxy to the last element in the collection.
350 *
351 * No checking is done to ensure that the container is not empty.
352 * Note that we return a proxy object rather than a reference;
353 * the proxy will handle deleting an owned element if it's assigned to.
354 */
355template <class DV>
356inline
357typename ConstDataVector<DV>::ElementProxy
358ConstDataVector<DV>::back ()
359{
360 return to_element_proxy (this->m_pCont.end()-1);
361}
362
363
364//=== Iterator creation.
365
366
367/**
368 * @brief Return an @c iterator pointing at the beginning
369 * of the collection.
370 * @return An @c iterator.
371 *
372 * Note that dereferencing the iterator will yield a proxy rather
373 * than a reference; the proxy will handle deleting an owned element
374 * if it's assigned to.
375 */
376template <class DV>
377inline
378typename ConstDataVector<DV>::iterator
379ConstDataVector<DV>::begin() noexcept
380{
381 return to_my_iterator (DV::begin());
382}
383
384
385/**
386 * @brief Return an @c iterator pointing past the end
387 * of the collection.
388 * @return An @c iterator.
389 *
390 * Note that dereferencing the iterator will yield a proxy rather
391 * than a reference; the proxy will handle deleting an owned element
392 * if it's assigned to.
393 */
394template <class DV>
395inline
396typename ConstDataVector<DV>::iterator
397ConstDataVector<DV>::end() noexcept
398{
399 return to_my_iterator (DV::end());
400}
401
402
403/**
404 * @brief Return a @c reverse_iterator pointing past the end
405 * of the collection.
406 * @return A @c reverse_iterator.
407 *
408 * Note that dereferencing the iterator will yield a proxy rather
409 * than a reference; the proxy will handle deleting an owned element
410 * if it's assigned to.
411 */
412template <class DV>
413inline
414typename ConstDataVector<DV>::reverse_iterator
415ConstDataVector<DV>::rbegin() noexcept
416{
417 return reverse_iterator (to_my_iterator (DV::end()));
418}
419
420
421/**
422 * @brief Return a @c reverse_iterator pointing at the beginning
423 * of the collection.
424 * @return A @c reverse_iterator.
425 *
426 * Note that dereferencing the iterator will yield a proxy rather
427 * than a reference; the proxy will handle deleting an owned element
428 * if it's assigned to.
429 */
430template <class DV>
431inline
432typename ConstDataVector<DV>::reverse_iterator
433ConstDataVector<DV>::rend() noexcept
434{
435 return reverse_iterator (to_my_iterator (DV::begin()));
436}
437
438
439//=== Insertion operations.
440
441
442/**
443 * @brief Add an element to the end of the collection.
444 * @param pElem The element to add to the collection.
445 *
446 * The container's ownership policy will determine if it takes ownership
447 * of the new element.
448 *
449 * Note: this method may only be called using the most derived
450 * @c DataVector in the hierarchy.
451 *
452 * Returns the pushed pointer.
453 */
454template <class DV>
455inline
456typename ConstDataVector<DV>::value_type
457ConstDataVector<DV>::push_back(value_type pElem)
458{
459 typename DV::value_type p ATLAS_THREAD_SAFE = const_cast<typename DV::value_type> (pElem);
460 DV::push_back (p);
461 return p;
462}
463
464
465/**
466 * @brief Add an element to the end of the collection.
467 * @param pElem The element to add to the collection.
468 *
469 * The container's ownership policy will determine if it takes ownership
470 * of the new element.
471 *
472 * Note: this method may only be called using the most derived
473 * @c DataVector in the hierarchy.
474 *
475 * For @c DataVector, this is like the same as @c push_back, and
476 * it returns the pushed element.
477 * It's included just for interface compatibility with `std::vector`.
478 */
479template <class DV>
480inline
481typename ConstDataVector<DV>::value_type
482ConstDataVector<DV>::emplace_back(value_type pElem)
483{
484 this->push_back (pElem);
485 return pElem;
486}
487
488
489/**
490 * @brief Add a new element to the collection.
491 * @param position Iterator before which the element will be added.
492 * @param pElem The element to add to the collection.
493 * @return An iterator that points to the inserted data.
494 *
495 * The container's ownership policy will determine if it takes ownership
496 * of the new element.
497 *
498 * Note: this method may only be called using the most derived
499 * @c DataVector in the hierarchy.
500 */
501template <class DV>
502inline
503typename ConstDataVector<DV>::iterator
504ConstDataVector<DV>::insert(iterator position, value_type pElem)
505{
506 typename DV::value_type p ATLAS_THREAD_SAFE = const_cast<typename DV::value_type> (pElem);
507 return to_my_iterator
508 (DV::insert (to_base_iterator (position), p));
509}
510
511
512/**
513 * @brief Add a new element to the collection.
514 * @param position Iterator before which the element will be added.
515 * @param pElem The element to add to the collection.
516 * @return An iterator that points to the inserted data.
517 *
518 * The container's ownership policy will determine if it takes ownership
519 * of the new element.
520 *
521 * Note: this method may only be called using the most derived
522 * @c DataVector in the hierarchy.
523 *
524 * For @c DataVector, this is just the same as @c insert.
525 * It's included just for interface compatibility with `std::vector`.
526 */
527template <class DV>
528inline
529typename ConstDataVector<DV>::iterator
530ConstDataVector<DV>::emplace(iterator position, value_type pElem)
531{
532 return this->insert (position, pElem);
533}
534
535
536/**
537 * @brief Add a group of new elements to the collection.
538 * @param position Iterator before which the element will be added.
539 * @param first The start of the range to put in the container.
540 * @param last The end of the range to put in the container.
541 *
542 * The container's ownership policy will determine if it takes ownership
543 * of the new element.
544 *
545 * Note: this method may only be called using the most derived
546 * @c DataVector in the hierarchy.
547 */
548template <class DV>
549template <class InputIterator>
550inline
551void ConstDataVector<DV>::insert (iterator position,
552 InputIterator first,
553 InputIterator last)
554{
555 ConstDataVector_detail::remove_const<typename DV::base_value_type> cast;
556 auto view = std::ranges::subrange(first, last) | std::views::transform(cast);
557 DV::insert(to_base_iterator(position), view.begin(), view.end());
558}
559
560
561/**
562 * @brief Add an element to the end of the collection.
563 * @param pElem The element to add to the collection.
564 *
565 * The container must be an owning container.
566 *
567 * Note: this method may only be called using the most derived
568 * @c DataVector in the hierarchy.
569 *
570 * Returns the pushed pointer.
571 */
572template <class DV>
573inline
574typename ConstDataVector<DV>::value_type
575ConstDataVector<DV>::push_back(std::unique_ptr<const base_value_type> pElem)
576{
577 typename DV::value_type ptmp ATLAS_THREAD_SAFE =
578 const_cast<typename DV::value_type> (pElem.release());
579 std::unique_ptr<typename DV::base_value_type> ptr (ptmp);
580 DV::push_back (std::move (ptr));
581 return DV::back();
582}
583
584
585/**
586 * @brief Add a new element to the collection.
587 * @param position Iterator before which the element will be added.
588 * @param pElem The element to add to the collection.
589 * @return An iterator that points to the inserted data.
590 *
591 * The container must be an owning container.
592 *
593 * Note: this method may only be called using the most derived
594 * @c DataVector in the hierarchy.
595 */
596template <class DV>
597inline
598typename ConstDataVector<DV>::iterator
599ConstDataVector<DV>::insert(iterator position,
600 std::unique_ptr<const base_value_type> pElem)
601{
602 typename DV::value_type ptmp ATLAS_THREAD_SAFE =
603 const_cast<typename DV::value_type> (pElem.release());
604 std::unique_ptr<typename DV::base_value_type> ptr (ptmp);
605 return to_my_iterator
606 (DV::insert (to_base_iterator (position), std::move (ptr)));
607}
608
609
610/**
611 * @brief Add a group of new elements to the collection.
612 * @param position Iterator before which the element will be added.
613 * @param l An initializer list.
614 *
615 * The container's ownership policy will determine if it takes ownership
616 * of the new element.
617 *
618 * Note: this method may only be called using the most derived
619 * @c DataVector in the hierarchy.
620 */
621template <class DV>
622inline
623void ConstDataVector<DV>::insert (iterator position,
624 std::initializer_list<value_type> l)
625{
626 this->insert (position, l.begin(), l.end());
627}
628
629
630//=== Erasure operations.
631
632
633/**
634 * @brief Remove element at a given position.
635 * @param position Iterator pointing to the element to be removed.
636 * @return An iterator pointing to the next element (or @c end()).
637 *
638 * If the container owns its elements, then the pointed-to element
639 * will be deleted.
640 */
641template <class DV>
642inline
643typename ConstDataVector<DV>::iterator
644ConstDataVector<DV>::erase(iterator position)
645{
646 return to_my_iterator (DV::erase (to_base_iterator (position)));
647}
648
649
650/**
651 * @brief Remove a range of elements.
652 * @param first Iterator pointing to the first element to be removed.
653 * @param last Iterator pointing one past the last element to be removed.
654 * @return An iterator pointing to the element pointed to by @a last
655 * prior to erasing (or @c end()).
656 *
657 * If the container owns its elements, then the removed elements
658 * will be deleted. Any duplicates will be removed in this process,
659 * but don't rely on this.
660 */
661template <class DV>
662inline
663typename ConstDataVector<DV>::iterator
664ConstDataVector<DV>::erase(iterator first, iterator last)
665{
666 return to_my_iterator
667 (DV::erase (to_base_iterator (first),
668 to_base_iterator (last)));
669}
670
671
672/**
673 * @brief clear()
674 * @brief Erase all the elements in the collection.
675 *
676 * If the container owns its elements, then the removed elements
677 * will be deleted. Any duplicates will be removed in this process,
678 * but don't rely on this.
679 */
680template <class DV>
681inline
682void ConstDataVector<DV>::clear()
683{
684 DV::clear();
685}
686
687
688/**
689 * @brief Swap this collection with another.
690 * @param rhs The collection with which to swap.
691 *
692 * Ownership is swapped along with the collection content.
693 *
694 * Note: this method may only be called using the most-derived
695 * @c DataVector in the hierarchy. The @a rhs must also be
696 * referenced using the most-derived @c DataVector.
697 */
698template <class DV>
699inline
700void ConstDataVector<DV>::swap (ConstDataVector& rhs)
701{
702 DV::swap (rhs);
703}
704
705
706/**
707 * @brief Swap the referents of two @c DataVector iterators.
708 * @param a The first iterator for the swap.
709 * @param b The second iterator for the swap.
710 */
711template <class DV>
712inline
713void ConstDataVector<DV>::iter_swap (iterator a, iterator b)
714{
715 DV::iter_swap (to_base_iterator (a),
716 to_base_iterator (b));
717}
718
719
720//=== Non-standard operations.
721
722
723/**
724 * @brief Swap one element out of the container.
725 * @param index Index of the element in the container to swap.
726 * @param newElem New element to put in the container.
727 * May be 0.
728 * @param oldElem Reference to receive the element removed from the
729 * container.
730 *
731 * Reference @a oldElem is initialized with element @a index of the
732 * collection (no bounds checking). Then element @a index is set
733 * to @c newElem. If the collection owns its elements, then it will
734 * take ownership of @a newElem and release (without deleting)
735 * the element returned through @a oldElem.
736 *
737 * Note: this method may only be called using the most derived
738 * @c DataVector in the hierarchy.
739 */
740template <class DV>
741inline
742void
743ConstDataVector<DV>::swapElement (size_type index,
744 value_type newElem,
745 reference oldElem)
746{
747 typename DV::value_type pnew ATLAS_THREAD_SAFE = const_cast<typename DV::value_type>(newElem);
748 typename DV::reference rold ATLAS_THREAD_SAFE = const_cast<typename DV::reference>(oldElem);
749 DV::swapElement (index, pnew, rold);
750}
751
752
753/**
754 * @brief Swap one element out of the container.
755 * @param pos The element in the container to swap.
756 * @param newElem New element to put in the container.
757 * May be 0.
758 * @param oldElem Reference to receive the element removed from the
759 * container.
760 *
761 * Reference @a oldElem is initialized with element @a pos of the
762 * collection (no bounds checking). Then element @a index is set
763 * to @c newElem. If the collection owns its elements, then it will
764 * take ownership of @a newElem and release (without deleting)
765 * the element returned through @a oldElem.
766 *
767 * Note: this method may only be called using the most derived
768 * @c DataList in the hierarchy.
769 */
770template <class DV>
771inline
772void
773ConstDataVector<DV>::swapElement (iterator pos,
774 value_type newElem,
775 reference oldElem)
776{
777 typename DV::value_type pnew ATLAS_THREAD_SAFE = const_cast<typename DV::value_type>(newElem);
778 typename DV::reference rold ATLAS_THREAD_SAFE = const_cast<typename DV::reference>(oldElem);
779 DV::swapElement (to_base_iterator(pos), pnew, rold);
780}
781
782
783/**
784 * @brief Swap one element out of the container.
785 * @param index Index of the element in the container to swap.
786 * @param newElem New element to put in the container.
787 * May be 0.
788 * @param oldElem Reference to receive the element removed from the
789 * container.
790 *
791 * Reference @a oldElem is initialized with element @a index of the
792 * collection (no bounds checking). Then element @a index is set
793 * to @c newElem.
794 *
795 * The collection must own its elements to use its interface.
796 * The collection will take ownership of @c newElem and will return
797 * ownership of @c oldElem.
798 *
799 * Note: this method may only be called using the most derived
800 * @c DataVector in the hierarchy.
801 */
802template <class DV>
803inline
804void
805ConstDataVector<DV>::swapElement (size_type index,
806 std::unique_ptr<const base_value_type> newElem,
807 std::unique_ptr<const base_value_type>& oldElem)
808{
809 typename DV::value_type pelem ATLAS_THREAD_SAFE =
810 const_cast<typename DV::value_type> (newElem.release());
811 std::unique_ptr<typename DV::base_value_type> new_u (pelem);
812 std::unique_ptr<typename DV::base_value_type> old_u;
813 DV::swapElement (index, std::move(new_u), old_u);
814 oldElem = std::move (old_u);
815}
816
817
818/**
819 * @brief Swap one element out of the container.
820 * @param pos The element in the container to swap.
821 * @param newElem New element to put in the container.
822 * May be 0.
823 * @param oldElem Reference to receive the element removed from the
824 * container.
825 *
826 * Reference @a oldElem is initialized with element @a pos of the
827 * collection (no bounds checking). Then element @a index is set
828 * to @c newElem.
829 *
830 * The collection must own its elements to use its interface.
831 * The collection will take ownership of @c newElem and will return
832 * ownership of @c oldElem.
833 *
834 * Note: this method may only be called using the most derived
835 * @c DataList in the hierarchy.
836 */
837template <class DV>
838inline
839void
840ConstDataVector<DV>::swapElement (iterator pos,
841 std::unique_ptr<const base_value_type> newElem,
842 std::unique_ptr<const base_value_type>& oldElem)
843{
844 typename DV::value_type pelem ATLAS_THREAD_SAFE =
845 const_cast<typename DV::value_type> (newElem.release());
846 std::unique_ptr<typename DV::base_value_type> new_u (pelem);
847 std::unique_ptr<typename DV::base_value_type> old_u;
848 DV::swapElement (to_base_iterator(pos), std::move(new_u), old_u);
849 oldElem = std::move (old_u);
850}
851
852
853/**
854 * @brief Return a pointer to this object, as a const @c DataVector.
855 */
856template <class DV>
857inline
858const DV*
859ConstDataVector<DV>::asDataVector() const
860{
861 return static_cast<const DV*>(this);
862}
863
864
865/**
866 * @brief Cast from a @c DataVector to a @c ConstDataVector.
867 * @param dv Pointer to object to cast.
868 *
869 * Return @c DV cast to a @c ConstDataVector.
870 */
871template <class DV>
872const ConstDataVector<DV>* ConstDataVector<DV>::fromDataVector (const DV* dv)
873{
874 if (typeid (*dv) == typeid (ConstDataVector))
875 return static_cast<const ConstDataVector*> (dv);
876 return nullptr;
877}
878
879
880/**
881 * @brief Reset indices / reorder aux data after elements have been permuted.
882 * @param beg Start of the range of elements to process.
883 * @param end End of the range of elements to process.
884 *
885 * This is a no-op for @c ConstDataVector.
886 */
887template <class DV>
888inline
889void ConstDataVector<DV>::resortAux (iterator /*beg*/, iterator /*end*/)
890{
891}
892
893
894/**
895 * @brief Erase all the elements in the collection, and reset
896 * the ownership mode.
897 * @param ownPolicy The new ownership policy of the container.
898 *
899 * If the container owns its elements, then the removed elements
900 * will be deleted. Any duplicates will be removed in this process,
901 * but don't rely on this.
902 */
903template <class DV>
904inline
905void ConstDataVector<DV>::clear (SG::OwnershipPolicy ownPolicy)
906{
907 DV::clear (ownPolicy, SG::NEVER_TRACK_INDICES);
908}
909
910
911/**
912 * @fn void clear
913 * @brief Erase all the elements in the collection, and reset
914 * the ownership mode.
915 * @param ownPolicy The new ownership policy of the container.
916 * @param trackIndices The index tracking policy.
917 *
918 * If the container owns its elements, then the removed elements
919 * will be deleted. Any duplicates will be removed in this process,
920 * but don't rely on this.
921 */
922template <class DV>
923inline
924void ConstDataVector<DV>::clear (SG::OwnershipPolicy ownPolicy,
925 SG::IndexTrackingPolicy trackIndices)
926{
927 DV::clear (ownPolicy, trackIndices);
928 if (DV::trackIndices()) std::abort();
929}
930
931
932/**
933 * @brief Convert to @c AuxVectorBase.
934 *
935 * Needed to get @x AuxVectorBase from a @c ConstDataVector.
936 * Present in @c DataVector as well for consistency.
937 */
938template <class DV>
939inline
940const SG::AuxVectorBase& ConstDataVector<DV>::auxbase() const
941{
942 return *this;
943}
944
945
946//=== Relational operators.
947
948
949/**
950 * @brief Vector ordering relation.
951 * @param b A @c ConstDataVector of the same type as @a *this.
952 * @return True iff @a *this is lexicographically less than @a b.
953 *
954 * This is a total ordering relation. It is linear in the size of the
955 * vectors. Comparisons are done on the pointer values of the elements.
956 *
957 * See @c std::lexicographical_compare() for how the determination is made.
958 */
959template <class DV>
960inline
961bool ConstDataVector<DV>::operator< (const ConstDataVector& b) const
962{
963 return static_cast<const DV&>(*this) < static_cast<const DV&>(b);
964}
965
966
967/// Based on operator<
968template <class DV>
969inline
970bool ConstDataVector<DV>::operator> (const ConstDataVector& b) const
971{
972 return static_cast<const DV&>(*this) > static_cast<const DV&>(b);
973}
974
975
976/// Based on operator<
977template <class DV>
978inline
979bool ConstDataVector<DV>::operator<= (const ConstDataVector& b) const
980{
981 return static_cast<const DV&>(*this) <= static_cast<const DV&>(b);
982}
983
984
985/// Based on operator<
986template <class DV>
987inline
988bool ConstDataVector<DV>::operator>= (const ConstDataVector& b) const
989{
990 return static_cast<const DV&>(*this) >= static_cast<const DV&>(b);
991}
992
993
994/**
995 * @brief Vector equality comparison.
996 * @param b A @c ConstDataVector of the same type as @a *this.
997 * @return True iff the size and elements of the vectors are equal.
998 *
999 * This is an equivalence relation. It is linear in the size of the
1000 * vectors. Vectors are considered equivalent if their sizes are equal,
1001 * and if corresponding elements compare equal.
1002 */
1003template <class DV>
1004inline
1005bool ConstDataVector<DV>::operator== (const ConstDataVector& b) const
1006{
1007 return static_cast<const DV&>(*this) == static_cast<const DV&>(b);
1008}
1009
1010
1011/// Based on operator==
1012template <class DV>
1013inline
1014bool ConstDataVector<DV>::operator!= (const ConstDataVector& b) const
1015{
1016 return static_cast<const DV&>(*this) != static_cast<const DV&>(b);
1017}
1018
1019
1020//=== Private helpers.
1021
1022
1023/**
1024 * @brief Handle element assignment.
1025 * @param pos Position in the container to assign.
1026 * @param newElem The new element to assign.
1027 *
1028 * The old element is freed if this container owns elements.
1029 * Auxiliary data are copied if appropriate.
1030 */
1031template <class DV>
1032inline
1033void
1034ConstDataVector<DV>::assignElement (typename BaseContainer::iterator pos,
1035 value_type newElem)
1036{
1037 typename DV::value_type pelem ATLAS_THREAD_SAFE =
1038 const_cast<typename DV::value_type> (newElem);
1039 DV::assignElement (pos, pelem);
1040}
1041
1042
1043/**
1044 * @brief Handle element assignment.
1045 * @param pos Position in the container to assign.
1046 * @param newElem The new element to assign.
1047 *
1048 * The container must own its elements.
1049 * Auxiliary data are copied if appropriate.
1050 */
1051template <class DV>
1052inline
1053void
1054ConstDataVector<DV>::assignElement (typename BaseContainer::iterator pos,
1055 std::unique_ptr<const base_value_type> newElem)
1056{
1057 typename DV::value_type pelem ATLAS_THREAD_SAFE =
1058 const_cast<typename DV::value_type> (newElem.release());
1059 std::unique_ptr<typename DV::base_value_type> new_u (pelem);
1060 DV::assignElement (pos, std::move(new_u));
1061}
1062
1063
1064/**
1065 * @brief Handle element assignment from a base pointer.
1066 * @param pos Position in the container to assign.
1067 * @param newElem The new element to assign.
1068 *
1069 * The old element is freed if this container owns elements.
1070 * Auxiliary data are copied if appropriate.
1071 */
1072template <class DV>
1073inline
1074void
1075ConstDataVector<DV>::assignBaseElement (typename BaseContainer::iterator pos,
1076 typename BaseContainer::value_type newElem)
1077{
1078 DV::assignBaseElement (pos, newElem);
1079}
1080
1081
1082/**
1083 * @brief Convert a @c ConstDataVector::iterator to an iterator
1084 * of the base @c DataVector.
1085 * @param it The @c ConstDataVector::iterator to convert.
1086 */
1087template <class DV>
1088inline
1089typename DV::iterator
1090ConstDataVector<DV>::to_base_iterator (iterator it)
1091{
1092 return typename DV::iterator (it.base(), it.container());
1093}
1094
1095
1096/**
1097 * @brief Convert an iterator of the base @c DataVector to
1098 * a @c ConstDataVector::iterator.
1099 * @param it The base @c DataVector iterator to convert.
1100 */
1101template <class DV>
1102inline
1103typename ConstDataVector<DV>::iterator
1104ConstDataVector<DV>::to_my_iterator (typename DV::iterator it)
1105{
1106 return iterator (it.base(), this);
1107}
1108
1109
1110/**
1111 * @brief Convert an iterator of the base @c vector
1112 * an @c ElementProxy for the @c ConstDataVector.
1113 * @param it The base @c vector iterator to convert.
1114 */
1115template <class DV>
1116inline
1117typename ConstDataVector<DV>::ElementProxy
1118ConstDataVector<DV>::to_element_proxy (typename BaseContainer::iterator i)
1119{
1120 return ElementProxy (i, this);
1121}
1122
1123
1124//=== Other helper classes.
1125
1126
1127#ifndef XAOD_STANDALONE
1128
1129
1130/**
1131 * @brief Constructor from a payload object.
1132 * @param data Object to hold in the bucket.
1133 */
1134namespace SG {
1135
1136
1137template <class DV>
1138DVLConstDataVectorBucket<DV>::DVLConstDataVectorBucket
1139 (ConstDataVector<DV>* data)
1140 : DVLDataBucket<DV>
1141 ([] (const DV* dv) { DV* dv_nc ATLAS_THREAD_SAFE = const_cast<DV*> (dv);
1142 return dv_nc; }
1143 (data->asDataVector()))
1144{
1145}
1146
1147
1148/**
1149 * @brief Constructor from a payload object.
1150 * @param data Object to hold in the bucket.
1151 */
1152template <class DV>
1153DVLConstDataVectorBucket<DV>::DVLConstDataVectorBucket
1154 (std::unique_ptr<ConstDataVector<DV> > data)
1155 : DVLDataBucket<DV> (std::unique_ptr<DV>
1156 ([] (const DV* dv) { DV* dv_nc ATLAS_THREAD_SAFE = const_cast<DV*> (dv);
1157 return dv_nc; }
1158 (data.release()->asDataVector())))
1159{
1160}
1161
1162
1163} // namespace SG
1164
1165
1166#endif // not XAOD_STANDALONE