ATLAS Offline Software
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 
19 namespace ConstDataVector_detail {
20 
21 
22 /// Functional to cast const away.
23 template <class T>
24 class remove_const
25 {
26 public:
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  */
47 template <class DV>
48 inline
49 ConstDataVector<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  */
63 template <class DV>
64 template <typename... ARGS>
65 inline
66 ConstDataVector<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  */
85 template <class DV>
86 inline
87 ConstDataVector<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  */
107 template <class DV>
108 template <class InputIterator>
109 inline
110 ConstDataVector<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  */
129 template <class DV>
130 inline
131 ConstDataVector<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  */
147 template <class DV>
148 inline
149 ConstDataVector<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  */
163 template <class DV>
164 template <class CONTAINER>
165 ConstDataVector<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  */
187 template <class DV>
188 inline
189 ConstDataVector<DV>&
190 ConstDataVector<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  */
203 template <class DV>
204 inline
205 ConstDataVector<DV>&
206 ConstDataVector<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  */
225 template <class DV>
226 inline
227 ConstDataVector<DV>&
228 ConstDataVector<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  */
244 template <class DV>
245 template <class InputIterator>
246 inline
247 void 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  */
264 template <class DV>
265 inline
266 void 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  */
278 template <class DV>
279 template <class CONTAINER>
280 void 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  */
301 template <class DV>
302 inline
303 typename ConstDataVector<DV>::ElementProxy
304 ConstDataVector<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  */
319 template <class DV>
320 inline
321 typename ConstDataVector<DV>::ElementProxy
322 ConstDataVector<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  */
338 template <class DV>
339 inline
340 typename ConstDataVector<DV>::ElementProxy
341 ConstDataVector<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  */
355 template <class DV>
356 inline
357 typename ConstDataVector<DV>::ElementProxy
358 ConstDataVector<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  */
376 template <class DV>
377 inline
378 typename ConstDataVector<DV>::iterator
379 ConstDataVector<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  */
394 template <class DV>
395 inline
396 typename ConstDataVector<DV>::iterator
397 ConstDataVector<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  */
412 template <class DV>
413 inline
414 typename ConstDataVector<DV>::reverse_iterator
415 ConstDataVector<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  */
430 template <class DV>
431 inline
432 typename ConstDataVector<DV>::reverse_iterator
433 ConstDataVector<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  */
454 template <class DV>
455 inline
456 typename ConstDataVector<DV>::value_type
457 ConstDataVector<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  */
479 template <class DV>
480 inline
481 typename ConstDataVector<DV>::value_type
482 ConstDataVector<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  */
501 template <class DV>
502 inline
503 typename ConstDataVector<DV>::iterator
504 ConstDataVector<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  */
527 template <class DV>
528 inline
529 typename ConstDataVector<DV>::iterator
530 ConstDataVector<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  */
548 template <class DV>
549 template <class InputIterator>
550 inline
551 void 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  */
576 template <class DV>
577 inline
578 typename ConstDataVector<DV>::value_type
579 ConstDataVector<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  */
600 template <class DV>
601 inline
602 typename ConstDataVector<DV>::iterator
603 ConstDataVector<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  */
625 template <class DV>
626 inline
627 void 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  */
645 template <class DV>
646 inline
647 typename ConstDataVector<DV>::iterator
648 ConstDataVector<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  */
665 template <class DV>
666 inline
667 typename ConstDataVector<DV>::iterator
668 ConstDataVector<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  */
684 template <class DV>
685 inline
686 void 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  */
702 template <class DV>
703 inline
704 void 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  */
715 template <class DV>
716 inline
717 void 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  */
744 template <class DV>
745 inline
746 void
747 ConstDataVector<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  */
774 template <class DV>
775 inline
776 void
777 ConstDataVector<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  */
806 template <class DV>
807 inline
808 void
809 ConstDataVector<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  */
841 template <class DV>
842 inline
843 void
844 ConstDataVector<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  */
860 template <class DV>
861 inline
862 const DV*
863 ConstDataVector<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  */
875 template <class DV>
876 const 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  */
891 template <class DV>
892 inline
893 void 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  */
907 template <class DV>
908 inline
909 void 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  */
926 template <class DV>
927 inline
928 void 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  */
942 template <class DV>
943 inline
944 const 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  */
963 template <class DV>
964 inline
965 bool 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<
972 template <class DV>
973 inline
974 bool 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<
981 template <class DV>
982 inline
983 bool 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<
990 template <class DV>
991 inline
992 bool 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  */
1007 template <class DV>
1008 inline
1009 bool 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==
1016 template <class DV>
1017 inline
1018 bool 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  */
1035 template <class DV>
1036 inline
1037 void
1038 ConstDataVector<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  */
1055 template <class DV>
1056 inline
1057 void
1058 ConstDataVector<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  */
1076 template <class DV>
1077 inline
1078 void
1079 ConstDataVector<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  */
1091 template <class DV>
1092 inline
1093 typename DV::iterator
1094 ConstDataVector<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  */
1105 template <class DV>
1106 inline
1107 typename ConstDataVector<DV>::iterator
1108 ConstDataVector<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  */
1119 template <class DV>
1120 inline
1121 typename ConstDataVector<DV>::ElementProxy
1122 ConstDataVector<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  */
1138 namespace SG {
1139 
1140 
1141 template <class DV>
1142 DVLConstDataVectorBucket<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  */
1156 template <class DV>
1157 DVLConstDataVectorBucket<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