ATLAS Offline Software
DataVector.icc
Go to the documentation of this file.
1 // Dear emacs, this is -*- c++ -*-
2 
3 /*
4  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
5 */
6 /**
7  * @file AthContainers/DataVector.icc
8  * @author scott snyder, Paolo Calafiura, etc
9  * @date May 2005; rewritten from earlier version.
10  * @brief An STL vector of pointers that by default owns its pointed-to
11  * elements.
12  * Implementation file.
13  */
14 
15 
16 #include "AthContainers/tools/CompareAndPrint.h"
17 #include "AthContainers/tools/ATHCONTAINERS_ASSERT.h"
18 #include "CxxUtils/releasing_iterator.h"
19 #include <limits>
20 #include <functional>
21 
22 
23 //****************************************************************************
24 // VirtBases
25 //
26 
27 namespace ROOT { namespace Meta { namespace Selection {
28  namespace DataVector_detail {
29  template <class B1, class B2, class B3> class VirtBases;
30  }
31 }}} // ROOT namespace
32 
33 
34 namespace DataVector_detail {
35 
36 /* #define DO_REMOVE_DUPLICATES to activate for debugging purposes (Slow) */
37 // Note: this name should be distinct from the corresponding one in DataList,
38 // even though they're in different namespaces. This due to an apparent
39 // Koenig lookup bug in gccxml 0.9.0.
40 template <class FI>
41 void optimizeMeAway_DV(FI, bool){}
42 /**
43  * @brief Remove duplicates from a @c DataVector before deleting elements.
44  * @param b Start of range to scan.
45  * @param e One past end of range to scan.
46  * @param quiet If true, complain if duplicates are found.
47  * @return One past the last unique elements.
48  *
49  * The elements within the range are sorted, then duplicate elements
50  * are moved to the end. If duplicate elements are found and
51  * @a quiet is @c true, then a complaint will be printed.
52  */
53 template <class ForwIter>
54 ForwIter remove_duplicates(ForwIter b, ForwIter e, bool quiet=false)
55 {
56 #ifdef DO_REMOVE_DUPLICATES
57  std::sort(b, e);
58  return std::unique(b, e, DataModel_detail::CompareAndPrint(quiet));
59 #else
60  optimizeMeAway_DV(b, quiet);
61  return e;
62 #endif
63 }
64 
65 /**
66  * @brief VirtBases for one class.
67  *
68  * @c DataVector<T> derives from this for the case of
69  * @c T deriving virtually from a single class.
70  * It in turn derives from @c B1.
71  */
72 template <class B1>
73 struct VirtBases<B1, DataModel_detail::NoBase, DataModel_detail::NoBase>
74  : virtual public DataVector<B1>
75 {
76  // Make these types available to the derived @c DataVector.
77  typedef typename DataVector<B1>::PtrVector PtrVector;
78  typedef typename DataVector<B1>::size_type size_type;
79  typedef typename DataVector<B1>::difference_type difference_type;
80  typedef typename DataVector<B1>::allocator_type allocator_type;
81  typedef typename DataVector<B1>::Deleter Deleter;
82  // cppcheck-suppress duplInheritedMember; deliberate
83  static constexpr bool must_own = DataVector<B1>::must_own;
84 
85  // We're using virtual derivation.
86  // cppcheck-suppress duplInheritedMember; deliberate
87  static constexpr bool has_virtual = true;
88 
89  // We need to delete the move ctor; otherwise, we get warnings about
90  // a virtual base having a non-trivial move ctor. Then we also need
91  // to explicitly default the ordinary ctors so that they remain visible.
92  VirtBases () = default;
93  VirtBases (const VirtBases&) = default;
94  // default doesn't work here with gcc 4.7; it does with 4.9.
95  VirtBases& operator= (VirtBases&) { return *this; }
96  VirtBases& operator= (VirtBases&&) = delete;
97 
98 
99 protected:
100  // Pass this down to base classes.
101  void clearMostDerived()
102  {
103  DataVector<B1>::clearMostDerived();
104  }
105 
106  // We need these here to prevent ambiguities,
107  // but they shouldn't actually be called.
108  virtual const std::type_info& dv_typeid() const override
109  {
110  return typeid(VirtBases);
111  }
112  virtual const DataModel_detail::DVLInfoBase& dvlinfo_v() const override
113  {
114  return DataVector<B1>::dvlinfo();
115  }
116  virtual void setMostDerived() override
117  {
118  std::abort();
119  }
120 
121 
122  static
123  int baseOffset1 (const char* p, const VirtBases& dv,
124  const std::type_info& ti)
125  {
126  return DataVector<B1>::baseOffset1 (p, dv, ti);
127  }
128 
129 
130 private:
131  typedef typename
132  ROOT::Meta::Selection::
133  DataVector_detail::VirtBases<B1,
134  DataModel_detail::NoBase,
135  DataModel_detail::NoBase>::self self;
136 };
137 
138 
139 /**
140  * @brief VirtBases for two classes.
141  *
142  * @c DataVector<T> derives from this for the case of
143  * @c T deriving from two classes.
144  * It in turn derives from @c B1 and @c B2.
145  */
146 template <class B1, class B2>
147 struct VirtBases<B1, B2, DataModel_detail::NoBase>
148  : virtual public DataVector<B1>,
149  virtual public DataVector<B2>
150 {
151  // Check to be sure that @c B1 and @c B2 have the same ultimate base type.
152  static_assert (std::is_same_v<typename DataVector<B1>::PtrVector,
153  typename DataVector<B2>::PtrVector>);
154 
155  // Make these types available to the derived @c DataVector.
156  typedef typename DataVector<B1>::PtrVector PtrVector;
157  typedef typename DataVector<B1>::size_type size_type;
158  typedef typename DataVector<B1>::difference_type difference_type;
159  typedef typename DataVector<B1>::allocator_type allocator_type;
160  typedef typename DataVector<B1>::Deleter Deleter;
161  // cppcheck-suppress duplInheritedMember; deliberate
162  static constexpr bool must_own = DataVector<B1>::must_own;
163 
164  // We're using virtual derivation.
165  // cppcheck-suppress duplInheritedMember; deliberate
166  static constexpr bool has_virtual = true;
167 
168 
169  // We need to delete the move ctor; otherwise, we get warnings about
170  // a virtual base having a non-trivial move ctor. Then we also need
171  // to explicitly default the ordinary ctors so that they remain visible.
172  VirtBases () = default;
173  VirtBases (const VirtBases&) = default;
174  // default doesn't work here with gcc 4.7; it does with 4.9.
175  VirtBases& operator= (VirtBases&) { return *this; }
176  VirtBases& operator= (VirtBases&&) = delete;
177 
178 
179 protected:
180  // Pass this down to base classes.
181  void clearMostDerived()
182  {
183  DataVector<B1>::clearMostDerived();
184  DataVector<B2>::clearMostDerived();
185  }
186 
187  // We need these here to prevent ambiguities,
188  // but they shouldn't actually be called.
189  virtual const std::type_info& dv_typeid() const override
190  {
191  return typeid(VirtBases);
192  }
193  virtual const DataModel_detail::DVLInfoBase& dvlinfo_v() const override
194  {
195  return DataVector<B1>::dvlinfo();
196  }
197  virtual void setMostDerived() override
198  {
199  std::abort();
200  }
201 
202 
203  static
204  int baseOffset1 (const char* p, const VirtBases& dv,
205  const std::type_info& ti)
206  {
207  int ret = DataVector<B1>::baseOffset1 (p, dv, ti);
208  if (ret >= 0)
209  return ret;
210  return DataVector<B2>::baseOffset1 (p, dv, ti);
211  }
212 
213 
214 private:
215  typedef typename
216  ROOT::Meta::Selection::
217  DataVector_detail::VirtBases<B1, B2,
218  DataModel_detail::NoBase>::self self;
219 };
220 
221 
222 /**
223  * @brief VirtBases for three classes.
224  *
225  * @c DataVector<T> derives from this for the case of
226  * @c T deriving from three classes.
227  * It in turn derives from @c B1, @c B2, and @c B3.
228  */
229 template <class B1, class B2, class B3>
230 struct VirtBases
231  : virtual public DataVector<B1>,
232  virtual public DataVector<B2>,
233  virtual public DataVector<B3>
234 {
235  // Check to be sure that @c B1, @c B2, and @c B3 have the same
236  // ultimate base type.
237  static_assert (std::is_same_v<typename DataVector<B1>::PtrVector,
238  typename DataVector<B2>::PtrVector>);
239  static_assert (std::is_same_v<typename DataVector<B1>::PtrVector,
240  typename DataVector<B3>::PtrVector>);
241 
242 
243  // Make these types available to the derived @c DataVector.
244  typedef typename DataVector<B1>::PtrVector PtrVector;
245  typedef typename DataVector<B1>::size_type size_type;
246  typedef typename DataVector<B1>::difference_type difference_type;
247  typedef typename DataVector<B1>::allocator_type allocator_type;
248  typedef typename DataVector<B1>::Deleter Deleter;
249  // cppcheck-suppress duplInheritedMember; deliberate
250  static constexpr bool must_own = DataVector<B1>::must_own;
251 
252  // We're using virtual derivation.
253  // cppcheck-suppress duplInheritedMember; deliberate
254  static constexpr bool has_virtual = true;
255 
256 
257  // We need to delete the move ctor; otherwise, we get warnings about
258  // a virtual base having a non-trivial move ctor. Then we also need
259  // to explicitly default the ordinary ctors so that they remain visible.
260  VirtBases () = default;
261  VirtBases (const VirtBases&) = default;
262  // default doesn't work here with gcc 4.7; it does with 4.9.
263  VirtBases& operator= (VirtBases&) { return *this; }
264  VirtBases& operator= (VirtBases&&) = delete;
265 
266 
267 protected:
268  // Pass this down to base classes.
269  void clearMostDerived()
270  {
271  DataVector<B1>::clearMostDerived();
272  DataVector<B2>::clearMostDerived();
273  DataVector<B3>::clearMostDerived();
274  }
275 
276  // We need these here to prevent ambiguities,
277  // but they shouldn't actually be called.
278  virtual const std::type_info& dv_typeid() const override
279  {
280  return typeid(VirtBases);
281  }
282  virtual const DataModel_detail::DVLInfoBase& dvlinfo_v() const override
283  {
284  return DataVector<B1>::dvlinfo();
285  }
286  virtual void setMostDerived() override
287  {
288  std::abort();
289  }
290 
291 
292  static
293  int baseOffset1 (const char* p, const VirtBases& dv,
294  const std::type_info& ti)
295  {
296  int ret = DataVector<B1>::baseOffset1 (p, dv, ti);
297  if (ret >= 0)
298  return ret;
299  ret = DataVector<B2>::baseOffset1 (p, dv, ti);
300  if (ret >= 0)
301  return ret;
302  return DataVector<B3>::baseOffset1 (p, dv, ti);
303  }
304 
305 
306 private:
307  typedef typename
308  ROOT::Meta::Selection::DataVector_detail::VirtBases<B1, B2, B3>::self
309  self;
310 };
311 
312 
313 } // namespace DataVector_detail
314 
315 
316 namespace ROOT { namespace Meta { namespace Selection {
317 namespace DataVector_detail {
318 
319 template< class B1, class B2, class B3 >
320 class VirtBases : KeepFirstTemplateArguments< 1 >, SelectNoInstance
321 {
322 
323 public:
324  /// A helper typedef
325  typedef DataVector_detail::VirtBases< B1, B2, B3 > self;
326 
327 };
328 
329 }
330 }}} // ROOT namespace
331 
332 
333 //****************************************************************************
334 // Generic (derived) DataVector implementation.
335 //
336 
337 
338 //=== Constructors, destructors, assignment.
339 
340 
341 /**
342  * @brief Default constructor.
343  * @param ownPolicy The ownership mode for the container.
344  * @param trackIndices The index tracking policy.
345  *
346  * By default, a @c DataVector will own its elements.
347  * To avoid this, pass @c SG::VIEW_ELEMENTS for @a ownPolicy.
348  *
349  * Note that we do the complete initialization here in the derived class,
350  * using the default constructors for the base classes. The reason
351  * for this is to be able to deal nicely with the virtual derivation
352  * case. We can arrange to call the proper base class from here to get
353  * things initialized in the virtual derivation case. But then anyone
354  * who derives from us must also know to explicitly reference that base
355  * class. Doing the initialization explicitly here means that other classes
356  * who derive from us need only know about the most derived DataVector
357  * class.
358  */
359 template <class T, class BASE>
360 inline
361 DataVector<T, BASE>::DataVector
362  (SG::OwnershipPolicy ownPolicy /*= SG::OWN_ELEMENTS*/,
363  SG::IndexTrackingPolicy trackIndices /*= SG::DEFAULT_TRACK_INDICES*/)
364 {
365  this->m_ownPolicy = ownPolicy;
366  this->template initAuxVectorBase<DataVector> (ownPolicy, trackIndices);
367  this->m_isMostDerived = true;
368  BASE::clearMostDerived();
369 }
370 
371 
372 /**
373  * @brief Sized constructor.
374  * @param n The size of the container.
375  * @param ownPolicy The ownership mode for the container.
376  * @param trackIndices The index tracking policy.
377  *
378  * Note that unlike the standard vector constructor, you can't specify
379  * an initial value here. The container will be initialized with 0's.
380  *
381  * By default, a @c DataVector will own its elements.
382  * To avoid this, pass @c SG::VIEW_ELEMENTS for @a ownPolicy.
383  *
384  * Note that we do the complete initialization here in the derived class,
385  * using the default constructors for the base classes. The reason
386  * for this is to be able to deal nicely with the virtual derivation
387  * case. We can arrange to call the proper base class from here to get
388  * things initialized in the virtual derivation case. But then anyone
389  * who derives from us must also know to explicitly reference that base
390  * class. Doing the initialization explicitly here means that other classes
391  * who derive from us need only know about the most derived DataVector
392  * class.
393  */
394 template <class T, class BASE>
395 inline
396 DataVector<T, BASE>::DataVector
397  (size_type n,
398  SG::OwnershipPolicy ownPolicy /*= SG::OWN_ELEMENTS*/,
399  SG::IndexTrackingPolicy trackIndices /*=SG::DEFAULT_TRACK_INDICES*/)
400 {
401  this->m_ownPolicy = ownPolicy;
402  this->template initAuxVectorBase<DataVector> (ownPolicy, trackIndices);
403  this->m_isMostDerived = true;
404  BASE::clearMostDerived();
405  this->m_pCont.resize (n);
406 }
407 
408 
409 /**
410  * @brief Move constructor.
411  * @param rhs The container from which to move.
412  *
413  * Any auxiliary data will be moved along with the container contents.
414  */
415 template <class T, class BASE>
416 DataVector<T, BASE>::DataVector (DataVector&& rhs) noexcept
417 {
418  SG::AuxVectorBase::operator= (std::move (rhs));
419  this->m_ownPolicy = rhs.m_ownPolicy;
420  this->m_pCont = std::move (rhs.m_pCont);
421  this->m_deleter = std::move(rhs.m_deleter);
422  rhs.m_deleter = nullptr;
423 
424  // Need to reset the container pointer on elements.
425  this->setIndices (this->begin(), this->end());
426  this->m_isMostDerived = true;
427 }
428 
429 
430 /**
431  * @brief Constructor from iterators.
432  * @param first The start of the range to put in the new container.
433  * @param last The end of the range to put in the new container.
434  * @param ownPolicy The ownership mode for the container.
435  * @param trackIndices The index tracking policy.
436  * @param store An associated auxiliary data store.
437  *
438  * By default, a view container is made, which does not own its elements.
439  * To have the container take ownership of the pointers passed
440  * to this constructor, pass @c SG::OWN_ELEMENTS for @a ownPolicy.
441  *
442  * Note that we do the complete initialization here in the derived class,
443  * using the default constructors for the base classes. The reason
444  * for this is to be able to deal nicely with the virtual derivation
445  * case. We can arrange to call the proper base class from here to get
446  * things initialized in the virtual derivation case. But then anyone
447  * who derives from us must also know to explicitly reference that base
448  * class. Doing the initialization explicitly here means that other classes
449  * who derive from us need only know about the most derived DataVector
450  * class.
451  */
452 template <class T, class BASE>
453 template <class InputIterator>
454 inline
455 DataVector<T, BASE>::DataVector
456  (InputIterator first,
457  InputIterator last,
458  SG::OwnershipPolicy ownPolicy /*= SG::VIEW_ELEMENTS*/,
459  SG::IndexTrackingPolicy trackIndices /*= SG::DEFAULT_INDEX_TRACKING*/,
460  SG::IAuxStore* store /*= 0*/)
461 {
462  // Make sure that the input iterator can actually be converted
463  // to a T*. Lets us give a compilation error for this:
464  // DATAVECTOR_BASE(D, B);
465  // B* bb[] = ...
466  // DataVector<D> d (bb, bb+1);
467  // which would otherwise compile.
468  //FIXME: Rewrite using concepts once we're using c++20.
469  using ittype = typename std::iterator_traits<InputIterator>::value_type;
470  static_assert (std::is_convertible_v<ittype, const T*> ||
471  std::is_convertible_v<ittype, std::unique_ptr<T> >);
472 
473  this->m_ownPolicy = ownPolicy;
474  this->template initAuxVectorBase<DataVector> (ownPolicy, trackIndices);
475  this->m_isMostDerived = true;
476  BASE::clearMostDerived();
477  if (store)
478  this->setStore (store);
479  insert (this->begin(), first, last);
480 }
481 
482 
483 /**
484  * @brief Constructor from an initializer list.
485  * @param l An initializer list.
486  * @param ownPolicy The ownership mode for the container.
487  * @param trackIndices The index tracking policy.
488  * @param store An associated auxiliary data store.
489  *
490  *
491  * A @c DataVector constructed this way will *not* own its elements
492  * by default. To change this, pass @c SG::OWN_ELEMENTS for @a ownPolicy.
493  *
494  * Note that we do the complete initialization here in the derived class,
495  * using the default constructors for the base classes. The reason
496  * for this is to be able to deal nicely with the virtual derivation
497  * case. We can arrange to call the proper base class from here to get
498  * things initialized in the virtual derivation case. But then anyone
499  * who derives from us must also know to explicitly reference that base
500  * class. Doing the initialization explicitly here means that other classes
501  * who derive from us need only know about the most derived DataVector
502  * class.
503  */
504 template <class T, class BASE>
505 inline
506 DataVector<T, BASE>::DataVector
507  (std::initializer_list<value_type> l,
508  SG::OwnershipPolicy ownPolicy /*= SG::VIEW_ELEMENTS*/,
509  SG::IndexTrackingPolicy trackIndices /*= SG::DEFAULT_INDEX_TRACKING*/,
510  SG::IAuxStore* store /*= 0*/)
511  : DataVector (l.begin(), l.end(), ownPolicy, trackIndices, store)
512 {
513 }
514 
515 
516 /**
517  * @brief Assignment operator.
518  * @param rhs The DataVector from which to assign.
519  * @return This object.
520  *
521  * This is a `shallow' copy; after the completion of this, the DataVector
522  * will not own its elements. Any elements it owned prior to this call
523  * will be released.
524  *
525  * Note: this method may only be called using the most derived
526  * @c DataVector in the hierarchy.
527  */
528 template <class T, class BASE>
529 inline
530 DataVector<T, BASE>& DataVector<T, BASE>::operator= (const DataVector& rhs)
531 {
532  if (&rhs != this) {
533  // Ensure we're not being called via a base class.
534  testInsert ("assignment operator");
535  this->clear(); // Release any currently-owned elements.
536  this->m_ownPolicy = SG::VIEW_ELEMENTS;
537  this->setStore ((SG::IConstAuxStore*)0);
538  this->template initAuxVectorBase<DataVector>(this->m_ownPolicy,
539  SG::DEFAULT_TRACK_INDICES);
540  this->m_pCont = rhs.m_pCont;
541  }
542  return *this;
543 }
544 
545 
546 /**
547  * @brief Move assignment.
548  * @param rhs The container from which to move.
549  *
550  * Any auxiliary data will be moved along with the container contents.
551  *
552  * (Can't be noexcept because testInsert() can throw.)
553  */
554 template <class T, class BASE>
555 DataVector<T, BASE>&
556 DataVector<T, BASE>::operator= (DataVector<T, BASE>&& rhs)
557 {
558  if (this != &rhs) {
559  // Ensure we're not being called via a base class.
560  testInsert ("assignment operator");
561 
562  this->clear(); // Release any currently-owned elements.
563 
564  SG::AuxVectorBase::operator= (std::move (rhs));
565  this->m_ownPolicy = rhs.m_ownPolicy;
566  this->m_pCont = std::move (rhs.m_pCont);
567 
568  delete this->m_deleter;
569  this->m_deleter = std::move(rhs.m_deleter);
570  rhs.m_deleter = nullptr;
571 
572  // Need to reset the container pointer on elements.
573  this->setIndices (this->begin(), this->end());
574  }
575  return *this;
576 }
577 
578 
579 /**
580  * @brief Assignment operator, from an initializer list.
581  * @param l An initializer list.
582  * @return This object.
583  *
584  * This is equivalent to @c assign.
585  * Any existing owned elements will be released.
586  * The @c DataVector's ownership policy determines whether it will take
587  * ownership of the new elements.
588  */
589 template <class T, class BASE>
590 inline
591 DataVector<T, BASE>&
592 DataVector<T, BASE>::operator= (std::initializer_list<value_type> l)
593 {
594  this->assign (l.begin(), l.end());
595  return *this;
596 }
597 
598 
599 /**
600  * @brief Assign from iterators.
601  * @param first The start of the range to put in the container.
602  * @param last The end of the range to put in the container.
603  *
604  * Any existing owned elements will be released.
605  * The @c DataVector's ownership policy determines whether it will take
606  * ownership of the new elements.
607  */
608 template <class T, class BASE>
609 template <class InputIterator>
610 void DataVector<T, BASE>::assign(InputIterator first, InputIterator last)
611 {
612  // Ensure we're not being called via a base class.
613  testInsert ("assign");
614  this->clear(); // Release any currently-owned elements.
615  insert(begin(), first, last);
616 }
617 
618 
619 /**
620  * @brief Assign from an initializer list.
621  * @param l An initializer list.
622  *
623  * Any existing owned elements will be released.
624  * The @c DataVector's ownership policy determines whether it will take
625  * ownership of the new elements.
626  */
627 template <class T, class BASE>
628 void DataVector<T, BASE>::assign(std::initializer_list<value_type> l)
629 {
630  this->assign (l.begin(), l.end());
631 }
632 
633 
634 //=== Size and capacity.
635 
636 
637 /**
638  * @fn size_type size() const
639  * @brief Returns the number of elements in the collection.
640  */
641 template <class T, class BASE>
642 inline
643 typename DataVector<T, BASE>::size_type
644 DataVector<T, BASE>::size() const noexcept
645 {
646  return this->m_pCont.size();
647 }
648 
649 
650 /**
651  * @brief Resizes the collection to the specified number of elements.
652  * @param sz The new size of the collection.
653  *
654  * Note that this function differs from the standard in that it does
655  * not allow specifying the value of any inserted elements.
656  * They will always be 0.
657  *
658  * If the container is shrunk, elements will be deleted as with @c erase().
659  */
660 template <class T, class BASE>
661 void DataVector<T, BASE>::resize(size_type sz)
662 {
663  if (sz < this->size()) {
664  this->erase (this->begin()+sz, this->end());
665  } else {
666  this->m_pCont.insert(this->m_pCont.end(), sz - this->m_pCont.size(), 0);
667  SG::AuxVectorBase::resize<DataVector> (sz);
668  }
669 }
670 
671 
672 /**
673  * @brief Attempt to preallocate enough memory for a specified number
674  * of elements.
675  * @param n Number of elements required.
676  */
677 template <class T, class BASE>
678 inline
679 void DataVector<T, BASE>::reserve (size_type n)
680 {
681  this->m_pCont.reserve (n);
682  SG::AuxVectorBase::reserve<DataVector> (n);
683 }
684 
685 
686 //=== Element access.
687 
688 
689 /**
690  * @brief Access an element, as an rvalue.
691  * @param n Array index to access.
692  * @return The element at @a n.
693  *
694  * No bounds checking is done.
695  * Note that we return a @c const @c T* rather than a reference.
696  */
697 template <class T, class BASE>
698 inline
699 const T* DataVector<T, BASE>::operator[] (size_type n) const
700 {
701  return do_cast(this->m_pCont[n]);
702 }
703 
704 
705 /**
706  * @brief Access an element, as an rvalue.
707  * @param n Array index to access.
708  * @return The element at @a n.
709  *
710  * This is a synonym for operator[] const, to be used when calling from root
711  * (where we can't readily call just the const version of a method).
712  */
713 template <class T, class BASE>
714 inline
715 const T* DataVector<T, BASE>::get (size_type n) const
716 {
717  return do_cast(this->m_pCont[n]);
718 }
719 
720 
721 /**
722  * @brief Access an element, as an lvalue.
723  * @param n Array index to access.
724  * @return Proxy to the element at @a n.
725  *
726  * No bounds checking is done.
727  * Note that we return a proxy object rather than a reference;
728  * the proxy will handle deleting an owned element if it's assigned to.
729  */
730 template <class T, class BASE>
731 inline
732 typename DataVector<T, BASE>::ElementProxy
733 DataVector<T, BASE>::operator[] (size_type n)
734 {
735  return ElementProxy (this->m_pCont.begin() + n, this);
736 }
737 
738 
739 /**
740  * @brief Access an element, as an rvalue.
741  * @param n Array index to access.
742  * @return The element at @a n.
743  *
744  * Will raise @c std::out_of_range if the index is out-of-bounds.
745  * Note that we return a @c const @c T* rather than a reference.
746  */
747 template <class T, class BASE>
748 inline
749 const T* DataVector<T, BASE>::at (size_type n) const
750 {
751  return do_cast(this->m_pCont.at(n));
752 }
753 
754 
755 /**
756  * @brief Access an element, as an lvalue.
757  * @param n Array index to access.
758  * @return Proxy to the element at @a n.
759  *
760  * Will raise @c std::out_of_range if the index is out-of-bounds.
761  * Note that we return a proxy object rather than a reference;
762  * the proxy will handle deleting an owned element if it's assigned to.
763  */
764 template <class T, class BASE>
765 inline
766 typename DataVector<T, BASE>::ElementProxy
767 DataVector<T, BASE>::at (size_type n)
768 {
769  // Can't use m_pCont's at here, because we need an iterator.
770  // So we have to do the bounds check ourselves.
771  if (n >= this->size())
772  throw std::out_of_range ("DataVector::at range check");
773  return ElementProxy (this->m_pCont.begin() + n, this);
774 }
775 
776 
777 /**
778  * @brief Access the first element in the collection as an rvalue.
779  * @return The first element in the collection.
780  *
781  * No checking is done to ensure that the container is not empty.
782  * Note that we return a @c const @c T* rather than a reference.
783  */
784 template <class T, class BASE>
785 inline
786 const T* DataVector<T, BASE>::front() const
787 {
788  return do_cast (this->m_pCont.front());
789 }
790 
791 
792 /**
793  * @brief Access the last element in the collection as an rvalue.
794  * @return The last element in the collection.
795  *
796  * No checking is done to ensure that the container is not empty.
797  * Note that we return a @c const @c T* rather than a reference.
798  */
799 template <class T, class BASE>
800 inline
801 const T* DataVector<T, BASE>::back() const
802 {
803  return do_cast (this->m_pCont.back());
804 }
805 
806 
807 /**
808  * @brief Access the first element in the collection as an lvalue.
809  * @return Proxy to the first element in the collection.
810  *
811  * No checking is done to ensure that the container is not empty.
812  * Note that we return a proxy object rather than a reference;
813  * the proxy will handle deleting an owned element if it's assigned to.
814  */
815 template <class T, class BASE>
816 inline
817 typename DataVector<T, BASE>::ElementProxy
818 DataVector<T, BASE>::front ()
819 {
820  return ElementProxy (this->m_pCont.begin(), this);
821 }
822 
823 
824 /**
825  * @brief Access the last element in the collection as an lvalue.
826  * @return Proxy to the last element in the collection.
827  *
828  * No checking is done to ensure that the container is not empty.
829  * Note that we return a proxy object rather than a reference;
830  * the proxy will handle deleting an owned element if it's assigned to.
831  */
832 template <class T, class BASE>
833 inline
834 typename DataVector<T, BASE>::ElementProxy
835 DataVector<T, BASE>::back ()
836 {
837  return ElementProxy (this->m_pCont.end()-1, this);
838 }
839 
840 
841 //=== Iterator creation.
842 
843 
844 /**
845  * @brief Return a @c const_iterator pointing at the beginning
846  * of the collection.
847  * @return A @c const_iterator.
848  *
849  * Note that dereferencing the iterator will yield a @c const @c T* rather
850  * than a reference.
851  */
852 template <class T, class BASE>
853 inline
854 typename DataVector<T, BASE>::const_iterator
855 DataVector<T, BASE>::begin() const noexcept
856 {
857  return const_iterator (this->m_pCont.begin());
858 }
859 
860 
861 /**
862  * @brief Return a @c const_iterator pointing past the end
863  * of the collection.
864  * @return A @c const_iterator.
865  *
866  * Note that dereferencing the iterator will yield a @c const @c T* rather
867  * than a reference.
868  */
869 template <class T, class BASE>
870 inline
871 typename DataVector<T, BASE>::const_iterator
872 DataVector<T, BASE>::end() const noexcept
873 {
874  return const_iterator (this->m_pCont.end());
875 }
876 
877 
878 /**
879  * @brief Return an @c iterator pointing at the beginning
880  * of the collection.
881  * @return An @c iterator.
882  *
883  * Note that dereferencing the iterator will yield a proxy rather
884  * than a reference; the proxy will handle deleting an owned element
885  * if it's assigned to.
886  */
887 template <class T, class BASE>
888 inline
889 typename DataVector<T, BASE>::iterator
890 DataVector<T, BASE>::begin() noexcept
891 {
892  return iterator (this->m_pCont.begin(), this);
893 }
894 
895 
896 /**
897  * @brief Return an @c iterator pointing past the end
898  * of the collection.
899  * @return An @c iterator.
900  *
901  * Note that dereferencing the iterator will yield a proxy rather
902  * than a reference; the proxy will handle deleting an owned element
903  * if it's assigned to.
904  */
905 template <class T, class BASE>
906 inline
907 typename DataVector<T, BASE>::iterator
908 DataVector<T, BASE>::end() noexcept
909 {
910  return iterator (this->m_pCont.end(), this);
911 }
912 
913 
914 /**
915  * @brief Return a @c const_reverse_iterator pointing past the end
916  * of the collection.
917  * @return A @c const_reverse_iterator.
918  *
919  * Note that dereferencing the iterator will yield a @c const @c T* rather
920  * than a reference.
921  */
922 template <class T, class BASE>
923 inline
924 typename DataVector<T, BASE>::const_reverse_iterator
925 DataVector<T, BASE>::rbegin() const noexcept
926 {
927  return const_reverse_iterator (end());
928 }
929 
930 
931 /**
932  * @brief Return a @c const_reverse_iterator pointing at the beginning
933  * of the collection.
934  * @return A @c const_reverse_iterator.
935  *
936  * Note that dereferencing the iterator will yield a @c const @c T* rather
937  * than a reference.
938  */
939 template <class T, class BASE>
940 inline
941 typename DataVector<T, BASE>::const_reverse_iterator
942 DataVector<T, BASE>::rend() const noexcept
943 {
944  return const_reverse_iterator (begin());
945 }
946 
947 
948 /**
949  * @brief Return a @c reverse_iterator pointing past the end
950  * of the collection.
951  * @return A @c reverse_iterator.
952  *
953  * Note that dereferencing the iterator will yield a proxy rather
954  * than a reference; the proxy will handle deleting an owned element
955  * if it's assigned to.
956  */
957 template <class T, class BASE>
958 inline
959 typename DataVector<T, BASE>::reverse_iterator
960 DataVector<T, BASE>::rbegin() noexcept
961 {
962  return reverse_iterator (iterator (this->m_pCont.end(), this));
963 }
964 
965 
966 /**
967  * @brief Return a @c reverse_iterator pointing at the beginning
968  * of the collection.
969  * @return A @c reverse_iterator.
970  *
971  * Note that dereferencing the iterator will yield a proxy rather
972  * than a reference; the proxy will handle deleting an owned element
973  * if it's assigned to.
974  */
975 template <class T, class BASE>
976 inline
977 typename DataVector<T, BASE>::reverse_iterator
978 DataVector<T, BASE>::rend() noexcept
979 {
980  return reverse_iterator (iterator (this->m_pCont.begin(), this));
981 }
982 
983 
984 /**
985  * @brief Return a @c const_iterator pointing at the beginning
986  * of the collection.
987  * @return A @c const_iterator.
988  *
989  * Note that dereferencing the iterator will yield a @c const @c T* rather
990  * than a reference.
991  */
992 template <class T, class BASE>
993 inline
994 typename DataVector<T, BASE>::const_iterator
995 DataVector<T, BASE>::cbegin() const noexcept
996 {
997  return const_iterator (this->m_pCont.begin());
998 }
999 
1000 
1001 /**
1002  * @brief Return a @c const_iterator pointing past the end
1003  * of the collection.
1004  * @return A @c const_iterator.
1005  *
1006  * Note that dereferencing the iterator will yield a @c const @c T* rather
1007  * than a reference.
1008  */
1009 template <class T, class BASE>
1010 inline
1011 typename DataVector<T, BASE>::const_iterator
1012 DataVector<T, BASE>::cend() const noexcept
1013 {
1014  return const_iterator (this->m_pCont.end());
1015 }
1016 
1017 
1018 /**
1019  * @brief Return a @c const_reverse_iterator pointing past the end
1020  * of the collection.
1021  * @return A @c const_reverse_iterator.
1022  *
1023  * Note that dereferencing the iterator will yield a @c const @c T* rather
1024  * than a reference.
1025  */
1026 template <class T, class BASE>
1027 inline
1028 typename DataVector<T, BASE>::const_reverse_iterator
1029 DataVector<T, BASE>::crbegin() const noexcept
1030 {
1031  return const_reverse_iterator (cend());
1032 }
1033 
1034 
1035 /**
1036  * @brief Return a @c const_reverse_iterator pointing at the beginning
1037  * of the collection.
1038  * @return A @c const_reverse_iterator.
1039  *
1040  * Note that dereferencing the iterator will yield a @c const @c T* rather
1041  * than a reference.
1042  */
1043 template <class T, class BASE>
1044 inline
1045 typename DataVector<T, BASE>::const_reverse_iterator
1046 DataVector<T, BASE>::crend() const noexcept
1047 {
1048  return const_reverse_iterator (cbegin());
1049 }
1050 
1051 
1052 //=== Insertion operations.
1053 
1054 
1055 /**
1056  * @brief Add an element to the end of the collection.
1057  * @param pElem The element to add to the collection.
1058  *
1059  * The container's ownership policy will determine if it takes ownership
1060  * of the new element.
1061  *
1062  * Note: this method may only be called using the most derived
1063  * @c DataVector in the hierarchy.
1064  *
1065  * Returns the pushed pointer.
1066  */
1067 template <class T, class BASE>
1068 inline
1069 typename DataVector<T, BASE>::value_type
1070 DataVector<T, BASE>::push_back(value_type pElem)
1071 {
1072  // Ensure we're not being called via a base class.
1073  testInsert ("push_back");
1074  this->m_pCont.push_back(static_cast<typename PtrVector::value_type>(pElem));
1075  SG::AuxVectorBase::resize<DataVector> (this->size());
1076  if (pElem)
1077  this->moveAux (this->size()-1, pElem, false, true);
1078  return pElem;
1079 }
1080 
1081 
1082 /**
1083  * @brief Add an element to the end of the collection.
1084  * @param pElem The element to add to the collection.
1085  *
1086  * The container must be an owning container.
1087  *
1088  * Note: this method may only be called using the most derived
1089  * @c DataVector in the hierarchy.
1090  *
1091  * Returns the pushed pointer.
1092  */
1093 template <class T, class BASE>
1094 inline
1095 typename DataVector<T, BASE>::value_type
1096 DataVector<T, BASE>::push_back(std::unique_ptr<base_value_type> pElem)
1097 {
1098  // Container must own its elements.
1099  if (this->m_ownPolicy != SG::OWN_ELEMENTS)
1100  SG::throwExcNonowningContainer();
1101 
1102  // Ensure we're not being called via a base class.
1103  testInsert ("push_back");
1104  value_type ptr = pElem.release();
1105  this->m_pCont.push_back(ptr);
1106  SG::AuxVectorBase::resize<DataVector> (this->size());
1107  if (ptr)
1108  this->moveAux (this->size()-1, ptr, false, true);
1109  return ptr;
1110 }
1111 
1112 
1113 /**
1114  * @brief Add an element to the end of the collection.
1115  * @param pElem The element to add to the collection.
1116  *
1117  * The container's ownership policy will determine if it takes ownership
1118  * of the new element.
1119  *
1120  * Note: this method may only be called using the most derived
1121  * @c DataVector in the hierarchy.
1122  *
1123  * For @c DataVector, this is like the same as @c push_back, and
1124  * it returns the pushed element.
1125  * It's included just for interface compatibility with `std::vector`.
1126  */
1127 template <class T, class BASE>
1128 inline
1129 typename DataVector<T, BASE>::value_type
1130 DataVector<T, BASE>::emplace_back(value_type pElem)
1131 {
1132  return this->push_back (pElem);
1133 }
1134 
1135 
1136 /**
1137  * @brief Add a new element to the collection.
1138  * @param position Iterator before which the element will be added.
1139  * @param pElem The element to add to the collection.
1140  * @return An iterator that points to the inserted data.
1141  *
1142  * The container's ownership policy will determine if it takes ownership
1143  * of the new element.
1144  *
1145  * Note: this method may only be called using the most derived
1146  * @c DataVector in the hierarchy.
1147  */
1148 template <class T, class BASE>
1149 typename DataVector<T, BASE>::iterator
1150 DataVector<T, BASE>::insert(iterator position, value_type pElem)
1151 {
1152  // Ensure we're not being called via a base class.
1153  testInsert ("insert");
1154  iterator ret (this->m_pCont.insert(position.base(), pElem), this);
1155  this->shift (ret - this->begin(), 1);
1156  this->moveAux (ret-this->begin(), pElem, false, true);
1157  return ret;
1158 }
1159 
1160 
1161 /**
1162  * @brief Add a new element to the collection.
1163  * @param position Iterator before which the element will be added.
1164  * @param pElem The element to add to the collection.
1165  * @return An iterator that points to the inserted data.
1166  *
1167  * The container must be an owning container.
1168  *
1169  * Note: this method may only be called using the most derived
1170  * @c DataVector in the hierarchy.
1171  */
1172 template <class T, class BASE>
1173 typename DataVector<T, BASE>::iterator
1174 DataVector<T, BASE>::insert(iterator position,
1175  std::unique_ptr<base_value_type> pElem)
1176 {
1177  // Container must own its elements.
1178  if (this->m_ownPolicy != SG::OWN_ELEMENTS)
1179  SG::throwExcNonowningContainer();
1180 
1181  // Ensure we're not being called via a base class.
1182  testInsert ("insert");
1183  value_type ptr = pElem.release();
1184  iterator ret (this->m_pCont.insert(position.base(), ptr), this);
1185  this->shift (ret - this->begin(), 1);
1186  this->moveAux (ret-this->begin(), ptr, false, true);
1187  return ret;
1188 }
1189 
1190 
1191 /**
1192  * @brief Add a new element to the collection.
1193  * @param position Iterator before which the element will be added.
1194  * @param pElem The element to add to the collection.
1195  * @return An iterator that points to the inserted data.
1196  *
1197  * The container's ownership policy will determine if it takes ownership
1198  * of the new element.
1199  *
1200  * Note: this method may only be called using the most derived
1201  * @c DataVector in the hierarchy.
1202  *
1203  * For @c DataVector, this is just the same as @c insert.
1204  * It's included just for interface compatibility with `std::vector`.
1205  */
1206 template <class T, class BASE>
1207 typename DataVector<T, BASE>::iterator
1208 DataVector<T, BASE>::emplace(iterator position, value_type pElem)
1209 {
1210  return this->insert (position, pElem);
1211 }
1212 
1213 
1214 /**
1215  * @brief Add a group of new elements to the collection.
1216  * @param position Iterator before which the element will be added.
1217  * @param first The start of the range to put in the container.
1218  * @param last The end of the range to put in the container.
1219  *
1220  * The container's ownership policy will determine if it takes ownership
1221  * of the new element.
1222  *
1223  * Note: this method may only be called using the most derived
1224  * @c DataVector in the hierarchy.
1225  *
1226  * This overload is for the case where the iterator value type
1227  * is convertible to T*.
1228  */
1229 template <class T, class BASE>
1230 template <class InputIterator,
1231  DataVector_detail::enable_if_ptr_itr<InputIterator, T> >
1232 void DataVector<T, BASE>::insert(iterator position,
1233  InputIterator first,
1234  InputIterator last)
1235 {
1236  // Make sure that the input iterator can actually be converted
1237  // to a T*. Lets us give a compilation error for this:
1238  // DATAVECTOR_BASE(D, B);
1239  // B* bb[] = ...
1240  // DataVector<D> d;
1241  // d.insert (d.begin(), bb, bb+1);
1242  // which would otherwise compile.
1243  using ittype = typename std::iterator_traits<InputIterator>::value_type;
1244  static_assert (std::is_convertible_v<ittype, const T*>);
1245 
1246  // Ensure we're not being called via a base class.
1247  testInsert ("insert");
1248  size_t idx = position - this->begin();
1249  size_t old_sz = this->m_pCont.size();
1250  this->m_pCont.insert(position.base(), first, last);
1251  size_t n = this->m_pCont.size() - old_sz;
1252  this->shift (idx, n);
1253  this->moveAux (idx, first, last, false, true);
1254 }
1255 
1256 
1257 /**
1258  * @brief Add a group of new elements to the collection.
1259  * @param position Iterator before which the element will be added.
1260  * @param first The start of the range to put in the container.
1261  * @param last The end of the range to put in the container.
1262  *
1263  * The container's ownership policy will determine if it takes ownership
1264  * of the new element.
1265  *
1266  * Note: this method may only be called using the most derived
1267  * @c DataVector in the hierarchy.
1268  *
1269  * This overload is for the case where the iterator value type
1270  * is convertible to unique_ptr<T>.
1271  */
1272 template <class T, class BASE>
1273 template <class InputIterator,
1274  DataVector_detail::enable_if_up_itr<InputIterator, T> >
1275 void DataVector<T, BASE>::insert(iterator position,
1276  InputIterator first,
1277  InputIterator last)
1278 {
1279  // Make sure that the input iterator can actually be converted
1280  // to a T*. Lets us give a compilation error for this:
1281  // DATAVECTOR_BASE(D, B);
1282  // B* bb[] = ...
1283  // DataVector<D> d;
1284  // d.insert (d.begin(), bb, bb+1);
1285  // which would otherwise compile.
1286  using ittype = typename std::iterator_traits<InputIterator>::value_type;
1287  static_assert (std::is_convertible_v<typename ittype::pointer, const T*>);
1288 
1289  // Ensure we're not being called via a base class.
1290  testInsert ("insert");
1291  size_t idx = position - this->begin();
1292  size_t old_sz = this->m_pCont.size();
1293  using CxxUtils::releasing_iterator;
1294  this->m_pCont.insert(position.base(), releasing_iterator(first), releasing_iterator(last));
1295  size_t n = this->m_pCont.size() - old_sz;
1296  this->shift (idx, n);
1297  this->moveAux (idx, this->begin()+idx, this->begin()+idx+n);
1298 }
1299 
1300 
1301 /**
1302  * @brief Add a group of new elements to the collection.
1303  * @param position Iterator before which the element will be added.
1304  * @param l An initializer list.
1305  *
1306  * The container's ownership policy will determine if it takes ownership
1307  * of the new element.
1308  *
1309  * Note: this method may only be called using the most derived
1310  * @c DataVector in the hierarchy.
1311  */
1312 template <class T, class BASE>
1313 void DataVector<T, BASE>::insert(iterator position,
1314  std::initializer_list<value_type> l)
1315 {
1316  insert (position, l.begin(), l.end());
1317 }
1318 
1319 
1320 /**
1321  * @brief Insert the contents of another @c DataVector,
1322  * with auxiliary data copied via move semantics.
1323  * @param position Iterator before which the new elements will be added.
1324  * @param other The vector to add.
1325  *
1326  * The ownership mode of this vector must be the same as @c other;
1327  * otherwise, an exception will be thrown.
1328  *
1329  * If both vectors are view vectors, then this is the same
1330  * as <code> insert (position, other.begin(), other.end()) </code>.
1331  *
1332  * Otherwise, the elements from @c other will be inserted into this vector.
1333  * This vector will take ownership of the elements, and the ownership
1334  * mode of @c other will be changed to @c VIEW_ELEMENTS.
1335  * Auxiliary data for these elements will be transferred,
1336  * using move semantics if possible. (Thus, the auxiliary store
1337  * for @c other may be modified and must not be locked.)
1338  * Finally, the auxiliary store pointer for @c other will be cleared
1339  * (but the store itself will not be deleted since it's not owned
1340  * by the vector).
1341  *
1342  * Note: this method may only be called using the most derived
1343  * @c DataVector in the hierarchy.
1344  */
1345 template <class T, class BASE>
1346 void
1347 DataVector<T, BASE>::insertMove (iterator position, DataVector& other)
1348 {
1349  if (this->m_ownPolicy != other.ownPolicy())
1350  throw SG::ExcInsertMoveOwnershipMismatch();
1351 
1352  if (this->m_ownPolicy == SG::VIEW_ELEMENTS) {
1353  this->insert (position, other.begin(), other.end());
1354  return;
1355  }
1356 
1357  testInsert ("insertMove");
1358  size_t pos = position.base() - this->m_pCont.begin();
1359  this->m_pCont.insert (position.base(), other.begin(), other.end());
1360  this->setIndices (this->begin()+pos, this->end(), pos);
1361  other.m_ownPolicy = SG::VIEW_ELEMENTS;
1362 
1363  SG::IAuxStore* otherStore = other.getStore();
1364  if (otherStore) {
1365  SG::IAuxStore* store = this->getStore();
1366  if (store) {
1367  if (!store->insertMove (pos, *otherStore))
1368  this->clearCache();
1369  }
1370  else if (this->hasStore())
1371  throw SG::ExcConstAuxData ("insertMove");
1372  other.setStore (static_cast<SG::IAuxStore*>(nullptr));
1373  }
1374  else if (other.hasStore())
1375  throw SG::ExcConstAuxData ("insertMove");
1376 }
1377 
1378 
1379 //=== Erasure operations.
1380 
1381 
1382 /**
1383  * @brief Remove element at a given position.
1384  * @param position Iterator pointing to the element to be removed.
1385  * @return An iterator pointing to the next element (or @c end()).
1386  *
1387  * If the container owns its elements, then the pointed-to element
1388  * will be deleted.
1389  */
1390 template <class T, class BASE>
1391 typename DataVector<T, BASE>::iterator
1392 DataVector<T, BASE>::erase(iterator position)
1393 {
1394  if (this->m_ownPolicy != SG::OWN_ELEMENTS)
1395  this->clearIndex (position);
1396  iterator ret (this->erase_base (position.base()), this);
1397  this->shift (ret - this->begin() + 1, -1);
1398  return ret;
1399 }
1400 
1401 
1402 /**
1403  * @brief Remove a range of elements.
1404  * @param first Iterator pointing to the first element to be removed.
1405  * @param last Iterator pointing one past the last element to be removed.
1406  * @return An iterator pointing to the element pointed to by @a last
1407  * prior to erasing (or @c end()).
1408  *
1409  * If the container owns its elements, then the removed elements
1410  * will be deleted. Any duplicates will be removed in this process,
1411  * but don't rely on this.
1412  */
1413 template <class T, class BASE>
1414 typename DataVector<T, BASE>::iterator
1415 DataVector<T, BASE>::erase(iterator first, iterator last)
1416 {
1417  if (this->m_ownPolicy != SG::OWN_ELEMENTS)
1418  this->clearIndices (first, last);
1419  iterator ret (this->erase_base (first.base(), last.base()), this);
1420  this->shift (ret - this->begin() + (last-first), -(last-first));
1421  return ret;
1422 }
1423 
1424 
1425 /**
1426  * @brief Remove the last element from the collection.
1427  *
1428  * If the container owns its elements, then the removed element
1429  * will be deleted.
1430  */
1431 template <class T, class BASE>
1432 void DataVector<T, BASE>::pop_back()
1433 {
1434  if (!this->m_pCont.empty()) {
1435  if (this->m_ownPolicy == SG::OWN_ELEMENTS)
1436  this->doDelete (this->m_pCont.back());
1437  else
1438  this->clearIndex (iterator (this->m_pCont.end() - 1, this));
1439  this->m_pCont.pop_back();
1440  SG::AuxVectorBase::resize<DataVector> (this->m_pCont.size());
1441  }
1442 }
1443 
1444 
1445 /**
1446  * @brief Erase all the elements in the collection.
1447  *
1448  * If the container owns its elements, then the removed elements
1449  * will be deleted. Any duplicates will be removed in this process,
1450  * but don't rely on this.
1451  */
1452 template <class T, class BASE>
1453 inline
1454 void DataVector<T, BASE>::clear()
1455 {
1456  if (this->m_ownPolicy != SG::OWN_ELEMENTS)
1457  this->clearIndices (begin(), end());
1458  this->erase_base (this->m_pCont.begin(), this->m_pCont.end());
1459  SG::AuxVectorBase::resize<DataVector> (0);
1460 }
1461 
1462 
1463 //=== Swap and sort.
1464 
1465 
1466 /**
1467  * @brief Swap this collection with another.
1468  * @param rhs The collection with which to swap.
1469  *
1470  * Ownership is swapped along with the collection content.
1471  *
1472  * Note: this method may only be called using the most-derived
1473  * @c DataVector in the hierarchy. The @a rhs must also be
1474  * referenced using the most-derived @c DataVector.
1475  *
1476  * Warning: If this container has auxiliary data, then this
1477  * is an O(N) operation, not O(1).
1478  */
1479 template <class T, class BASE>
1480 void DataVector<T, BASE>::swap(DataVector& rhs)
1481 {
1482  testInsert ("swap");
1483  rhs.testInsert ("swap");
1484  std::swap(this->m_ownPolicy, rhs.m_ownPolicy);
1485  SG::AuxVectorBase::swap (rhs);
1486  this->m_pCont.swap(rhs.m_pCont);
1487  std::swap (this->m_deleter, rhs.m_deleter);
1488  this->setIndices (this->begin(), this->end());
1489  rhs.setIndices (rhs.begin(), rhs.end());
1490 }
1491 
1492 
1493 /**
1494  * @brief Swap the referents of two @c DataVector iterators.
1495  * @param a The first iterator for the swap.
1496  * @param b The second iterator for the swap.
1497  */
1498 template <class T, class BASE>
1499 void DataVector<T, BASE>::iter_swap (iterator a, iterator b)
1500 {
1501  if (a.ownPolicy() != b.ownPolicy()) {
1502  throw SG::ExcBadIterSwap();
1503  }
1504  a.testInsert ("iter_swap");
1505  b.testInsert ("iter_swap");
1506  std::iter_swap (a.base(), b.base());
1507  DataVector* acont = a.container();
1508  DataVector* bcont = b.container();
1509  if (typename SG::AuxStore_traits<DataVector>::flag())
1510  acont->swapElementsAux (a.base() - acont->stdcont().begin(),
1511  b.base() - bcont->stdcont().begin(),
1512  DataModel_detail::DVLCast<DataVector>::cast(*a.base()),
1513  DataModel_detail::DVLCast<DataVector>::cast(*b.base()),
1514  bcont);
1515 }
1516 
1517 
1518 /**
1519  * @brief Sort the container.
1520  *
1521  * This just sorts by pointer value, so it's probably not very useful.
1522  */
1523 template <class T, class BASE>
1524 void DataVector<T, BASE>::sort()
1525 {
1526  typedef std::less<typename PtrVector::value_type> less;
1527  std::sort (this->m_pCont.begin(), this->m_pCont.end(),
1528  DataModel_detail::Compwrapper<DataVector, less> (less()));
1529  this->resortAux (this->begin(), this->end());
1530 }
1531 
1532 
1533 /**
1534  * @brief Sort the container with a user-specified comparison operator.
1535  * @param comp Functional to compare two values.
1536  */
1537 template <class T, class BASE>
1538 template <class COMPARE>
1539 void DataVector<T, BASE>::sort(COMPARE comp)
1540 {
1541  std::sort (this->m_pCont.begin(), this->m_pCont.end(),
1542  DataModel_detail::Compwrapper<DataVector, COMPARE> (comp));
1543  this->resortAux (this->begin(), this->end());
1544 }
1545 
1546 
1547 //=== Non-standard operations.
1548 
1549 
1550 /**
1551  * @brief Swap one element out of the container.
1552  * @param index Index of the element in the container to swap.
1553  * @param newElement New element to put in the container.
1554  * May be 0.
1555  * @param oldElem Reference to receive the element removed from the
1556  * container.
1557  *
1558  * Reference @a oldElem is initialized with element @a index of the
1559  * collection (no bounds checking). Then element @a index is set
1560  * to @newElem. If the collection owns its elements, then it will
1561  * take ownership of @a newElem and release (without deleting)
1562  * the element returned through @a oldElem.
1563  *
1564  * Note: this method may only be called using the most derived
1565  * @c DataVector in the hierarchy.
1566  */
1567 template <class T, class BASE>
1568 void DataVector<T, BASE>::swapElement(size_type index,
1569  value_type newElem,
1570  reference oldElem)
1571 {
1572  testInsert ("swapElement");
1573  oldElem =
1574  DataModel_detail::DVLCast<DataVector>::cast(this->m_pCont[index]);
1575  this->clearIndex (iterator (this->m_pCont.begin() + index, this));
1576  this->m_pCont[index] = newElem;
1577  this->moveAux (index, newElem);
1578 }
1579 
1580 
1581 /**
1582  * @brief Swap one element out of the container.
1583  * @param pos The element in the container to swap.
1584  * @param newElem New element to put in the container.
1585  * May be 0.
1586  * @param oldElem Reference to receive the element removed from the
1587  * container.
1588  *
1589  * Reference @a oldElem is initialized with element @a pos of the
1590  * collection (no bounds checking). Then element @a index is set
1591  * to @c newElem. If the collection owns its elements, then it will
1592  * take ownership of @a newElem and release (without deleting)
1593  * the element returned through @a oldElem.
1594  *
1595  * Note: this method may only be called using the most derived
1596  * @c DataVector in the hierarchy.
1597  */
1598 template <class T, class BASE>
1599 void DataVector<T, BASE>::swapElement(iterator pos,
1600  value_type newElem,
1601  reference oldElem)
1602 {
1603  testInsert ("swapElement");
1604  oldElem =
1605  DataModel_detail::DVLCast<DataVector>::cast(*pos.base());
1606  this->clearIndex (pos);
1607  *pos.base() = newElem;
1608  this->moveAux (pos.base() - this->m_pCont.begin(), newElem);
1609 }
1610 
1611 
1612 /**
1613  * @brief Swap one element out of the container.
1614  * @param index Index of the element in the container to swap.
1615  * @param newElement New element to put in the container.
1616  * May be 0.
1617  * @param oldElem Reference to receive the element removed from the
1618  * container.
1619  *
1620  * Reference @a oldElem is initialized with element @a index of the
1621  * collection (no bounds checking). Then element @a index is set
1622  * to @newElem.
1623  *
1624  * The collection must own its elements to use its interface.
1625  * The collection will take ownership of @c newElem and will return
1626  * ownership of @c oldElem.
1627  *
1628  * Note: this method may only be called using the most derived
1629  * @c DataVector in the hierarchy.
1630  */
1631 template <class T, class BASE>
1632 void DataVector<T, BASE>::swapElement(size_type index,
1633  std::unique_ptr<base_value_type> newElem,
1634  std::unique_ptr<base_value_type>& oldElem)
1635 {
1636  // Container must own its elements.
1637  if (this->m_ownPolicy != SG::OWN_ELEMENTS)
1638  SG::throwExcNonowningContainer();
1639 
1640  testInsert ("swapElement");
1641  oldElem = std::unique_ptr<base_value_type>
1642  (DataModel_detail::DVLCast<DataVector>::cast(this->m_pCont[index]));
1643  this->clearIndex (iterator (this->m_pCont.begin() + index, this));
1644  value_type ptr = newElem.release();
1645  this->m_pCont[index] = ptr;
1646  this->moveAux (index, ptr);
1647 }
1648 
1649 
1650 /**
1651  * @brief Swap one element out of the container.
1652  * @param pos The element in the container to swap.
1653  * @param newElem New element to put in the container.
1654  * May be 0.
1655  * @param oldElem Reference to receive the element removed from the
1656  * container.
1657  *
1658  * Reference @a oldElem is initialized with element @a pos of the
1659  * collection (no bounds checking). Then element @a index is set
1660  * to @c newElem.
1661  *
1662  * The collection must own its elements to use its interface.
1663  * The collection will take ownership of @c newElem and will return
1664  * ownership of @c oldElem.
1665  *
1666  * Note: this method may only be called using the most derived
1667  * @c DataVector in the hierarchy.
1668  */
1669 template <class T, class BASE>
1670 void DataVector<T, BASE>::swapElement(iterator pos,
1671  std::unique_ptr<base_value_type> newElem,
1672  std::unique_ptr<base_value_type>& oldElem)
1673 {
1674  // Container must own its elements.
1675  if (this->m_ownPolicy != SG::OWN_ELEMENTS)
1676  SG::throwExcNonowningContainer();
1677 
1678  testInsert ("swapElement");
1679  oldElem = std::unique_ptr<base_value_type>
1680  (DataModel_detail::DVLCast<DataVector>::cast(*pos.base()));
1681  this->clearIndex (pos);
1682  value_type ptr = newElem.release();
1683  *pos.base() = ptr;
1684  this->moveAux (pos.base() - this->m_pCont.begin(), ptr);
1685 }
1686 
1687 
1688 /**
1689  * @brief Erase all the elements in the collection, and reset
1690  * the ownership mode.
1691  * @param ownPolicy The new ownership policy of the container.
1692  *
1693  * If the container owns its elements, then the removed elements
1694  * will be deleted. Any duplicates will be removed in this process,
1695  * but don't rely on this.
1696  */
1697 template <class T, class BASE>
1698 void DataVector<T, BASE>::clear (SG::OwnershipPolicy ownPolicy)
1699 {
1700  this->clear();
1701  this->m_ownPolicy = ownPolicy;
1702  this->template initAuxVectorBase<DataVector> (ownPolicy,
1703  SG::DEFAULT_TRACK_INDICES);
1704 }
1705 
1706 
1707 /**
1708  * @brief Erase all the elements in the collection, and reset
1709  * the ownership mode.
1710  * @param ownPolicy The new ownership policy of the container.
1711  * @param trackIndices The index tracking policy.
1712  *
1713  * If the container owns its elements, then the removed elements
1714  * will be deleted. Any duplicates will be removed in this process,
1715  * but don't rely on this.
1716  */
1717 template <class T, class BASE>
1718 void DataVector<T, BASE>::clear (SG::OwnershipPolicy ownPolicy,
1719  SG::IndexTrackingPolicy trackIndices)
1720 {
1721  this->clear();
1722  this->m_ownPolicy = ownPolicy;
1723  this->template initAuxVectorBase<DataVector> (ownPolicy, trackIndices);
1724 }
1725 
1726 
1727 /**
1728  * @brief Return the DV/DL info struct for this class.
1729  *
1730  * This can be used to make sure that it's instantiated.
1731  */
1732 template <class T, class BASE>
1733 const DataModel_detail::DVLInfoBase& DataVector<T, BASE>::dvlinfo()
1734 {
1735  static const DataModel_detail::DVLInfo<DataVector<T, BASE> > info;
1736  return info;
1737 }
1738 
1739 
1740 /**
1741  * @brief Erase all the elements in the collection, and change
1742  * how elements are to be deleted.
1743  * @param deleter Object to be used to delete object.
1744  * Passing nullptr will change back to the default.
1745  *
1746  * If the container owns its elements, then the removed elements
1747  * will be deleted. Any duplicates will be removed in this process,
1748  * but don't rely on this.
1749  * After the current elements are deleted, the Deleter object is changed.
1750  */
1751 template <class T, class BASE>
1752 void DataVector<T, BASE>::clear (std::unique_ptr<Deleter> deleter)
1753 {
1754  this->clear();
1755  delete this->m_deleter;
1756  this->m_deleter = deleter.release();
1757 }
1758 
1759 
1760 /**
1761  * @brief Return the DV/DL info struct for this class.
1762  *
1763  * This can be used to make sure that it's instantiated.
1764  */
1765 template <class T, class BASE>
1766 const DataModel_detail::DVLInfoBase& DataVector<T, BASE>::dvlinfo_v() const
1767 {
1768  return DataVector<T, BASE>::dvlinfo();
1769 }
1770 
1771 
1772 /**
1773  * @brief Return the offset of a base @c DataVector class.
1774  * @param ti @c std::type_info of the desired class.
1775  *
1776  * If @c ti represents a @c DataVector base class of this one,
1777  * then return the offset of that base class. Otherwise, return -1.
1778  *
1779  * This function is here due to limitations of root 6, which can't
1780  * calculate these offsets correctly from the dictionary if
1781  * virtual derivation is used.
1782  */
1783 template <class T, class BASE>
1784 int DataVector<T, BASE>::baseOffset (const std::type_info& ti)
1785 {
1786  DataVector dv;
1787  return baseOffset1 (reinterpret_cast<const char*>(&dv), dv, ti);
1788 }
1789 
1790 
1791 /**
1792  * @brief Convert to @c AuxVectorBase.
1793  *
1794  * Needed to get @x AuxVectorBase from a @c ConstDataVector.
1795  * Present in @c DataVector as well for consistency.
1796  * We only really need it in the base class; however, root6 fails
1797  * constructing a @c TMethodCall for this if there is virtual
1798  * derivation. A workaround is to redeclare this in the derived
1799  * classes too.
1800  */
1801 template <class T, class BASE>
1802 const SG::AuxVectorBase& DataVector<T, BASE>::auxbase() const
1803 {
1804  return *this;
1805 }
1806 
1807 
1808 //=== Internal operations.
1809 
1810 
1811 /**
1812  * @brief Helper for @c baseOffset.
1813  * @param p Pointer to the start of the top-level object.
1814  * @param dv Reference to the DataVector object.
1815  * @param ti @c std::type_info of the desired class.
1816  *
1817  * If @c ti represents a @c DataVector base class of this one,
1818  * then return the offset of that base class. Otherwise, return -1.
1819  *
1820  */
1821 template <class T, class BASE>
1822 int DataVector<T, BASE>::baseOffset1 (const char* p, const DataVector& dv,
1823  const std::type_info& ti)
1824 {
1825  if (typeid(DataVector) == ti)
1826  return reinterpret_cast<const char*>(&dv) - p;
1827  return BASE::baseOffset1 (p, dv, ti);
1828 }
1829 
1830 
1831 /**
1832  * @brief Reset indices / reorder aux data after elements have been permuted.
1833  * @param beg Start of the range of elements to process.
1834  * @param end End of the range of elements to process.
1835  *
1836  * Call this after some operation that has permuted the elements in the
1837  * container (such as sort). The index information in the elements
1838  * will be used to permute all auxiliary data in the same way.
1839  * Finally, all the indices will be reset in the correct order.
1840  */
1841 template <class T, class BASE>
1842 void DataVector<T, BASE>::resortAux (iterator beg, iterator end)
1843 {
1844  if (typename SG::AuxStore_traits<DataVector>::flag() &&
1845  beg >= this->begin() && end <= this->end())
1846  {
1847  SG::AuxVectorBase::resortAux (beg-begin(), beg, end);
1848  }
1849 }
1850 
1851 
1852 /**
1853  * @brief Test if we can insert; raise an exception if not.
1854  * @param op Description of the attempted operation.
1855  *
1856  * In order to maintain type-safety, we can only allow insertions
1857  * using the most-derived instance of @c DataVector. This checks
1858  * this by testing the @c m_isMostDerived, which is set by the constructors
1859  * to true only for the most-derived instance.
1860  * If the test fails, we call to potentially out-of-line code to continue.
1861  */
1862 template <class T, class BASE>
1863 inline
1864 void DataVector<T, BASE>::testInsert (const char* op)
1865 {
1866  if (ATHCONTAINERS_LIKELY (m_isMostDerived))
1867  return;
1868  this->testInsertOol (op);
1869 }
1870 
1871 
1872 /**
1873  * @brief Test if we can insert; raise an exception if not.
1874  * @param op Description of the attempted operation.
1875  *
1876  * This continues the test of @c testInsert. There is one case
1877  * where @c m_isMostDerived may not be set correctly. If this container
1878  * was made via copy construction, then all the @c m_isMostDerived flags
1879  * will be false. So we call @c setMostDerived to set the flags correctly
1880  * and test again. If the test fails again, then we raise an exception.
1881  */
1882 template <class T, class BASE>
1883 void DataVector<T, BASE>::testInsertOol (const char* op)
1884 {
1885  this->setMostDerived();
1886  if (!m_isMostDerived)
1887  throw SG::ExcInsertionInBaseClass (op, typeid(DataVector), dv_typeid());
1888 }
1889 
1890 
1891 /**
1892  * @brief Handle element assignment.
1893  * @param pos Position in the container to assign.
1894  * @param newElem The new element to assign.
1895  *
1896  * The old element is freed if this container owns elements.
1897  * Auxiliary data are copied if appropriate.
1898  */
1899 template <class T, class BASE>
1900 void DataVector<T, BASE>::assignElement (typename BaseContainer::iterator pos,
1901  value_type newElem)
1902 {
1903  testInsert ("assignElement");
1904  if (this->m_ownPolicy == SG::OWN_ELEMENTS)
1905  this->doDelete (*pos);
1906  else
1907  this->clearIndex (iterator (pos, this));
1908  *pos = newElem;
1909  this->moveAux (pos - this->m_pCont.begin(), newElem);
1910 }
1911 
1912 
1913 /**
1914  * @brief Handle element assignment.
1915  * @param pos Position in the container to assign.
1916  * @param newElem The new element to assign.
1917  *
1918  * The container must own its elements.
1919  * Auxiliary data are copied if appropriate.
1920  */
1921 template <class T, class BASE>
1922 void
1923 DataVector<T, BASE>::assignElement (typename BaseContainer::iterator pos,
1924  std::unique_ptr<base_value_type> newElem)
1925 {
1926  // Container must own its elements.
1927  if (this->m_ownPolicy != SG::OWN_ELEMENTS)
1928  SG::throwExcNonowningContainer();
1929 
1930  testInsert ("assignElement");
1931  this->doDelete (*pos);
1932  value_type ptr = newElem.release();
1933  *pos = ptr;
1934  this->moveAux (pos - this->m_pCont.begin(), ptr);
1935 }
1936 
1937 
1938 /**
1939  * @brief Handle element assignment from a base pointer.
1940  * @param pos Position in the container to assign.
1941  * @param newElem The new element to assign.
1942  *
1943  * The old element is freed if this container owns elements.
1944  * Auxiliary data are copied if appropriate.
1945  */
1946 template <class T, class BASE>
1947 void
1948 DataVector<T, BASE>::assignBaseElement (typename BaseContainer::iterator pos,
1949  typename BaseContainer::value_type newElem)
1950 {
1951  testInsert ("assignBaseElement");
1952  if (this->m_ownPolicy == SG::OWN_ELEMENTS)
1953  this->doDelete (*pos);
1954  else
1955  this->clearIndex (iterator (pos, this));
1956  *pos = newElem;
1957  if (typename SG::AuxStore_traits<DataVector>::flag())
1958  this->moveAux (pos - this->m_pCont.begin(),
1959  DataModel_detail::DVLCast<DataVector>::cast(newElem));
1960 }
1961 
1962 
1963 /**
1964  * @brief Shift the auxiliary elements of the container.
1965  * @param pos The starting index for the shift.
1966  * @param offs The (signed) amount of the shift.
1967  *
1968  * The elements in the container should have already been shifted;
1969  * this operation will then adjust the element indices and also shift
1970  * the elements in the vectors for all aux data items.
1971  * @c offs may be either positive or negative.
1972  *
1973  * If @c offs is positive, then the container is growing.
1974  * The container size should be increased by @c offs,
1975  * the element at @c pos moved to @c pos + @c offs,
1976  * and similarly for following elements.
1977  * The elements between @c pos and @c pos + @c offs should
1978  * be default-initialized.
1979  *
1980  * If @c offs is negative, then the container is shrinking.
1981  * The element at @c pos should be moved to @c pos + @c offs,
1982  * and similarly for following elements.
1983  * The container should then be shrunk by @c -offs elements
1984  * (running destructors as appropriate).
1985  */
1986 template <class T, class BASE>
1987 void DataVector<T, BASE>::shift (size_t pos, ptrdiff_t offs)
1988 {
1989  SG::AuxVectorBase::shift (*this, pos, offs);
1990 }
1991 
1992 
1993 /**
1994  * @brief Helper to shorten calls to @c DataVector_detail::DVLCast.
1995  * @param p The value to convert.
1996  * @return The value as a @c const @c T*.
1997  *
1998  * The conversion will be done with @c static_cast if possible,
1999  * with @c dynamic_cast otherwise.
2000  */
2001 template <class T, class BASE>
2002 inline
2003 const T*
2004 DataVector<T, BASE>::do_cast (const typename PtrVector::value_type p)
2005 {
2006  return DataModel_detail::DVLCast<DataVector>::cast (p);
2007 }
2008 
2009 
2010 /**
2011  * @brief Helper to shorten calls to @c DataVector_detail::DVLCast.
2012  * @param p The value to convert.
2013  * @return The value as a @c T*.
2014  *
2015  * The conversion will be done with @c static_cast if possible,
2016  * with @c dynamic_cast otherwise.
2017  */
2018 template <class T, class BASE>
2019 inline
2020 T*
2021 DataVector<T, BASE>::do_cast_nc (typename PtrVector::value_type p)
2022 {
2023  return DataModel_detail::DVLCast<DataVector>::cast (p);
2024 }
2025 
2026 
2027 /**
2028  * @brief Find the most-derived @c DataVector class in the hierarchy.
2029  * @return The @c type_info for the class for which this method gets run.
2030  *
2031  * This is used to generate a nice error message when the most-derived
2032  * check for insertions fails.
2033  * Every @c DataVector defines this virtual method, so when it's
2034  * called, the one corresponding to the most-derived @c DataVector
2035  * gets run.
2036  */
2037 template <class T, class BASE>
2038 const std::type_info& DataVector<T, BASE>::dv_typeid() const
2039 {
2040  return typeid(DataVector);
2041 }
2042 
2043 
2044 /**
2045  * @brief Clear @c m_isMostDerived for this instance and for all bases.
2046  *
2047  * Called from the constructor after setting @c m_isMostDerived.
2048  */
2049 template <class T, class BASE>
2050 inline
2051 void DataVector<T, BASE>::clearMostDerived()
2052 {
2053  this->m_isMostDerived = false;
2054  BASE::clearMostDerived();
2055 }
2056 
2057 
2058 /**
2059  * @brief Set @c m_isMostDerived for this instance and clear it for all bases.
2060  *
2061  * Called from @c testInsert if the test fails. The flag may not have
2062  * been set if this container was made via copy construction, so set
2063  * it appropriately now so we can test again.
2064  */
2065 template <class T, class BASE>
2066 void DataVector<T, BASE>::setMostDerived()
2067 {
2068  m_isMostDerived = true;
2069  BASE::clearMostDerived();
2070 }
2071 
2072 
2073 //****************************************************************************
2074 // Specialized (base) DataVector implementation.
2075 //
2076 
2077 
2078 // An abbreviation for the DataVector specialization to try to make
2079 // things a little more readable.
2080 #define DATAVECTOR DataVector<T, DataModel_detail::NoBase>
2081 
2082 
2083 //=== Constructors, destructors, assignment.
2084 
2085 /**
2086  * @brief Default constructor.
2087  * @param ownPolicy The ownership mode for the container.
2088  * @param trackIndices The index tracking policy.
2089  *
2090  * By default, a @c DataVector will own its elements.
2091  * To avoid this, pass @c SG::VIEW_ELEMENTS for @a ownPolicy.
2092  */
2093 template <class T>
2094 inline
2095 DATAVECTOR::DataVector
2096  (SG::OwnershipPolicy ownPolicy /*= SG::OWN_ELEMENTS*/,
2097  SG::IndexTrackingPolicy trackIndices /*=SG::DEFAULT_TRACK_INDICES*/)
2098  : m_ownPolicy(ownPolicy)
2099 {
2100  this->template initAuxVectorBase<DataVector> (ownPolicy, trackIndices);
2101  this->m_isMostDerived = true;
2102 }
2103 
2104 
2105 /**
2106  * @brief Sized constructor.
2107  * @param n The size of the container.
2108  * @param ownPolicy The ownership mode for the container.
2109  * @param trackIndices The index tracking policy.
2110  *
2111  * Note that unlike the standard vector constructor, you can't specify
2112  * an initial value here. The container will be initialized with 0's.
2113  *
2114  * By default, a @c DataVector will own its elements.
2115  * To avoid this, pass @c SG::VIEW_ELEMENTS for @a ownPolicy.
2116  */
2117 template <class T>
2118 inline
2119 DATAVECTOR::DataVector
2120  (size_type n,
2121  SG::OwnershipPolicy ownPolicy /*= SG::OWN_ELEMENTS*/,
2122  SG::IndexTrackingPolicy trackIndices /*= SG::DEFAULT_TRACK_INDICES*/)
2123  : m_ownPolicy(ownPolicy),
2124  m_pCont (n)
2125 {
2126  this->template initAuxVectorBase<DataVector> (ownPolicy, trackIndices);
2127  this->m_isMostDerived = true;
2128 }
2129 
2130 
2131 /**
2132  * @brief Copy constructor.
2133  * @param rhs The container from which to copy.
2134  *
2135  * This is a `shallow' copy; the new container will not own its elements.
2136  */
2137 template <class T>
2138 inline
2139 DATAVECTOR::DataVector(const DataVector& rhs)
2140  : AuxVectorBase(),
2141  m_ownPolicy(SG::VIEW_ELEMENTS),
2142  m_pCont(rhs.m_pCont)
2143 {
2144  this->template initAuxVectorBase<DataVector> (m_ownPolicy,
2145  SG::DEFAULT_TRACK_INDICES);
2146  // Leave m_isMostDerived false here, because we may be being called
2147  // from a derived class implicit copy constructor. The flags will get
2148  // set correctly when @c testInsert gets called.
2149 }
2150 
2151 
2152 /**
2153  * @brief Move constructor.
2154  * @param rhs The container from which to move.
2155  *
2156  * Any auxiliary data will be moved along with the container contents.
2157  */
2158 template <class T>
2159 inline
2160 DATAVECTOR::DataVector(DataVector&& rhs) noexcept
2161  : AuxVectorBase (std::move (rhs)),
2162  m_ownPolicy(rhs.m_ownPolicy),
2163  m_pCont(std::move (rhs.m_pCont))
2164 {
2165  m_deleter = std::move(rhs.m_deleter);
2166  rhs.m_deleter = nullptr;
2167 
2168  // Need to reset the container pointer on elements.
2169  // Functions called from here can throw GaudiException.
2170  // However, logically that should not actually happen; so leave this
2171  // declared as noexcept.
2172  this->setIndices (this->begin(), this->end());
2173 
2174  // This doesn't get called from derived classes.
2175  // Go ahead and set this flag now.
2176  m_isMostDerived = true;
2177 }
2178 
2179 
2180 /**
2181  * @brief Constructor from iterators.
2182  * @param first The start of the range to put in the new container.
2183  * @param last The end of the range to put in the new container.
2184  * @param ownPolicy The ownership mode for the container.
2185  * @param trackIndices The index tracking policy.
2186  * @param store An associated auxiliary data store.
2187  *
2188  * By default, a view container is made, which does not own its elements.
2189  * To have the container take ownership of the pointers passed
2190  * to this constructor, pass @c SG::OWN_ELEMENTS for @a ownPolicy.
2191  */
2192 template <class T>
2193 template <class InputIterator>
2194 inline
2195 DATAVECTOR::DataVector
2196  (InputIterator first,
2197  InputIterator last,
2198  SG::OwnershipPolicy ownPolicy /*= SG::VIEW_ELEMENTS*/,
2199  SG::IndexTrackingPolicy trackIndices /*= SG::DEFAULT_TRACK_INDICES*/,
2200  SG::IAuxStore* store /*= 0*/)
2201  : m_ownPolicy(ownPolicy)
2202 {
2203  this->template initAuxVectorBase<DataVector> (ownPolicy, trackIndices);
2204  this->m_isMostDerived = true;
2205  if (store)
2206  this->setStore (store);
2207  insert (this->begin(), first, last);
2208 }
2209 
2210 
2211 /**
2212  * @brief Constructor from an initializer list.
2213  * @param l An initializer list.
2214  * @param last The end of the range to put in the new container.
2215  * @param ownPolicy The ownership mode for the container.
2216  * @param trackIndices The index tracking policy.
2217  * @param store An associated auxiliary data store.
2218  *
2219  *
2220  * A @c DataVector constructed this way will *not* own its elements
2221  * by default. To change this, pass @c SG::OWN_ELEMENTS for @a ownPolicy.
2222  */
2223 template <class T>
2224 inline
2225 DATAVECTOR::DataVector
2226  (std::initializer_list<value_type> l,
2227  SG::OwnershipPolicy ownPolicy /*= SG::VIEW_ELEMENTS*/,
2228  SG::IndexTrackingPolicy trackIndices /*= SG::DEFAULT_TRACK_INDICES*/,
2229  SG::IAuxStore* store /*= 0*/)
2230  : DataVector (l.begin(), l.end(), ownPolicy, trackIndices, store)
2231 {
2232 }
2233 
2234 
2235 /**
2236  * @brief Assignment operator.
2237  * @param rhs The DataVector from which to assign.
2238  * @return This object.
2239  *
2240  * This is a `shallow' copy; after the completion of this, the @c DataVector
2241  * will not own its elements. Any elements it owned prior to this call
2242  * will be released.
2243  *
2244  * Note: this method may only be called using the most derived
2245  * @c DataVector in the hierarchy.
2246  */
2247 template <class T>
2248 inline
2249 DATAVECTOR& DATAVECTOR::operator= (const DataVector& rhs)
2250 {
2251  if (&rhs != this) {
2252  // Ensure we're not being called via a base class.
2253  // This can throw an exception, so this method should not be noexcept.
2254  testInsert ("assignment operator");
2255  clear(); // Release any currently-owned elements.
2256  m_ownPolicy = SG::VIEW_ELEMENTS;
2257  this->setStore ((SG::IConstAuxStore*)0);
2258  this->template initAuxVectorBase<DataVector> (m_ownPolicy,
2259  SG::DEFAULT_TRACK_INDICES);
2260  m_pCont = rhs.m_pCont;
2261  }
2262  return *this;
2263 }
2264 
2265 
2266 /**
2267  * @brief Move assignment.
2268  * @param rhs The container from which to move.
2269  *
2270  * Any auxiliary data will be moved along with the container contents.
2271  */
2272 template <class T>
2273 DATAVECTOR& DATAVECTOR::operator= (DATAVECTOR&& rhs)
2274 {
2275  if (this != &rhs) {
2276  // Ensure we're not being called via a base class.
2277  // This can throw an exception, so this method should not be noexcept.
2278  testInsert ("assignment operator");
2279 
2280  this->clear(); // Release any currently-owned elements.
2281 
2282  SG::AuxVectorBase::operator= (std::move (rhs));
2283  this->m_ownPolicy = rhs.m_ownPolicy;
2284  this->m_pCont = std::move (rhs.m_pCont);
2285 
2286  delete this->m_deleter;
2287  this->m_deleter = std::move(rhs.m_deleter);
2288  rhs.m_deleter = nullptr;
2289 
2290  // Need to reset the container pointer on elements.
2291  this->setIndices (this->begin(), this->end());
2292  }
2293  return *this;
2294 }
2295 
2296 
2297 /**
2298  * @brief Assignment operator, from an initializer list.
2299  * @param l An initializer list.
2300  * @return This object.
2301  *
2302  * This is equivalent to @c assign.
2303  * Any existing owned elements will be released.
2304  * The @c DataVector's ownership policy determines whether it will take
2305  * ownership of the new elements.
2306  */
2307 template <class T>
2308 inline
2309 DATAVECTOR& DATAVECTOR::operator= (std::initializer_list<value_type> l)
2310 {
2311  this->assign (l.begin(), l.end());
2312  return *this;
2313 }
2314 
2315 
2316 /**
2317  * @brief Assign from iterators.
2318  * @param first The start of the range to put in the container.
2319  * @param last The end of the range to put in the container.
2320  *
2321  * Any existing owned elements will be released.
2322  * The @c DataVector's ownership policy determines whether it will take
2323  * ownership of the new elements.
2324  */
2325 template <class T>
2326 template <class InputIterator>
2327 void DATAVECTOR::assign (InputIterator first,
2328  InputIterator last)
2329 {
2330  // Ensure we're not being called via a base class.
2331  testInsert ("assign");
2332  clear(); // Release any currently-owned elements.
2333  insert(begin(), first, last);
2334 }
2335 
2336 
2337 /**
2338  * @brief Assign from an initializer list.
2339  * @param l An initializer list.
2340  *
2341  * Any existing owned elements will be released.
2342  * The @c DataVector's ownership policy determines whether it will take
2343  * ownership of the new elements.
2344  */
2345 template <class T>
2346 void DATAVECTOR::assign (std::initializer_list<value_type> l)
2347 {
2348  this->assign (l.begin(), l.end());
2349 }
2350 
2351 
2352 /**
2353  * @brief Destructor.
2354  *
2355  * If this container owns its elements, the contained elements will
2356  * be deleted as well. Before doing this, the destructor will scan
2357  * for duplicate pointers (takes @f$n \log n@f$ time); duplicates are only
2358  * destroyed once. Duplicates should, however, be considered an error;
2359  * don't rely on this behavior.
2360  */
2361 template <class T>
2362 DATAVECTOR::~DataVector()
2363 {
2364  if (m_ownPolicy == SG::OWN_ELEMENTS) {
2365  typename PtrVector::iterator new_end =
2366  DataVector_detail::remove_duplicates(m_pCont.begin(), m_pCont.end());
2367  this->doDelete (m_pCont.begin(), new_end);
2368  }
2369  delete m_deleter;
2370 }
2371 
2372 
2373 //=== Size and capacity.
2374 
2375 
2376 /**
2377  * @brief Returns the number of elements in the collection.
2378  */
2379 template <class T>
2380 inline
2381 typename DATAVECTOR::size_type DATAVECTOR::size() const noexcept
2382 {
2383  return m_pCont.size();
2384 }
2385 
2386 
2387 /**
2388  * @brief Returns the number of elements in the collection.
2389  *
2390  * This version is virtual, to be callable from the AuxData
2391  * base class.
2392  */
2393 template <class T>
2394 inline
2395 typename DATAVECTOR::size_type DATAVECTOR::size_v() const
2396 {
2397  return this->size();
2398 }
2399 
2400 
2401 /**
2402  * @brief Returns the @c size() of the largest possible collection.
2403  */
2404 template <class T>
2405 inline
2406 typename DATAVECTOR::size_type DATAVECTOR::max_size() const noexcept
2407 {
2408  return m_pCont.max_size();
2409 }
2410 
2411 
2412 /**
2413  * @brief Resizes the collection to the specified number of elements.
2414  * @param sz The new size of the collection.
2415  *
2416  * Note that this function differs from the standard in that it does
2417  * not allow specifying the value of any inserted elements.
2418  * They will always be 0.
2419  *
2420  * If the container is shrunk, elements will be deleted as with @c erase().
2421  */
2422 template <class T>
2423 void DATAVECTOR::resize(size_type sz)
2424 {
2425  if (sz < this->size()) {
2426  this->erase (this->begin()+sz, this->end());
2427  } else {
2428  this->m_pCont.insert(this->m_pCont.end(), sz - this->m_pCont.size(), 0);
2429  SG::AuxVectorBase::resize<DataVector> (sz);
2430  }
2431 }
2432 
2433 
2434 /**
2435  * @brief Returns the total number of elements that the collection can hold
2436  * before needing to allocate more memory.
2437  */
2438 template <class T>
2439 inline
2440 typename DATAVECTOR::size_type DATAVECTOR::capacity() const noexcept
2441 {
2442  return m_pCont.capacity();
2443 }
2444 
2445 
2446 /**
2447  * @brief Returns the total number of elements that the collection can hold
2448  * before needing to allocate more memory.
2449  *
2450  * This version is virtual, to be callable from the AuxData
2451  * base class.
2452  */
2453 template <class T>
2454 inline
2455 typename DATAVECTOR::size_type DATAVECTOR::capacity_v() const
2456 {
2457  return capacity();
2458 }
2459 
2460 
2461 /**
2462  * @brief Returns @c true if the collection is empty.
2463  */
2464 template <class T>
2465 inline
2466 bool DATAVECTOR::empty() const noexcept
2467 {
2468  return m_pCont.empty();
2469 }
2470 
2471 
2472 /**
2473  * @brief Attempt to preallocate enough memory for a specified number
2474  * of elements.
2475  * @param n Number of elements required.
2476  */
2477 template <class T>
2478 inline
2479 void DATAVECTOR::reserve (size_type n)
2480 {
2481  m_pCont.reserve (n);
2482  SG::AuxVectorBase::reserve<DataVector> (n);
2483 }
2484 
2485 
2486 /**
2487  * @brief Change the vector capacity to match the current size.
2488  *
2489  * Note: this does not affect auxiliary data.
2490  */
2491 template <class T>
2492 inline
2493 void DATAVECTOR::shrink_to_fit()
2494 {
2495  m_pCont.shrink_to_fit();
2496 }
2497 
2498 
2499 //=== Element access.
2500 
2501 
2502 /**
2503  * @brief Access an element, as an rvalue.
2504  * @param n Array index to access.
2505  * @return The element at @a n.
2506  *
2507  * No bounds checking is done.
2508  * Note that we return a @c const @c T* rather than a reference.
2509  */
2510 template <class T>
2511 inline
2512 const T* DATAVECTOR::operator[] (size_type n) const
2513 {
2514  return m_pCont[n];
2515 }
2516 
2517 
2518 /**
2519  * @brief Access an element, as an rvalue.
2520  * @param n Array index to access.
2521  * @return The element at @a n.
2522  *
2523  * This is a synonym for operator[] const, to be used when calling from root
2524  * (where we can't readily call just the const version of a method).
2525  */
2526 template <class T>
2527 inline
2528 const T* DATAVECTOR::get (size_type n) const
2529 {
2530  return do_cast(this->m_pCont[n]);
2531 }
2532 
2533 
2534 /**
2535  * @brief Access an element, as an lvalue.
2536  * @param n Array index to access.
2537  * @return Proxy to the element at @a n.
2538  *
2539  * No bounds checking is done.
2540  * Note that we return a proxy object rather than a reference;
2541  * the proxy will handle deleting an owned element if it's assigned to.
2542  */
2543 template <class T>
2544 inline
2545 typename DATAVECTOR::ElementProxy DATAVECTOR::operator[] (size_type n)
2546 {
2547  return ElementProxy (m_pCont.begin() + n, this);
2548 }
2549 
2550 
2551 /**
2552  * @brief Access an element, as an rvalue.
2553  * @param n Array index to access.
2554  * @return The element at @a n.
2555  *
2556  * Will raise @c std::out_of_range if the index is out-of-bounds.
2557  * Note that we return a @c const @c T* rather than a reference.
2558  */
2559 template <class T>
2560 inline
2561 const T* DATAVECTOR::at (size_type n) const
2562 {
2563  return m_pCont.at(n);
2564 }
2565 
2566 
2567 /**
2568  * @brief Access an element, as an lvalue.
2569  * @param n Array index to access.
2570  * @return Proxy to the element at @a n.
2571  *
2572  * Will raise @c std::out_of_range if the index is out-of-bounds.
2573  * Note that we return a proxy object rather than a reference;
2574  * the proxy will handle deleting an owned element if it's assigned to.
2575  */
2576 template <class T>
2577 inline
2578 typename DATAVECTOR::ElementProxy DATAVECTOR::at (size_type n)
2579 {
2580  // Can't use m_pCont's at here, because we need an iterator.
2581  // So we have to do the bounds check ourselves.
2582  if (n >= size())
2583  throw std::out_of_range ("DataVector::at range check");
2584  return ElementProxy (m_pCont.begin() + n, this);
2585 }
2586 
2587 
2588 /**
2589  * @brief Access the first element in the collection as an rvalue.
2590  * @return The first element in the collection.
2591  *
2592  * No checking is done to ensure that the container is not empty.
2593  * Note that we return a @c const @c T* rather than a reference.
2594  */
2595 template <class T>
2596 inline
2597 const T* DATAVECTOR::front() const
2598 {
2599  return m_pCont.front();
2600 }
2601 
2602 
2603 /**
2604  * @brief Access the last element in the collection as an rvalue.
2605  * @return The last element in the collection.
2606  *
2607  * No checking is done to ensure that the container is not empty.
2608  * Note that we return a @c const @c T* rather than a reference.
2609  */
2610 template <class T>
2611 inline
2612 const T* DATAVECTOR::back() const
2613 {
2614  return m_pCont.back();
2615 }
2616 
2617 
2618 /**
2619  * @brief Access the first element in the collection as an lvalue.
2620  * @return Proxy to the first element in the collection.
2621  *
2622  * No checking is done to ensure that the container is not empty.
2623  * Note that we return a proxy object rather than a reference;
2624  * the proxy will handle deleting an owned element if it's assigned to.
2625  */
2626 template <class T>
2627 inline
2628 typename DATAVECTOR::ElementProxy DATAVECTOR::front ()
2629 {
2630  return ElementProxy (m_pCont.begin(), this);
2631 }
2632 
2633 
2634 /**
2635  * @brief Access the last element in the collection as an lvalue.
2636  * @return Proxy to the last element in the collection.
2637  *
2638  * No checking is done to ensure that the container is not empty.
2639  * Note that we return a proxy object rather than a reference;
2640  * the proxy will handle deleting an owned element if it's assigned to.
2641  */
2642 template <class T>
2643 inline
2644 typename DATAVECTOR::ElementProxy DATAVECTOR::back ()
2645 {
2646  return ElementProxy (m_pCont.end()-1, this);
2647 }
2648 
2649 
2650 //=== Iterator creation.
2651 
2652 
2653 /**
2654  * @brief Return a @c const_iterator pointing at the beginning
2655  * of the collection.
2656  * @return A @c const_iterator.
2657  *
2658  * Note that dereferencing the iterator will yield a @c const @c T* rather
2659  * than a reference.
2660  */
2661 template <class T>
2662 inline
2663 typename DATAVECTOR::const_iterator DATAVECTOR::begin() const noexcept
2664 {
2665  return m_pCont.begin();
2666 }
2667 
2668 
2669 /**
2670  * @brief Return a @c const_iterator pointing past the end
2671  * of the collection.
2672  * @return A @c const_iterator.
2673  *
2674  * Note that dereferencing the iterator will yield a @c const @c T* rather
2675  * than a reference.
2676  */
2677 template <class T>
2678 inline
2679 typename DATAVECTOR::const_iterator DATAVECTOR::end() const noexcept
2680 {
2681  return m_pCont.end();
2682 }
2683 
2684 
2685 /**
2686  * @brief Return an @c iterator pointing at the beginning
2687  * of the collection.
2688  * @return An @c iterator.
2689  *
2690  * Note that dereferencing the iterator will yield a proxy rather
2691  * than a reference; the proxy will handle deleting an owned element
2692  * if it's assigned to.
2693  */
2694 template <class T>
2695 inline
2696 typename DATAVECTOR::iterator DATAVECTOR::begin() noexcept
2697 {
2698  return iterator (m_pCont.begin(), this);
2699 }
2700 
2701 
2702 /**
2703  * @brief Return an @c iterator pointing past the end
2704  * of the collection.
2705  * @return An @c iterator.
2706  *
2707  * Note that dereferencing the iterator will yield a proxy rather
2708  * than a reference; the proxy will handle deleting an owned element
2709  * if it's assigned to.
2710  */
2711 template <class T>
2712 inline
2713 typename DATAVECTOR::iterator DATAVECTOR::end() noexcept
2714 {
2715  return iterator (m_pCont.end(), this);
2716 }
2717 
2718 
2719 /**
2720  * @brief Return a @c const_reverse_iterator pointing past the end
2721  * of the collection.
2722  * @return A @c const_reverse_iterator.
2723  *
2724  * Note that dereferencing the iterator will yield a @c const @c T* rather
2725  * than a reference.
2726  */
2727 template <class T>
2728 inline
2729 typename DATAVECTOR::const_reverse_iterator DATAVECTOR::rbegin() const noexcept
2730 {
2731  return const_reverse_iterator (m_pCont.end());
2732 }
2733 
2734 
2735 /**
2736  * @brief Return a @c const_reverse_iterator pointing at the beginning
2737  * of the collection.
2738  * @return A @c const_reverse_iterator.
2739  *
2740  * Note that dereferencing the iterator will yield a @c const @c T* rather
2741  * than a reference.
2742  */
2743 template <class T>
2744 inline
2745 typename DATAVECTOR::const_reverse_iterator DATAVECTOR::rend() const noexcept
2746 {
2747  return const_reverse_iterator (const_iterator (m_pCont.begin()));
2748 }
2749 
2750 
2751 /**
2752  * @brief Return a @c reverse_iterator pointing past the end
2753  * of the collection.
2754  * @return A @c reverse_iterator.
2755  *
2756  * Note that dereferencing the iterator will yield a proxy rather
2757  * than a reference; the proxy will handle deleting an owned element
2758  * if it's assigned to.
2759  */
2760 template <class T>
2761 inline
2762 typename DATAVECTOR::reverse_iterator DATAVECTOR::rbegin() noexcept
2763 {
2764  return reverse_iterator(iterator (m_pCont.end(), this));
2765 }
2766 
2767 
2768 /**
2769  * @brief Return a @c reverse_iterator pointing at the beginning
2770  * of the collection.
2771  * @return A @c reverse_iterator.
2772  *
2773  * Note that dereferencing the iterator will yield a proxy rather
2774  * than a reference; the proxy will handle deleting an owned element
2775  * if it's assigned to.
2776  */
2777 template <class T>
2778 inline
2779 typename DATAVECTOR::reverse_iterator DATAVECTOR::rend() noexcept
2780 {
2781  return reverse_iterator(iterator (m_pCont.begin(), this));
2782 }
2783 
2784 
2785 /**
2786  * @brief Return a @c const_iterator pointing at the beginning
2787  * of the collection.
2788  * @return A @c const_iterator.
2789  *
2790  * Note that dereferencing the iterator will yield a @c const @c T* rather
2791  * than a reference.
2792  */
2793 template <class T>
2794 inline
2795 typename DATAVECTOR::const_iterator DATAVECTOR::cbegin() const noexcept
2796 {
2797  return m_pCont.begin();
2798 }
2799 
2800 
2801 /**
2802  * @brief Return a @c const_iterator pointing past the end
2803  * of the collection.
2804  * @return A @c const_iterator.
2805  *
2806  * Note that dereferencing the iterator will yield a @c const @c T* rather
2807  * than a reference.
2808  */
2809 template <class T>
2810 inline
2811 typename DATAVECTOR::const_iterator DATAVECTOR::cend() const noexcept
2812 {
2813  return m_pCont.end();
2814 }
2815 
2816 
2817 /**
2818  * @brief Return a @c const_reverse_iterator pointing past the end
2819  * of the collection.
2820  * @return A @c const_reverse_iterator.
2821  *
2822  * Note that dereferencing the iterator will yield a @c const @c T* rather
2823  * than a reference.
2824  */
2825 template <class T>
2826 inline
2827 typename DATAVECTOR::const_reverse_iterator DATAVECTOR::crbegin() const noexcept
2828 {
2829  return const_reverse_iterator (m_pCont.end());
2830 }
2831 
2832 
2833 /**
2834  * @brief Return a @c const_reverse_iterator pointing at the beginning
2835  * of the collection.
2836  * @return A @c const_reverse_iterator.
2837  *
2838  * Note that dereferencing the iterator will yield a @c const @c T* rather
2839  * than a reference.
2840  */
2841 template <class T>
2842 inline
2843 typename DATAVECTOR::const_reverse_iterator DATAVECTOR::crend() const noexcept
2844 {
2845  return const_reverse_iterator (const_iterator (m_pCont.begin()));
2846 }
2847 
2848 
2849 //=== Insertion operations.
2850 
2851 
2852 /**
2853  * @brief Add an element to the end of the collection.
2854  * @param pElem The element to add to the collection.
2855  *
2856  * The container's ownership policy will determine if it takes ownership
2857  * of the new element.
2858  *
2859  * Note: this method may only be called using the most derived
2860  * @c DataVector in the hierarchy.
2861  *
2862  * Returns the pushed pointer.
2863  */
2864 template <class T>
2865 inline
2866 typename DATAVECTOR::value_type
2867 DATAVECTOR::push_back(value_type pElem)
2868 {
2869  // Ensure we're not being called via a base class.
2870  testInsert ("push_back");
2871  m_pCont.push_back(pElem);
2872  SG::AuxVectorBase::resize<DataVector> (this->size());
2873  if (pElem)
2874  this->moveAux (this->size()-1, pElem, false, true);
2875  return pElem;
2876 }
2877 
2878 
2879 /**
2880  * @brief Add an element to the end of the collection.
2881  * @param pElem The element to add to the collection.
2882  *
2883  * The container must be an owning container.
2884  *
2885  * Note: this method may only be called using the most derived
2886  * @c DataVector in the hierarchy.
2887  *
2888  * Returns the pushed pointer.
2889  */
2890 template <class T>
2891 inline
2892 typename DATAVECTOR::value_type
2893 DATAVECTOR::push_back(std::unique_ptr<base_value_type> pElem)
2894 {
2895  // Container must own its elements.
2896  if (this->m_ownPolicy != SG::OWN_ELEMENTS)
2897  SG::throwExcNonowningContainer();
2898 
2899  // Ensure we're not being called via a base class.
2900  testInsert ("push_back");
2901  value_type ptr = pElem.release();
2902  m_pCont.push_back(ptr);
2903  SG::AuxVectorBase::resize<DataVector> (this->size());
2904  if (ptr)
2905  this->moveAux (this->size()-1, ptr, false, true);
2906  return ptr;
2907 }
2908 
2909 
2910 /**
2911  * @brief Add an element to the end of the collection.
2912  * @param pElem The element to add to the collection.
2913  *
2914  * The container's ownership policy will determine if it takes ownership
2915  * of the new element.
2916  *
2917  * Note: this method may only be called using the most derived
2918  * @c DataVector in the hierarchy.
2919  *
2920  * For @c DataVector, this is like the same as @c push_back, and
2921  * it returns the pushed element.
2922  * It's included just for interface compatibility with `std::vector`.
2923  */
2924 template <class T>
2925 inline
2926 typename DATAVECTOR::value_type
2927 DATAVECTOR::emplace_back(value_type pElem)
2928 {
2929  return this->push_back (pElem);
2930 }
2931 
2932 
2933 /**
2934  * @brief Add a new element to the collection.
2935  * @param position Iterator before which the element will be added.
2936  * @param pElem The element to add to the collection.
2937  * @return An iterator that points to the inserted data.
2938  *
2939  * The container's ownership policy will determine if it takes ownership
2940  * of the new element.
2941  *
2942  * Note: this method may only be called using the most derived
2943  * @c DataVector in the hierarchy.
2944  */
2945 template <class T>
2946 inline
2947 typename DATAVECTOR::iterator
2948 DATAVECTOR::insert(iterator position, value_type pElem)
2949 {
2950  // Ensure we're not being called via a base class.
2951  testInsert ("insert");
2952  iterator ret (m_pCont.insert(position.base(), pElem), this);
2953  this->shift (ret - this->begin(), 1);
2954  this->moveAux (ret-this->begin(), pElem, false, true);
2955  return ret;
2956 }
2957 
2958 
2959 /**
2960  * @brief Add a new element to the collection.
2961  * @param position Iterator before which the element will be added.
2962  * @param pElem The element to add to the collection.
2963  * @return An iterator that points to the inserted data.
2964  *
2965  * The container must be an owning container.
2966  *
2967  * Note: this method may only be called using the most derived
2968  * @c DataVector in the hierarchy.
2969  */
2970 template <class T>
2971 inline
2972 typename DATAVECTOR::iterator
2973 DATAVECTOR::insert(iterator position, std::unique_ptr<base_value_type> pElem)
2974 {
2975  // Container must own its elements.
2976  if (this->m_ownPolicy != SG::OWN_ELEMENTS)
2977  SG::throwExcNonowningContainer();
2978 
2979  // Ensure we're not being called via a base class.
2980  testInsert ("insert");
2981  value_type ptr = pElem.release();
2982  iterator ret (m_pCont.insert(position.base(), ptr), this);
2983  this->shift (ret - this->begin(), 1);
2984  this->moveAux (ret-this->begin(), ptr, false, true);
2985  return ret;
2986 }
2987 
2988 
2989 /**
2990  * @brief Add a new element to the collection.
2991  * @param position Iterator before which the element will be added.
2992  * @param pElem The element to add to the collection.
2993  * @return An iterator that points to the inserted data.
2994  *
2995  * The container's ownership policy will determine if it takes ownership
2996  * of the new element.
2997  *
2998  * Note: this method may only be called using the most derived
2999  * @c DataVector in the hierarchy.
3000  *
3001  * For @c DataVector, this is just the same as @c insert.
3002  * It's included just for interface compatibility with `std::vector`.
3003  */
3004 template <class T>
3005 inline
3006 typename DATAVECTOR::iterator
3007 DATAVECTOR::emplace(iterator position, value_type pElem)
3008 {
3009  return this->insert (position, pElem);
3010 }
3011 
3012 
3013 /**
3014  * @brief Add a group of new elements to the collection.
3015  * @param position Iterator before which the element will be added.
3016  * @param first The start of the range to put in the container.
3017  * @param last The end of the range to put in the container.
3018  *
3019  * The container's ownership policy will determine if it takes ownership
3020  * of the new element.
3021  *
3022  * Note: this method may only be called using the most derived
3023  * @c DataVector in the hierarchy.
3024  *
3025  * This overload is for the case where the iterator value type
3026  * is convertible to T*.
3027  */
3028 template <class T>
3029 template <class InputIterator,
3030  DataVector_detail::enable_if_ptr_itr<InputIterator, T> >
3031 inline
3032 void
3033 DATAVECTOR::insert (iterator position, InputIterator first, InputIterator last)
3034 {
3035  static_assert (std::is_same_v<T*, typename DATAVECTOR::value_type>);
3036  // Ensure we're not being called via a base class.
3037  testInsert ("insert");
3038  size_t idx = position - this->begin();
3039  size_t old_sz = this->m_pCont.size();
3040  m_pCont.insert(position.base(), first, last);
3041  size_t n = this->m_pCont.size() - old_sz;
3042  this->shift (idx, n);
3043  this->moveAux (idx, first, last, false, true);
3044 }
3045 
3046 
3047 /**
3048  * @brief Add a group of new elements to the collection.
3049  * @param position Iterator before which the element will be added.
3050  * @param first The start of the range to put in the container.
3051  * @param last The end of the range to put in the container.
3052  *
3053  * The container's ownership policy will determine if it takes ownership
3054  * of the new element.
3055  *
3056  * Note: this method may only be called using the most derived
3057  * @c DataVector in the hierarchy.
3058  *
3059  * This overload is for the case where the iterator value type
3060  * is convertible to unique_ptr<T>.
3061  */
3062 template <class T>
3063 template <class InputIterator,
3064  DataVector_detail::enable_if_up_itr<InputIterator, T> >
3065 inline
3066 void
3067 DATAVECTOR::insert (iterator position, InputIterator first, InputIterator last)
3068 {
3069  // Ensure we're not being called via a base class.
3070  testInsert ("insert");
3071  size_t idx = position - this->begin();
3072  size_t old_sz = this->m_pCont.size();
3073  using CxxUtils::releasing_iterator;
3074  m_pCont.insert(position.base(), releasing_iterator(first), releasing_iterator(last));
3075  size_t n = this->m_pCont.size() - old_sz;
3076  this->shift (idx, n);
3077  this->moveAux (idx, this->begin()+idx, this->begin()+idx+n);
3078 }
3079 
3080 
3081 /**
3082  * @brief Add a group of new elements to the collection.
3083  * @param position Iterator before which the element will be added.
3084  * @param l An initializer list.
3085  *
3086  * The container's ownership policy will determine if it takes ownership
3087  * of the new element.
3088  *
3089  * Note: this method may only be called using the most derived
3090  * @c DataVector in the hierarchy.
3091  */
3092 template <class T>
3093 inline
3094 void
3095 DATAVECTOR::insert (iterator position, std::initializer_list<value_type> l)
3096 {
3097  this->insert (position, l.begin(), l.end());
3098 }
3099 
3100 
3101 /**
3102  * @brief Insert the contents of another @c DataVector,
3103  * with auxiliary data copied via move semantics.
3104  * @param position Iterator before which the new elements will be added.
3105  * @param other The vector to add.
3106  *
3107  * The ownership mode of this vector must be the same as @c other;
3108  * otherwise, an exception will be thrown.
3109  *
3110  * If both vectors are view vectors, then this is the same
3111  * as <code> insert (position, other.begin(), other.end()) </code>.
3112  *
3113  * Otherwise, the elements from @c other will be inserted into this vector.
3114  * This vector will take ownership of the elements, and the ownership
3115  * mode of @c other will be changed to @c VIEW_ELEMENTS.
3116  * Auxiliary data for these elements will be transferred,
3117  * using move semantics if possible. (Thus, the auxiliary store
3118  * for @c other may be modified and must not be locked.)
3119  * Finally, the auxiliary store pointer for @c other will be cleared
3120  * (but the store itself will not be deleted since it's not owned
3121  * by the vector).
3122  *
3123  * Note: this method may only be called using the most derived
3124  * @c DataVector in the hierarchy.
3125  */
3126 template <class T>
3127 void
3128 DATAVECTOR::insertMove (iterator position, DataVector& other)
3129 {
3130  if (this->m_ownPolicy != other.ownPolicy())
3131  throw SG::ExcInsertMoveOwnershipMismatch();
3132 
3133  if (this->m_ownPolicy == SG::VIEW_ELEMENTS) {
3134  this->insert (position, other.begin(), other.end());
3135  return;
3136  }
3137 
3138  testInsert ("insertMove");
3139  size_t pos = position.base() - this->m_pCont.begin();
3140  this->m_pCont.insert (position.base(), other.begin(), other.end());
3141  this->setIndices (this->begin()+pos, this->end(), pos);
3142  other.m_ownPolicy = SG::VIEW_ELEMENTS;
3143 
3144  SG::IAuxStore* otherStore = other.getStore();
3145  if (otherStore) {
3146  SG::IAuxStore* store = this->getStore();
3147  if (store) {
3148  if (!store->insertMove (pos, *otherStore))
3149  this->clearCache();
3150  }
3151  else if (this->hasStore())
3152  throw SG::ExcConstAuxData ("insertMove");
3153  other.setStore (static_cast<SG::IAuxStore*>(nullptr));
3154  }
3155  else if (other.hasStore())
3156  throw SG::ExcConstAuxData ("insertMove");
3157 }
3158 
3159 
3160 //=== Erasure operations.
3161 
3162 
3163 /**
3164  * @brief Remove element at a given position.
3165  * @param position Iterator pointing to the element to be removed.
3166  * @return An iterator pointing to the next element (or @c end()).
3167  *
3168  * If the container owns its elements, then the pointed-to element
3169  * will be deleted.
3170  */
3171 template <class T>
3172 inline
3173 typename DATAVECTOR::iterator DATAVECTOR::erase(iterator position)
3174 {
3175  if (this->m_ownPolicy != SG::OWN_ELEMENTS)
3176  this->clearIndex (position);
3177  iterator ret (this->erase_base (position.base()), this);
3178  this->shift (ret - this->begin() + 1, -1);
3179  return ret;
3180 }
3181 
3182 
3183 /**
3184  * @brief Remove a range of elements.
3185  * @param first Iterator pointing to the first element to be removed.
3186  * @param last Iterator pointing one past the last element to be removed.
3187  * @return An iterator pointing to the element pointed to by @a last
3188  * prior to erasing (or @c end()).
3189  *
3190  * If the container owns its elements, then the removed elements
3191  * will be deleted. Any duplicates will be removed in this process,
3192  * but don't rely on this.
3193  */
3194 template <class T>
3195 inline
3196 typename DATAVECTOR::iterator DATAVECTOR::erase(iterator first, iterator last)
3197 {
3198  if (this->m_ownPolicy != SG::OWN_ELEMENTS)
3199  this->clearIndices (first, last);
3200  iterator ret (this->erase_base (first.base(), last.base()), this);
3201  this->shift (ret - this->begin() + (last-first), -(last-first));
3202  return ret;
3203 }
3204 
3205 
3206 /**
3207  * @brief Remove the last element from the collection.
3208  *
3209  * If the container owns its elements, then the removed element
3210  * will be deleted.
3211  */
3212 template <class T>
3213 void DATAVECTOR::pop_back()
3214 {
3215  if (!m_pCont.empty()) {
3216  if (m_ownPolicy == SG::OWN_ELEMENTS)
3217  this->doDelete (m_pCont.back());
3218  else
3219  this->clearIndex (m_pCont.end() - 1);
3220  m_pCont.pop_back();
3221  SG::AuxVectorBase::resize<DataVector> (this->m_pCont.size());
3222  }
3223 }
3224 
3225 
3226 /**
3227  * @brief Erase all the elements in the collection.
3228  *
3229  * If the container owns its elements, then the removed elements
3230  * will be deleted. Any duplicates will be removed in this process,
3231  * but don't rely on this.
3232  */
3233 template <class T>
3234 inline
3235 void DATAVECTOR::clear()
3236 {
3237  if (this->m_ownPolicy != SG::OWN_ELEMENTS)
3238  this->clearIndices (begin(), end());
3239  this->erase_base (m_pCont.begin(), m_pCont.end());
3240  SG::AuxVectorBase::resize<DataVector> (0);
3241 }
3242 
3243 
3244 //=== Swap and sort.
3245 
3246 
3247 /**
3248  * @brief Swap this collection with another.
3249  * @param rhs The collection with which to swap.
3250  *
3251  * Ownership is swapped along with the collection content.
3252  *
3253  * Note: this method may only be called using the most-derived
3254  * @c DataVector in the hierarchy. The @a rhs must also be
3255  * referenced using the most-derived @c DataVector.
3256  *
3257  * Warning: If this container has auxiliary data, then this
3258  * is an O(N) operation, not O(1).
3259  */
3260 template <class T>
3261 void DATAVECTOR::swap(DataVector& rhs)
3262 {
3263  testInsert ("swap");
3264  rhs.testInsert ("swap");
3265  std::swap(m_ownPolicy, rhs.m_ownPolicy);
3266  SG::AuxVectorBase::swap (rhs);
3267  m_pCont.swap(rhs.m_pCont);
3268  std::swap (this->m_deleter, rhs.m_deleter);
3269  this->setIndices (this->begin(), this->end());
3270  rhs.setIndices (rhs.begin(), rhs.end());
3271 }
3272 
3273 
3274 /**
3275  * @brief Swap the referents of two @c DataVector iterators.
3276  * @param a The first iterator for the swap.
3277  * @param b The second iterator for the swap.
3278  */
3279 template <class T>
3280 void DATAVECTOR::iter_swap (iterator a, iterator b)
3281 {
3282  if (a.ownPolicy() != b.ownPolicy()) {
3283  throw SG::ExcBadIterSwap();
3284  }
3285  a.testInsert ("iter_swap");
3286  b.testInsert ("iter_swap");
3287  std::iter_swap (a.base(), b.base());
3288  DataVector* acont = a.container();
3289  DataVector* bcont = b.container();
3290  if (typename SG::AuxStore_traits<DataVector>::flag())
3291  acont->swapElementsAux (a.base() - acont->stdcont().begin(),
3292  b.base() - bcont->stdcont().begin(),
3293  *a.base(),
3294  *b.base(),
3295  bcont);
3296 }
3297 
3298 
3299 /**
3300  * @brief Sort the container.
3301  *
3302  * This just sorts by pointer value, so it's probably not very useful.
3303  */
3304 template <class T>
3305 void DATAVECTOR::sort()
3306 {
3307  std::sort(m_pCont.begin(), m_pCont.end());
3308  this->resortAux (this->begin(), this->end());
3309 }
3310 
3311 
3312 /**
3313  * @brief Sort the container with a user-specified comparison operator.
3314  * @param comp Functional to compare two values.
3315  */
3316 template <class T>
3317 template <class COMPARE>
3318 void DATAVECTOR::sort(COMPARE comp)
3319 {
3320  std::sort(m_pCont.begin(), m_pCont.end(), comp);
3321  this->resortAux (this->begin(), this->end());
3322 }
3323 
3324 
3325 //=== Non-standard operations.
3326 
3327 
3328 /**
3329  * @brief Swap one element out of the container.
3330  * @param index Index of the element in the container to swap.
3331  * @param newElement New element to put in the container.
3332  * May be 0.
3333  * @param oldElem Reference to receive the element removed from the
3334  * container.
3335  *
3336  * Reference @a oldElem is initialized with element @a index of the
3337  * collection (no bounds checking). Then element @a index is set
3338  * to @newElem. If the collection owns its elements, then it will
3339  * take ownership of @a newElem and release (without deleting)
3340  * the element returned through @a oldElem.
3341  *
3342  * Note: this method may only be called using the most derived
3343  * @c DataVector in the hierarchy.
3344  */
3345 template <class T>
3346 void
3347 DATAVECTOR::swapElement (size_type index,
3348  value_type newElem,
3349  reference oldElem)
3350 {
3351  testInsert ("swapElement");
3352  oldElem = m_pCont[index];
3353  this->clearIndex (iterator (m_pCont.begin() + index, this));
3354  m_pCont[index] = newElem;
3355  this->moveAux (index, newElem);
3356 }
3357 
3358 
3359 /**
3360  * @brief Swap one element out of the container.
3361  * @param pos The element in the container to swap.
3362  * @param newElem New element to put in the container.
3363  * May be 0.
3364  * @param oldElem Reference to receive the element removed from the
3365  * container.
3366  *
3367  * Reference @a oldElem is initialized with element @a pos of the
3368  * collection (no bounds checking). Then element @a index is set
3369  * to @c newElem. If the collection owns its elements, then it will
3370  * take ownership of @a newElem and release (without deleting)
3371  * the element returned through @a oldElem.
3372  *
3373  * Note: this method may only be called using the most derived
3374  * @c DataVector in the hierarchy.
3375  */
3376 template <class T>
3377 void
3378 DATAVECTOR::swapElement (iterator pos,
3379  value_type newElem,
3380  reference oldElem)
3381 {
3382  testInsert ("swapElement");
3383  oldElem = *pos.base();
3384  this->clearIndex (pos);
3385  *pos.base() = newElem;
3386  this->moveAux (pos.base() - this->m_pCont.begin(), newElem);
3387 }
3388 
3389 
3390 /**
3391  * @brief Swap one element out of the container.
3392  * @param index Index of the element in the container to swap.
3393  * @param newElement New element to put in the container.
3394  * May be 0.
3395  * @param oldElem Reference to receive the element removed from the
3396  * container.
3397  *
3398  * Reference @a oldElem is initialized with element @a index of the
3399  * collection (no bounds checking). Then element @a index is set
3400  * to @newElem.
3401  *
3402  * The collection must own its elements to use its interface.
3403  * The collection will take ownership of @c newElem and will return
3404  * ownership of @c oldElem.
3405  *
3406  * Note: this method may only be called using the most derived
3407  * @c DataVector in the hierarchy.
3408  */
3409 template <class T>
3410 void
3411 DATAVECTOR::swapElement (size_type index,
3412  std::unique_ptr<base_value_type> newElem,
3413  std::unique_ptr<base_value_type>& oldElem)
3414 {
3415  // Container must own its elements.
3416  if (this->m_ownPolicy != SG::OWN_ELEMENTS)
3417  SG::throwExcNonowningContainer();
3418 
3419  testInsert ("swapElement");
3420  oldElem = std::unique_ptr<base_value_type> (m_pCont[index]);
3421  this->clearIndex (iterator (m_pCont.begin() + index, this));
3422  value_type ptr = newElem.release();
3423  m_pCont[index] = ptr;
3424  this->moveAux (index, ptr);
3425 }
3426 
3427 
3428 /**
3429  * @brief Swap one element out of the container.
3430  * @param pos The element in the container to swap.
3431  * @param newElem New element to put in the container.
3432  * May be 0.
3433  * @param oldElem Reference to receive the element removed from the
3434  * container.
3435  *
3436  * Reference @a oldElem is initialized with element @a pos of the
3437  * collection (no bounds checking). Then element @a index is set
3438  * to @c newElem.
3439  *
3440  * The collection must own its elements to use its interface.
3441  * The collection will take ownership of @c newElem and will return
3442  * ownership of @c oldElem.
3443  *
3444  * Note: this method may only be called using the most derived
3445  * @c DataVector in the hierarchy.
3446  */
3447 template <class T>
3448 void
3449 DATAVECTOR::swapElement (iterator pos,
3450  std::unique_ptr<base_value_type> newElem,
3451  std::unique_ptr<base_value_type>& oldElem)
3452 {
3453  // Container must own its elements.
3454  if (this->m_ownPolicy != SG::OWN_ELEMENTS)
3455  SG::throwExcNonowningContainer();
3456 
3457  testInsert ("swapElement");
3458  oldElem = std::unique_ptr<base_value_type> (*pos.base());
3459  this->clearIndex (pos);
3460  value_type ptr = newElem.release();
3461  *pos.base() = ptr;
3462  this->moveAux (pos.base() - this->m_pCont.begin(), ptr);
3463 }
3464 
3465 
3466 /**
3467  * @brief Return the underlying @c std::vector of the container.
3468  * @return Reference to the @c std::vector actually holding the collection.
3469  *
3470  * Note that @c DataVector<T>::stdcont does not necessarily return
3471  * a @c std::vector<T*> if @c DataVector inheritance is being used.
3472  */
3473 template <class T>
3474 inline
3475 const typename DATAVECTOR::PtrVector& DATAVECTOR::stdcont() const
3476 {
3477  return m_pCont;
3478 }
3479 
3480 
3481 /**
3482  * @brief Return the ownership policy setting for this container.
3483  */
3484 template <class T>
3485 inline
3486 SG::OwnershipPolicy DATAVECTOR::ownPolicy() const
3487 {
3488  return m_ownPolicy;
3489 }
3490 
3491 
3492 /**
3493  * @brief Erase all the elements in the collection, and reset
3494  * the ownership mode.
3495  * @param ownPolicy The new ownership policy of the container.
3496  * @param trackIndices The index tracking policy.
3497  *
3498  * If the container owns its elements, then the removed elements
3499  * will be deleted. Any duplicates will be removed in this process,
3500  * but don't rely on this.
3501  */
3502 template <class T>
3503 void DATAVECTOR::clear (SG::OwnershipPolicy ownPolicy)
3504 {
3505  clear();
3506  m_ownPolicy = ownPolicy;
3507  this->template initAuxVectorBase<DataVector> (ownPolicy,
3508  SG::DEFAULT_TRACK_INDICES);
3509 }
3510 
3511 
3512 /**
3513  * @brief Erase all the elements in the collection, and reset
3514  * the ownership mode.
3515  * @param ownPolicy The new ownership policy of the container.
3516  * @param trackIndices The index tracking policy.
3517  *
3518  * If the container owns its elements, then the removed elements
3519  * will be deleted. Any duplicates will be removed in this process,
3520  * but don't rely on this.
3521  */
3522 template <class T>
3523 void DATAVECTOR::clear (SG::OwnershipPolicy ownPolicy,
3524  SG::IndexTrackingPolicy trackIndices)
3525 {
3526  clear();
3527  m_ownPolicy = ownPolicy;
3528  this->template initAuxVectorBase<DataVector> (ownPolicy, trackIndices);
3529 }
3530 
3531 
3532 /**
3533  * @brief Return the DV/DL info struct for this class.
3534  *
3535  * This can be used to make sure that it's instantiated.
3536  */
3537 template <class T>
3538 const DataModel_detail::DVLInfoBase& DATAVECTOR::dvlinfo()
3539 {
3540  static const DataModel_detail::DVLInfo<DataVector<T, DataModel_detail::NoBase> > info;
3541  return info;
3542 }
3543 
3544 
3545 /**
3546  * @brief Erase all the elements in the collection, and change
3547  * how elements are to be deleted.
3548  * @param deleter Object to be used to delete object.
3549  * (The DataVector does not take ownership.)
3550  * Passing nullptr will change back to the default.
3551  *
3552  * If the container owns its elements, then the removed elements
3553  * will be deleted. Any duplicates will be removed in this process,
3554  * but don't rely on this.
3555  * After the current elements are deleted, the Deleter object is changed.
3556  */
3557 template <class T>
3558 void DATAVECTOR::clear (std::unique_ptr<Deleter> deleter)
3559 {
3560  this->clear();
3561  delete this->m_deleter;
3562  this->m_deleter = deleter.release();
3563 }
3564 
3565 
3566 /**
3567  * @brief Return the DV/DL info struct for this class.
3568  *
3569  * This can be used to make sure that it's instantiated.
3570  */
3571 template <class T>
3572 const DataModel_detail::DVLInfoBase& DATAVECTOR::dvlinfo_v() const
3573 {
3574  return DATAVECTOR::dvlinfo();
3575 }
3576 
3577 
3578 /**
3579  * @brief Return the offset of a base @c DataVector class.
3580  * @param ti @c std::type_info of the desired class.
3581  *
3582  * If @c ti represents a @c DataVector base class of this one,
3583  * then return the offset of that base class. Otherwise, return -1.
3584  *
3585  * This function is here due to limitations of root 6, which can't
3586  * calculate these offsets correctly from the dictionary if
3587  * virtual derivation is used.
3588  */
3589 template <class T>
3590 int DATAVECTOR::baseOffset (const std::type_info& ti)
3591 {
3592  if (typeid(DataVector) == ti)
3593  return 0;
3594  return -1;
3595 }
3596 
3597 
3598 /**
3599  * @brief Convert to @c AuxVectorBase.
3600  *
3601  * Needed to get @x AuxVectorBase from a @c ConstDataVector.
3602  * Present in @c DataVector as well for consistency.
3603  */
3604 template <class T>
3605 inline
3606 const SG::AuxVectorBase& DATAVECTOR::auxbase() const
3607 {
3608  return *this;
3609 }
3610 
3611 
3612 //=== Internal operations.
3613 
3614 
3615 /**
3616  * @brief Helper for @c baseOffset.
3617  * @param p Pointer to the start of the top-level object.
3618  * @param dv Reference to the DataVector object.
3619  * @param ti @c std::type_info of the desired class.
3620  *
3621  * If @c ti represents a @c DataVector base class of this one,
3622  * then return the offset of that base class. Otherwise, return -1.
3623  *
3624  */
3625 template <class T>
3626 int DATAVECTOR::baseOffset1 (const char* p, const DataVector& dv,
3627  const std::type_info& ti)
3628 {
3629  if (typeid(DataVector) == ti)
3630  return reinterpret_cast<const char*>(&dv) - p;
3631  return -1;
3632 }
3633 
3634 
3635 /**
3636  * @brief Reset indices / reorder aux data after elements have been permuted.
3637  * @param beg Start of the range of elements to process.
3638  * @param end End of the range of elements to process.
3639  *
3640  * Call this after some operation that has permuted the elements in the
3641  * container (such as sort). The index information in the elements
3642  * will be used to permute all auxiliary data in the same way.
3643  * Finally, all the indices will be reset in the correct order.
3644  */
3645 template <class T>
3646 void DATAVECTOR::resortAux (iterator beg, iterator end)
3647 {
3648  if (typename SG::AuxStore_traits<DataVector>::flag() &&
3649  beg >= this->begin() && end <= this->end())
3650  {
3651  SG::AuxVectorBase::resortAux (beg-begin(), beg, end);
3652  }
3653 }
3654 
3655 
3656 /**
3657  * @brief Handle element assignment.
3658  * @param pos Position in the container to assign.
3659  * @param newElem The new element to assign.
3660  *
3661  * The old element is freed if this container owns elements.
3662  * Auxiliary data are copied if appropriate.
3663  */
3664 template <class T>
3665 void DATAVECTOR::assignElement (typename BaseContainer::iterator pos,
3666  value_type newElem)
3667 {
3668  testInsert ("assignElement");
3669  if (this->m_ownPolicy == SG::OWN_ELEMENTS)
3670  this->doDelete (*pos);
3671  else
3672  this->clearIndex (iterator (pos, this));
3673  *pos = newElem;
3674  this->moveAux (pos - this->m_pCont.begin(), newElem);
3675 }
3676 
3677 
3678 /**
3679  * @brief Handle element assignment.
3680  * @param pos Position in the container to assign.
3681  * @param newElem The new element to assign.
3682  *
3683  * The container must own its elements.
3684  * Auxiliary data are copied if appropriate.
3685  */
3686 template <class T>
3687 void
3688 DATAVECTOR::assignElement (typename BaseContainer::iterator pos,
3689  std::unique_ptr<base_value_type> newElem)
3690 {
3691  // Container must own its elements.
3692  if (this->m_ownPolicy != SG::OWN_ELEMENTS)
3693  SG::throwExcNonowningContainer();
3694 
3695  testInsert ("assignElement");
3696  this->doDelete (*pos);
3697  value_type ptr = newElem.release();
3698  *pos = ptr;
3699  this->moveAux (pos - this->m_pCont.begin(), ptr);
3700 }
3701 
3702 
3703 /**
3704  * @brief Handle element assignment from a base pointer.
3705  * @param pos Position in the container to assign.
3706  * @param newElem The new element to assign.
3707  *
3708  * The old element is freed if this container owns elements.
3709  * Auxiliary data are copied if appropriate.
3710  */
3711 template <class T>
3712 void DATAVECTOR::assignBaseElement (typename BaseContainer::iterator pos,
3713  typename BaseContainer::value_type newElem)
3714 {
3715  testInsert ("assignBaseElement");
3716  if (this->m_ownPolicy == SG::OWN_ELEMENTS)
3717  this->doDelete (*pos);
3718  else
3719  this->clearIndex (iterator (pos, this));
3720  *pos = newElem;
3721  if (typename SG::AuxStore_traits<DataVector>::flag())
3722  this->moveAux (pos - this->m_pCont.begin(), newElem);
3723 }
3724 
3725 
3726 /**
3727  * @brief Shift the auxiliary elements of the container.
3728  * @param pos The starting index for the shift.
3729  * @param offs The (signed) amount of the shift.
3730  *
3731  * The elements in the container should have already been shifted;
3732  * this operation will then adjust the element indices and also shift
3733  * the elements in the vectors for all aux data items.
3734  * @c offs may be either positive or negative.
3735  *
3736  * If @c offs is positive, then the container is growing.
3737  * The container size should be increased by @c offs,
3738  * the element at @c pos moved to @c pos + @c offs,
3739  * and similarly for following elements.
3740  * The elements between @c pos and @c pos + @c offs should
3741  * be default-initialized.
3742  *
3743  * If @c offs is negative, then the container is shrinking.
3744  * The element at @c pos should be moved to @c pos + @c offs,
3745  * and similarly for following elements.
3746  * The container should then be shrunk by @c -offs elements
3747  * (running destructors as appropriate).
3748  */
3749 template <class T>
3750 void DATAVECTOR::shift (size_t pos, ptrdiff_t offs)
3751 {
3752  SG::AuxVectorBase::shift (*this, pos, offs);
3753 }
3754 
3755 
3756 /**
3757  * @brief Helper to shorten calls to @c DataModel_detail::DVLCast.
3758  * @param p The value to convert.
3759  * @return The value as a @c const @c T*.
3760  *
3761  * This is a no-op for the base class.
3762  */
3763 template <class T>
3764 inline
3765 const T* DATAVECTOR::do_cast (const typename PtrVector::value_type p)
3766 {
3767  return p;
3768 }
3769 
3770 
3771 /**
3772  * @brief Helper to shorten calls to @c DataModel_detail::DVLCast.
3773  * @param p The value to convert.
3774  * @return The value as a @c T*.
3775  *
3776  * This is a no-op for the base class.
3777  */
3778 template <class T>
3779 inline
3780 T* DATAVECTOR::do_cast_nc (typename PtrVector::value_type p)
3781 {
3782  return p;
3783 }
3784 
3785 
3786 /**
3787  * @brief Find the most-derived @c DataVector class in the hierarchy.
3788  * @return The @c type_info for the class for which this method gets run.
3789  *
3790  * This is used to generate a nice error message when the most-derived
3791  * check for insertions fails.
3792  * Every @c DataVector defines this virtual method, so when it's
3793  * called, the one corresponding to the most-derived @c DataVector
3794  * gets run.
3795  */
3796 template <class T>
3797 const std::type_info& DATAVECTOR::dv_typeid() const
3798 {
3799  return typeid(DataVector);
3800 }
3801 
3802 
3803 /**
3804  * @brief Helper for @c erase(). Remove element at a given position.
3805  * @param position Iterator pointing to the element to be removed.
3806  * @return An iterator pointing to the next element (or @c end()).
3807  *
3808  * This function factors out common code between @c erase() in the
3809  * base and derived @c DataVector classes. It deals with the
3810  * @c std::vector iterators directly.
3811  */
3812 template <class T>
3813 typename DATAVECTOR::PtrVector::iterator
3814 DATAVECTOR::erase_base(typename PtrVector::iterator position)
3815 {
3816  if (m_ownPolicy == SG::OWN_ELEMENTS && position != m_pCont.end())
3817  this->doDelete (*position);
3818  return m_pCont.erase(position);
3819 }
3820 
3821 
3822 /**
3823  * @brief Helper for @c erase(). Remove a range of elements.
3824  * @param first Iterator pointing to the first element to be removed.
3825  * @param last Iterator pointing one past the last element to be removed.
3826  * @return An iterator pointing to the element pointed to by @a last
3827  * prior to erasing (or @c end()).
3828  *
3829  * This function factors out common code between @c erase() in the
3830  * base and derived @c DataVector classes. It deals with the
3831  * @c std::vector iterators directly.
3832  */
3833 template <class T>
3834 typename DATAVECTOR::PtrVector::iterator
3835 DATAVECTOR::erase_base(typename PtrVector::iterator first,
3836  typename PtrVector::iterator last)
3837 {
3838  if (first == last) return first;
3839  if (m_ownPolicy == SG::OWN_ELEMENTS) {
3840  typename PtrVector::iterator new_end =
3841  DataVector_detail::remove_duplicates(first, last);
3842  this->doDelete (first, new_end);
3843  }
3844  return m_pCont.erase(first, last);
3845 }
3846 
3847 
3848 /**
3849  * @brief Delete an element
3850  * @param p The element to delete.
3851  */
3852 template <class T>
3853 inline
3854 void DATAVECTOR::doDelete (value_type p)
3855 {
3856  if (m_deleter) {
3857  m_deleter->doDelete (p);
3858  }
3859  else {
3860  delete p;
3861  }
3862 }
3863 
3864 
3865 /**
3866  * @brief Delete a range of elements
3867  * @param first Start of range to delete.
3868  * @param last End of range to delete.
3869  */
3870 template <class T>
3871 inline
3872 void DATAVECTOR::doDelete (typename PtrVector::iterator first,
3873  typename PtrVector::iterator last)
3874 {
3875  if (m_deleter) {
3876  m_deleter->doDelete (first, last);
3877  }
3878  else {
3879  for (; first != last; ++first) {
3880  delete *first;
3881  }
3882  }
3883 }
3884 
3885 
3886 /**
3887  * @brief Test if we can insert; raise an exception if not.
3888  * @param op Description of the attempted operation.
3889  *
3890  * In order to maintain type-safety, we can only allow insertions
3891  * using the most-derived instance of @c DataVector. This checks
3892  * this by testing the @c m_isMostDerived, which is set by the constructors
3893  * to true only for the most-derived instance.
3894  * If the test fails, we call to potentially out-of-line code to continue.
3895  */
3896 template <class T>
3897 inline
3898 void DATAVECTOR::testInsert (const char* op)
3899 {
3900  if (ATHCONTAINERS_LIKELY (m_isMostDerived))
3901  return;
3902  this->testInsertOol (op);
3903 }
3904 
3905 
3906 /**
3907  * @brief Test if we can insert; raise an exception if not.
3908  * @param op Description of the attempted operation.
3909  *
3910  * This continues the test of @c testInsert. There is one case
3911  * where @c m_isMostDerived may not be set correctly. If this container
3912  * was made via copy construction, then all the @c m_isMostDerived flags
3913  * will be false. So we call @c setMostDerived to set the flags correctly
3914  * and test again. If the test fails again, then we raise an exception.
3915  */
3916 template <class T>
3917 void DATAVECTOR::testInsertOol (const char* op)
3918 {
3919  this->setMostDerived();
3920  if (!m_isMostDerived)
3921  throw SG::ExcInsertionInBaseClass (op, typeid(DataVector), dv_typeid());
3922 }
3923 
3924 
3925 /**
3926  * @brief Clear @c m_isMostDerived for this instance and for all bases.
3927  *
3928  * Called from the constructor after setting @c m_isMostDerived.
3929  */
3930 template <class T>
3931 inline
3932 void DATAVECTOR::clearMostDerived()
3933 {
3934  this->m_isMostDerived = false;
3935 }
3936 
3937 
3938 /**
3939  * @brief Set @c m_isMostDerived for this instance and clear it for all bases.
3940  *
3941  * Called from @c testInsert if the test fails. The flag may not have
3942  * been set if this container was made via copy construction, so set
3943  * it appropriately now so we can test again.
3944  */
3945 template <class T>
3946 void DATAVECTOR::setMostDerived()
3947 {
3948  m_isMostDerived = true;
3949 }
3950 
3951 
3952 #undef DATAVECTOR
3953 
3954 
3955 //****************************************************************************
3956 // Free function implementations.
3957 //
3958 
3959 
3960 /**
3961  * @brief Vector equality comparison.
3962  * @param a A @c DataVector.
3963  * @param b A @c DataVector of the same type as @a b.
3964  * @return True iff the size and elements of the vectors are equal.
3965  *
3966  * This is an equivalence relation. It is linear in the size of the
3967  * vectors. Vectors are considered equivalent if their sizes are equal,
3968  * and if corresponding elements compare equal.
3969  */
3970 template <class T>
3971 bool operator== (const DataVector<T>& a, const DataVector<T>& b)
3972 {
3973  return a.stdcont() == b.stdcont();
3974 }
3975 
3976 
3977 /// Based on operator==
3978 template <class T>
3979 bool operator!= (const DataVector<T>& a, const DataVector<T>& b)
3980 {
3981  return a.stdcont() != b.stdcont();
3982 }
3983 
3984 
3985 /**
3986  * @brief Vector ordering relation.
3987  * @param a A @c DataVector.
3988  * @param b A @c DataVector of the same type as @a x.
3989  * @return True iff @a a is lexicographically less than @a b.
3990  *
3991  * This is a total ordering relation. It is linear in the size of the
3992  * vectors. Comparisons are done on the pointer values of the elements.
3993  *
3994  * See @c std::lexicographical_compare() for how the determination is made.
3995  */
3996 template <class T>
3997 bool operator< (const DataVector<T>& a, const DataVector<T>& b)
3998 {
3999  return a.stdcont() < b.stdcont();
4000 }
4001 
4002 
4003 /// Based on operator<
4004 template <class T>
4005 bool operator> (const DataVector<T>& a, const DataVector<T>& b)
4006 {
4007  return a.stdcont() > b.stdcont();
4008 }
4009 
4010 
4011 /// Based on operator<
4012 template <class T>
4013 bool operator<= (const DataVector<T>& a, const DataVector<T>& b)
4014 {
4015  return a.stdcont() <= b.stdcont();
4016 }
4017 
4018 
4019 /// Based on operator<
4020 template <class T>
4021 bool operator>= (const DataVector<T>& a, const DataVector<T>& b)
4022 {
4023  return a.stdcont() >= b.stdcont();
4024 }
4025 
4026 
4027 /// See @c DataVector<T, BASE>::swap().
4028 template <class T>
4029 void swap (DataVector<T>& a, DataVector<T>& b)
4030 {
4031  a.swap (b);
4032 }
4033 
4034 
4035 /**
4036  * @brief Specialization of @c ClassName for @c DataVector.
4037  *
4038  * This overrides the default implementation of @c ClassName
4039  * to hide @c DataVector's second template parameter.
4040  */
4041 template <class T>
4042 std::string ClassName<DataVector<T> >::name()
4043 {
4044  std::string out = "DataVector<";
4045  out += ClassName<T>::name();
4046  if (out[out.size()-1] == '>')
4047  out += ' ';
4048  out += '>';
4049  return out;
4050 }
4051 
4052 
4053 #ifndef XAOD_STANDALONE
4054 
4055 
4056 // Set up initialization of element type BaseInfo
4057 namespace DataVector_detail {
4058 #define DVLTYPE DataVector
4059 #include "AthContainers/tools/DVLEltBaseInfo.icc"
4060 #undef DVLTYPE
4061 } // namespace DataVector_detail
4062 
4063 
4064 #else
4065 
4066 
4067 namespace DataVector_detail {
4068 /// Dummy implementation for the DVLEltBaseInit structure
4069 template< class T >
4070 struct DVLEltBaseInit {};
4071 } // namespace DataVector_detail
4072 
4073 
4074 #endif // not XAOD_STANDALONE
4075 
4076 
4077 
4078 // We need to specialize the function that DVLInfo uses to create the container
4079 // for DataVector.
4080 /**
4081  * @brief Construct a new container.
4082  * @param nreserve Number of elements for which to reserve space.
4083  * (Ignored if not appropriate.)
4084  * @param cont[out] Pointer to the constructed container.
4085  * (Returned via an argument to allow for template
4086  * argument deduction.)
4087  *
4088  * Specialization for DataVector.
4089  */
4090 template <class T>
4091 void dvl_makecontainer (size_t nreserve, DataVector<T>*& cont)
4092 {
4093  cont = new DataVector<T> (SG::VIEW_ELEMENTS);
4094  cont->reserve (nreserve);
4095 }