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 <boost/iterator/transform_iterator.hpp>
16#include <functional>
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 typedef boost::transform_iterator
556 <ConstDataVector_detail::remove_const<typename DV::base_value_type>,
557 InputIterator>
558 iterator_t;
559 DV::insert (to_base_iterator(position),
560 iterator_t (first),
561 iterator_t (last));
562}
563
564
565/**
566 * @brief Add an element to the end of the collection.
567 * @param pElem The element to add to the collection.
568 *
569 * The container must be an owning container.
570 *
571 * Note: this method may only be called using the most derived
572 * @c DataVector in the hierarchy.
573 *
574 * Returns the pushed pointer.
575 */
576template <class DV>
577inline
578typename ConstDataVector<DV>::value_type
579ConstDataVector<DV>::push_back(std::unique_ptr<const base_value_type> pElem)
580{
581 typename DV::value_type ptmp ATLAS_THREAD_SAFE =
582 const_cast<typename DV::value_type> (pElem.release());
583 std::unique_ptr<typename DV::base_value_type> ptr (ptmp);
584 DV::push_back (std::move (ptr));
585 return DV::back();
586}
587
588
589/**
590 * @brief Add a new element to the collection.
591 * @param position Iterator before which the element will be added.
592 * @param pElem The element to add to the collection.
593 * @return An iterator that points to the inserted data.
594 *
595 * The container must be an owning container.
596 *
597 * Note: this method may only be called using the most derived
598 * @c DataVector in the hierarchy.
599 */
600template <class DV>
601inline
602typename ConstDataVector<DV>::iterator
603ConstDataVector<DV>::insert(iterator position,
604 std::unique_ptr<const base_value_type> pElem)
605{
606 typename DV::value_type ptmp ATLAS_THREAD_SAFE =
607 const_cast<typename DV::value_type> (pElem.release());
608 std::unique_ptr<typename DV::base_value_type> ptr (ptmp);
609 return to_my_iterator
610 (DV::insert (to_base_iterator (position), std::move (ptr)));
611}
612
613
614/**
615 * @brief Add a group of new elements to the collection.
616 * @param position Iterator before which the element will be added.
617 * @param l An initializer list.
618 *
619 * The container's ownership policy will determine if it takes ownership
620 * of the new element.
621 *
622 * Note: this method may only be called using the most derived
623 * @c DataVector in the hierarchy.
624 */
625template <class DV>
626inline
627void ConstDataVector<DV>::insert (iterator position,
628 std::initializer_list<value_type> l)
629{
630 this->insert (position, l.begin(), l.end());
631}
632
633
634//=== Erasure operations.
635
636
637/**
638 * @brief Remove element at a given position.
639 * @param position Iterator pointing to the element to be removed.
640 * @return An iterator pointing to the next element (or @c end()).
641 *
642 * If the container owns its elements, then the pointed-to element
643 * will be deleted.
644 */
645template <class DV>
646inline
647typename ConstDataVector<DV>::iterator
648ConstDataVector<DV>::erase(iterator position)
649{
650 return to_my_iterator (DV::erase (to_base_iterator (position)));
651}
652
653
654/**
655 * @brief Remove a range of elements.
656 * @param first Iterator pointing to the first element to be removed.
657 * @param last Iterator pointing one past the last element to be removed.
658 * @return An iterator pointing to the element pointed to by @a last
659 * prior to erasing (or @c end()).
660 *
661 * If the container owns its elements, then the removed elements
662 * will be deleted. Any duplicates will be removed in this process,
663 * but don't rely on this.
664 */
665template <class DV>
666inline
667typename ConstDataVector<DV>::iterator
668ConstDataVector<DV>::erase(iterator first, iterator last)
669{
670 return to_my_iterator
671 (DV::erase (to_base_iterator (first),
672 to_base_iterator (last)));
673}
674
675
676/**
677 * @brief clear()
678 * @brief Erase all the elements in the collection.
679 *
680 * If the container owns its elements, then the removed elements
681 * will be deleted. Any duplicates will be removed in this process,
682 * but don't rely on this.
683 */
684template <class DV>
685inline
686void ConstDataVector<DV>::clear()
687{
688 DV::clear();
689}
690
691
692/**
693 * @brief Swap this collection with another.
694 * @param rhs The collection with which to swap.
695 *
696 * Ownership is swapped along with the collection content.
697 *
698 * Note: this method may only be called using the most-derived
699 * @c DataVector in the hierarchy. The @a rhs must also be
700 * referenced using the most-derived @c DataVector.
701 */
702template <class DV>
703inline
704void ConstDataVector<DV>::swap (ConstDataVector& rhs)
705{
706 DV::swap (rhs);
707}
708
709
710/**
711 * @brief Swap the referents of two @c DataVector iterators.
712 * @param a The first iterator for the swap.
713 * @param b The second iterator for the swap.
714 */
715template <class DV>
716inline
717void ConstDataVector<DV>::iter_swap (iterator a, iterator b)
718{
719 DV::iter_swap (to_base_iterator (a),
720 to_base_iterator (b));
721}
722
723
724//=== Non-standard operations.
725
726
727/**
728 * @brief Swap one element out of the container.
729 * @param index Index of the element in the container to swap.
730 * @param newElem New element to put in the container.
731 * May be 0.
732 * @param oldElem Reference to receive the element removed from the
733 * container.
734 *
735 * Reference @a oldElem is initialized with element @a index of the
736 * collection (no bounds checking). Then element @a index is set
737 * to @c newElem. If the collection owns its elements, then it will
738 * take ownership of @a newElem and release (without deleting)
739 * the element returned through @a oldElem.
740 *
741 * Note: this method may only be called using the most derived
742 * @c DataVector in the hierarchy.
743 */
744template <class DV>
745inline
746void
747ConstDataVector<DV>::swapElement (size_type index,
748 value_type newElem,
749 reference oldElem)
750{
751 typename DV::value_type pnew ATLAS_THREAD_SAFE = const_cast<typename DV::value_type>(newElem);
752 typename DV::reference rold ATLAS_THREAD_SAFE = const_cast<typename DV::reference>(oldElem);
753 DV::swapElement (index, pnew, rold);
754}
755
756
757/**
758 * @brief Swap one element out of the container.
759 * @param pos The element in the container to swap.
760 * @param newElem New element to put in the container.
761 * May be 0.
762 * @param oldElem Reference to receive the element removed from the
763 * container.
764 *
765 * Reference @a oldElem is initialized with element @a pos of the
766 * collection (no bounds checking). Then element @a index is set
767 * to @c newElem. If the collection owns its elements, then it will
768 * take ownership of @a newElem and release (without deleting)
769 * the element returned through @a oldElem.
770 *
771 * Note: this method may only be called using the most derived
772 * @c DataList in the hierarchy.
773 */
774template <class DV>
775inline
776void
777ConstDataVector<DV>::swapElement (iterator pos,
778 value_type newElem,
779 reference oldElem)
780{
781 typename DV::value_type pnew ATLAS_THREAD_SAFE = const_cast<typename DV::value_type>(newElem);
782 typename DV::reference rold ATLAS_THREAD_SAFE = const_cast<typename DV::reference>(oldElem);
783 DV::swapElement (to_base_iterator(pos), pnew, rold);
784}
785
786
787/**
788 * @brief Swap one element out of the container.
789 * @param index Index of the element in the container to swap.
790 * @param newElem New element to put in the container.
791 * May be 0.
792 * @param oldElem Reference to receive the element removed from the
793 * container.
794 *
795 * Reference @a oldElem is initialized with element @a index of the
796 * collection (no bounds checking). Then element @a index is set
797 * to @c newElem.
798 *
799 * The collection must own its elements to use its interface.
800 * The collection will take ownership of @c newElem and will return
801 * ownership of @c oldElem.
802 *
803 * Note: this method may only be called using the most derived
804 * @c DataVector in the hierarchy.
805 */
806template <class DV>
807inline
808void
809ConstDataVector<DV>::swapElement (size_type index,
810 std::unique_ptr<const base_value_type> newElem,
811 std::unique_ptr<const base_value_type>& oldElem)
812{
813 typename DV::value_type pelem ATLAS_THREAD_SAFE =
814 const_cast<typename DV::value_type> (newElem.release());
815 std::unique_ptr<typename DV::base_value_type> new_u (pelem);
816 std::unique_ptr<typename DV::base_value_type> old_u;
817 DV::swapElement (index, std::move(new_u), old_u);
818 oldElem = std::move (old_u);
819}
820
821
822/**
823 * @brief Swap one element out of the container.
824 * @param pos The element in the container to swap.
825 * @param newElem New element to put in the container.
826 * May be 0.
827 * @param oldElem Reference to receive the element removed from the
828 * container.
829 *
830 * Reference @a oldElem is initialized with element @a pos of the
831 * collection (no bounds checking). Then element @a index is set
832 * to @c newElem.
833 *
834 * The collection must own its elements to use its interface.
835 * The collection will take ownership of @c newElem and will return
836 * ownership of @c oldElem.
837 *
838 * Note: this method may only be called using the most derived
839 * @c DataList in the hierarchy.
840 */
841template <class DV>
842inline
843void
844ConstDataVector<DV>::swapElement (iterator pos,
845 std::unique_ptr<const base_value_type> newElem,
846 std::unique_ptr<const base_value_type>& oldElem)
847{
848 typename DV::value_type pelem ATLAS_THREAD_SAFE =
849 const_cast<typename DV::value_type> (newElem.release());
850 std::unique_ptr<typename DV::base_value_type> new_u (pelem);
851 std::unique_ptr<typename DV::base_value_type> old_u;
852 DV::swapElement (to_base_iterator(pos), std::move(new_u), old_u);
853 oldElem = std::move (old_u);
854}
855
856
857/**
858 * @brief Return a pointer to this object, as a const @c DataVector.
859 */
860template <class DV>
861inline
862const DV*
863ConstDataVector<DV>::asDataVector() const
864{
865 return static_cast<const DV*>(this);
866}
867
868
869/**
870 * @brief Cast from a @c DataVector to a @c ConstDataVector.
871 * @param dv Pointer to object to cast.
872 *
873 * Return @c DV cast to a @c ConstDataVector.
874 */
875template <class DV>
876const ConstDataVector<DV>* ConstDataVector<DV>::fromDataVector (const DV* dv)
877{
878 if (typeid (*dv) == typeid (ConstDataVector))
879 return static_cast<const ConstDataVector*> (dv);
880 return nullptr;
881}
882
883
884/**
885 * @brief Reset indices / reorder aux data after elements have been permuted.
886 * @param beg Start of the range of elements to process.
887 * @param end End of the range of elements to process.
888 *
889 * This is a no-op for @c ConstDataVector.
890 */
891template <class DV>
892inline
893void ConstDataVector<DV>::resortAux (iterator /*beg*/, iterator /*end*/)
894{
895}
896
897
898/**
899 * @brief Erase all the elements in the collection, and reset
900 * the ownership mode.
901 * @param ownPolicy The new ownership policy of the container.
902 *
903 * If the container owns its elements, then the removed elements
904 * will be deleted. Any duplicates will be removed in this process,
905 * but don't rely on this.
906 */
907template <class DV>
908inline
909void ConstDataVector<DV>::clear (SG::OwnershipPolicy ownPolicy)
910{
911 DV::clear (ownPolicy, SG::NEVER_TRACK_INDICES);
912}
913
914
915/**
916 * @fn void clear
917 * @brief Erase all the elements in the collection, and reset
918 * the ownership mode.
919 * @param ownPolicy The new ownership policy of the container.
920 * @param trackIndices The index tracking policy.
921 *
922 * If the container owns its elements, then the removed elements
923 * will be deleted. Any duplicates will be removed in this process,
924 * but don't rely on this.
925 */
926template <class DV>
927inline
928void ConstDataVector<DV>::clear (SG::OwnershipPolicy ownPolicy,
929 SG::IndexTrackingPolicy trackIndices)
930{
931 DV::clear (ownPolicy, trackIndices);
932 if (DV::trackIndices()) std::abort();
933}
934
935
936/**
937 * @brief Convert to @c AuxVectorBase.
938 *
939 * Needed to get @x AuxVectorBase from a @c ConstDataVector.
940 * Present in @c DataVector as well for consistency.
941 */
942template <class DV>
943inline
944const SG::AuxVectorBase& ConstDataVector<DV>::auxbase() const
945{
946 return *this;
947}
948
949
950//=== Relational operators.
951
952
953/**
954 * @brief Vector ordering relation.
955 * @param b A @c ConstDataVector of the same type as @a *this.
956 * @return True iff @a *this is lexicographically less than @a b.
957 *
958 * This is a total ordering relation. It is linear in the size of the
959 * vectors. Comparisons are done on the pointer values of the elements.
960 *
961 * See @c std::lexicographical_compare() for how the determination is made.
962 */
963template <class DV>
964inline
965bool ConstDataVector<DV>::operator< (const ConstDataVector& b) const
966{
967 return static_cast<const DV&>(*this) < static_cast<const DV&>(b);
968}
969
970
971/// Based on operator<
972template <class DV>
973inline
974bool ConstDataVector<DV>::operator> (const ConstDataVector& b) const
975{
976 return static_cast<const DV&>(*this) > static_cast<const DV&>(b);
977}
978
979
980/// Based on operator<
981template <class DV>
982inline
983bool ConstDataVector<DV>::operator<= (const ConstDataVector& b) const
984{
985 return static_cast<const DV&>(*this) <= static_cast<const DV&>(b);
986}
987
988
989/// Based on operator<
990template <class DV>
991inline
992bool ConstDataVector<DV>::operator>= (const ConstDataVector& b) const
993{
994 return static_cast<const DV&>(*this) >= static_cast<const DV&>(b);
995}
996
997
998/**
999 * @brief Vector equality comparison.
1000 * @param b A @c ConstDataVector of the same type as @a *this.
1001 * @return True iff the size and elements of the vectors are equal.
1002 *
1003 * This is an equivalence relation. It is linear in the size of the
1004 * vectors. Vectors are considered equivalent if their sizes are equal,
1005 * and if corresponding elements compare equal.
1006 */
1007template <class DV>
1008inline
1009bool ConstDataVector<DV>::operator== (const ConstDataVector& b) const
1010{
1011 return static_cast<const DV&>(*this) == static_cast<const DV&>(b);
1012}
1013
1014
1015/// Based on operator==
1016template <class DV>
1017inline
1018bool ConstDataVector<DV>::operator!= (const ConstDataVector& b) const
1019{
1020 return static_cast<const DV&>(*this) != static_cast<const DV&>(b);
1021}
1022
1023
1024//=== Private helpers.
1025
1026
1027/**
1028 * @brief Handle element assignment.
1029 * @param pos Position in the container to assign.
1030 * @param newElem The new element to assign.
1031 *
1032 * The old element is freed if this container owns elements.
1033 * Auxiliary data are copied if appropriate.
1034 */
1035template <class DV>
1036inline
1037void
1038ConstDataVector<DV>::assignElement (typename BaseContainer::iterator pos,
1039 value_type newElem)
1040{
1041 typename DV::value_type pelem ATLAS_THREAD_SAFE =
1042 const_cast<typename DV::value_type> (newElem);
1043 DV::assignElement (pos, pelem);
1044}
1045
1046
1047/**
1048 * @brief Handle element assignment.
1049 * @param pos Position in the container to assign.
1050 * @param newElem The new element to assign.
1051 *
1052 * The container must own its elements.
1053 * Auxiliary data are copied if appropriate.
1054 */
1055template <class DV>
1056inline
1057void
1058ConstDataVector<DV>::assignElement (typename BaseContainer::iterator pos,
1059 std::unique_ptr<const base_value_type> newElem)
1060{
1061 typename DV::value_type pelem ATLAS_THREAD_SAFE =
1062 const_cast<typename DV::value_type> (newElem.release());
1063 std::unique_ptr<typename DV::base_value_type> new_u (pelem);
1064 DV::assignElement (pos, std::move(new_u));
1065}
1066
1067
1068/**
1069 * @brief Handle element assignment from a base pointer.
1070 * @param pos Position in the container to assign.
1071 * @param newElem The new element to assign.
1072 *
1073 * The old element is freed if this container owns elements.
1074 * Auxiliary data are copied if appropriate.
1075 */
1076template <class DV>
1077inline
1078void
1079ConstDataVector<DV>::assignBaseElement (typename BaseContainer::iterator pos,
1080 typename BaseContainer::value_type newElem)
1081{
1082 DV::assignBaseElement (pos, newElem);
1083}
1084
1085
1086/**
1087 * @brief Convert a @c ConstDataVector::iterator to an iterator
1088 * of the base @c DataVector.
1089 * @param it The @c ConstDataVector::iterator to convert.
1090 */
1091template <class DV>
1092inline
1093typename DV::iterator
1094ConstDataVector<DV>::to_base_iterator (iterator it)
1095{
1096 return typename DV::iterator (it.base(), it.container());
1097}
1098
1099
1100/**
1101 * @brief Convert an iterator of the base @c DataVector to
1102 * a @c ConstDataVector::iterator.
1103 * @param it The base @c DataVector iterator to convert.
1104 */
1105template <class DV>
1106inline
1107typename ConstDataVector<DV>::iterator
1108ConstDataVector<DV>::to_my_iterator (typename DV::iterator it)
1109{
1110 return iterator (it.base(), this);
1111}
1112
1113
1114/**
1115 * @brief Convert an iterator of the base @c vector
1116 * an @c ElementProxy for the @c ConstDataVector.
1117 * @param it The base @c vector iterator to convert.
1118 */
1119template <class DV>
1120inline
1121typename ConstDataVector<DV>::ElementProxy
1122ConstDataVector<DV>::to_element_proxy (typename BaseContainer::iterator i)
1123{
1124 return ElementProxy (i, this);
1125}
1126
1127
1128//=== Other helper classes.
1129
1130
1131#ifndef XAOD_STANDALONE
1132
1133
1134/**
1135 * @brief Constructor from a payload object.
1136 * @param data Object to hold in the bucket.
1137 */
1138namespace SG {
1139
1140
1141template <class DV>
1142DVLConstDataVectorBucket<DV>::DVLConstDataVectorBucket
1143 (ConstDataVector<DV>* data)
1144 : DVLDataBucket<DV>
1145 ([] (const DV* dv) { DV* dv_nc ATLAS_THREAD_SAFE = const_cast<DV*> (dv);
1146 return dv_nc; }
1147 (data->asDataVector()))
1148{
1149}
1150
1151
1152/**
1153 * @brief Constructor from a payload object.
1154 * @param data Object to hold in the bucket.
1155 */
1156template <class DV>
1157DVLConstDataVectorBucket<DV>::DVLConstDataVectorBucket
1158 (std::unique_ptr<ConstDataVector<DV> > data)
1159 : DVLDataBucket<DV> (std::unique_ptr<DV>
1160 ([] (const DV* dv) { DV* dv_nc ATLAS_THREAD_SAFE = const_cast<DV*> (dv);
1161 return dv_nc; }
1162 (data.release()->asDataVector())))
1163{
1164}
1165
1166
1167} // namespace SG
1168
1169
1170#endif // not XAOD_STANDALONE