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