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