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