1 // Dear emacs, this is -*- c++ -*-
4 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
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
12 * Implementation file.
16 #include "AthContainers/tools/CompareAndPrint.h"
17 #include "AthContainers/tools/ATHCONTAINERS_ASSERT.h"
18 #include "CxxUtils/releasing_iterator.h"
23 //****************************************************************************
27 namespace ROOT { namespace Meta { namespace Selection {
28 namespace DataVector_detail {
29 template <class B1, class B2, class B3> class VirtBases;
34 namespace DataVector_detail {
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.
41 void optimizeMeAway_DV(FI, bool){}
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.
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.
53 template <class ForwIter>
54 ForwIter remove_duplicates(ForwIter b, ForwIter e, bool quiet=false)
56 #ifdef DO_REMOVE_DUPLICATES
58 return std::unique(b, e, DataModel_detail::CompareAndPrint(quiet));
60 optimizeMeAway_DV(b, quiet);
66 * @brief VirtBases for one class.
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.
73 struct VirtBases<B1, DataModel_detail::NoBase, DataModel_detail::NoBase>
74 : virtual public DataVector<B1>
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;
85 // We're using virtual derivation.
86 // cppcheck-suppress duplInheritedMember; deliberate
87 static constexpr bool has_virtual = true;
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;
100 // Pass this down to base classes.
101 void clearMostDerived()
103 DataVector<B1>::clearMostDerived();
106 // We need these here to prevent ambiguities,
107 // but they shouldn't actually be called.
108 virtual const std::type_info& dv_typeid() const override
110 return typeid(VirtBases);
112 virtual const DataModel_detail::DVLInfoBase& dvlinfo_v() const override
114 return DataVector<B1>::dvlinfo();
116 virtual void setMostDerived() override
123 int baseOffset1 (const char* p, const VirtBases& dv,
124 const std::type_info& ti)
126 return DataVector<B1>::baseOffset1 (p, dv, ti);
132 ROOT::Meta::Selection::
133 DataVector_detail::VirtBases<B1,
134 DataModel_detail::NoBase,
135 DataModel_detail::NoBase>::self self;
140 * @brief VirtBases for two classes.
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.
146 template <class B1, class B2>
147 struct VirtBases<B1, B2, DataModel_detail::NoBase>
148 : virtual public DataVector<B1>,
149 virtual public DataVector<B2>
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>);
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;
164 // We're using virtual derivation.
165 // cppcheck-suppress duplInheritedMember; deliberate
166 static constexpr bool has_virtual = true;
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;
180 // Pass this down to base classes.
181 void clearMostDerived()
183 DataVector<B1>::clearMostDerived();
184 DataVector<B2>::clearMostDerived();
187 // We need these here to prevent ambiguities,
188 // but they shouldn't actually be called.
189 virtual const std::type_info& dv_typeid() const override
191 return typeid(VirtBases);
193 virtual const DataModel_detail::DVLInfoBase& dvlinfo_v() const override
195 return DataVector<B1>::dvlinfo();
197 virtual void setMostDerived() override
204 int baseOffset1 (const char* p, const VirtBases& dv,
205 const std::type_info& ti)
207 int ret = DataVector<B1>::baseOffset1 (p, dv, ti);
210 return DataVector<B2>::baseOffset1 (p, dv, ti);
216 ROOT::Meta::Selection::
217 DataVector_detail::VirtBases<B1, B2,
218 DataModel_detail::NoBase>::self self;
223 * @brief VirtBases for three classes.
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.
229 template <class B1, class B2, class B3>
231 : virtual public DataVector<B1>,
232 virtual public DataVector<B2>,
233 virtual public DataVector<B3>
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>);
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;
252 // We're using virtual derivation.
253 // cppcheck-suppress duplInheritedMember; deliberate
254 static constexpr bool has_virtual = true;
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;
268 // Pass this down to base classes.
269 void clearMostDerived()
271 DataVector<B1>::clearMostDerived();
272 DataVector<B2>::clearMostDerived();
273 DataVector<B3>::clearMostDerived();
276 // We need these here to prevent ambiguities,
277 // but they shouldn't actually be called.
278 virtual const std::type_info& dv_typeid() const override
280 return typeid(VirtBases);
282 virtual const DataModel_detail::DVLInfoBase& dvlinfo_v() const override
284 return DataVector<B1>::dvlinfo();
286 virtual void setMostDerived() override
293 int baseOffset1 (const char* p, const VirtBases& dv,
294 const std::type_info& ti)
296 int ret = DataVector<B1>::baseOffset1 (p, dv, ti);
299 ret = DataVector<B2>::baseOffset1 (p, dv, ti);
302 return DataVector<B3>::baseOffset1 (p, dv, ti);
308 ROOT::Meta::Selection::DataVector_detail::VirtBases<B1, B2, B3>::self
313 } // namespace DataVector_detail
316 namespace ROOT { namespace Meta { namespace Selection {
317 namespace DataVector_detail {
319 template< class B1, class B2, class B3 >
320 class VirtBases : KeepFirstTemplateArguments< 1 >, SelectNoInstance
325 typedef DataVector_detail::VirtBases< B1, B2, B3 > self;
330 }}} // ROOT namespace
333 //****************************************************************************
334 // Generic (derived) DataVector implementation.
338 //=== Constructors, destructors, assignment.
342 * @brief Default constructor.
343 * @param ownPolicy The ownership mode for the container.
344 * @param trackIndices The index tracking policy.
346 * By default, a @c DataVector will own its elements.
347 * To avoid this, pass @c SG::VIEW_ELEMENTS for @a ownPolicy.
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
359 template <class T, class BASE>
361 DataVector<T, BASE>::DataVector
362 (SG::OwnershipPolicy ownPolicy /*= SG::OWN_ELEMENTS*/,
363 SG::IndexTrackingPolicy trackIndices /*= SG::DEFAULT_TRACK_INDICES*/)
365 this->m_ownPolicy = ownPolicy;
366 this->template initAuxVectorBase<DataVector> (ownPolicy, trackIndices);
367 this->m_isMostDerived = true;
368 BASE::clearMostDerived();
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.
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.
381 * By default, a @c DataVector will own its elements.
382 * To avoid this, pass @c SG::VIEW_ELEMENTS for @a ownPolicy.
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
394 template <class T, class BASE>
396 DataVector<T, BASE>::DataVector
398 SG::OwnershipPolicy ownPolicy /*= SG::OWN_ELEMENTS*/,
399 SG::IndexTrackingPolicy trackIndices /*=SG::DEFAULT_TRACK_INDICES*/)
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);
410 * @brief Move constructor.
411 * @param rhs The container from which to move.
413 * Any auxiliary data will be moved along with the container contents.
415 template <class T, class BASE>
416 DataVector<T, BASE>::DataVector (DataVector&& rhs) noexcept
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;
424 // Need to reset the container pointer on elements.
425 this->setIndices (this->begin(), this->end());
426 this->m_isMostDerived = true;
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.
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.
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
452 template <class T, class BASE>
453 template <class InputIterator>
455 DataVector<T, BASE>::DataVector
456 (InputIterator first,
458 SG::OwnershipPolicy ownPolicy /*= SG::VIEW_ELEMENTS*/,
459 SG::IndexTrackingPolicy trackIndices /*= SG::DEFAULT_INDEX_TRACKING*/,
460 SG::IAuxStore* store /*= 0*/)
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);
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> >);
473 this->m_ownPolicy = ownPolicy;
474 this->template initAuxVectorBase<DataVector> (ownPolicy, trackIndices);
475 this->m_isMostDerived = true;
476 BASE::clearMostDerived();
478 this->setStore (store);
479 insert (this->begin(), first, last);
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.
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.
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
504 template <class T, class BASE>
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)
517 * @brief Assignment operator.
518 * @param rhs The DataVector from which to assign.
519 * @return This object.
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
525 * Note: this method may only be called using the most derived
526 * @c DataVector in the hierarchy.
528 template <class T, class BASE>
530 DataVector<T, BASE>& DataVector<T, BASE>::operator= (const DataVector& rhs)
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;
547 * @brief Move assignment.
548 * @param rhs The container from which to move.
550 * Any auxiliary data will be moved along with the container contents.
552 * (Can't be noexcept because testInsert() can throw.)
554 template <class T, class BASE>
556 DataVector<T, BASE>::operator= (DataVector<T, BASE>&& rhs)
559 // Ensure we're not being called via a base class.
560 testInsert ("assignment operator");
562 this->clear(); // Release any currently-owned elements.
564 SG::AuxVectorBase::operator= (std::move (rhs));
565 this->m_ownPolicy = rhs.m_ownPolicy;
566 this->m_pCont = std::move (rhs.m_pCont);
568 delete this->m_deleter;
569 this->m_deleter = std::move(rhs.m_deleter);
570 rhs.m_deleter = nullptr;
572 // Need to reset the container pointer on elements.
573 this->setIndices (this->begin(), this->end());
580 * @brief Assignment operator, from an initializer list.
581 * @param l An initializer list.
582 * @return This object.
584 * This is equivalent to @c assign.
585 * Any existing owned elements will be released.
586 * The @c DataVector's ownership policy determines whether it will take
587 * ownership of the new elements.
589 template <class T, class BASE>
592 DataVector<T, BASE>::operator= (std::initializer_list<value_type> l)
594 this->assign (l.begin(), l.end());
600 * @brief Assign from iterators.
601 * @param first The start of the range to put in the container.
602 * @param last The end of the range to put in the container.
604 * Any existing owned elements will be released.
605 * The @c DataVector's ownership policy determines whether it will take
606 * ownership of the new elements.
608 template <class T, class BASE>
609 template <class InputIterator>
610 void DataVector<T, BASE>::assign(InputIterator first, InputIterator last)
612 // Ensure we're not being called via a base class.
613 testInsert ("assign");
614 this->clear(); // Release any currently-owned elements.
615 insert(begin(), first, last);
620 * @brief Assign from an initializer list.
621 * @param l An initializer list.
623 * Any existing owned elements will be released.
624 * The @c DataVector's ownership policy determines whether it will take
625 * ownership of the new elements.
627 template <class T, class BASE>
628 void DataVector<T, BASE>::assign(std::initializer_list<value_type> l)
630 this->assign (l.begin(), l.end());
634 //=== Size and capacity.
638 * @fn size_type size() const
639 * @brief Returns the number of elements in the collection.
641 template <class T, class BASE>
643 typename DataVector<T, BASE>::size_type
644 DataVector<T, BASE>::size() const noexcept
646 return this->m_pCont.size();
651 * @brief Resizes the collection to the specified number of elements.
652 * @param sz The new size of the collection.
654 * Note that this function differs from the standard in that it does
655 * not allow specifying the value of any inserted elements.
656 * They will always be 0.
658 * If the container is shrunk, elements will be deleted as with @c erase().
660 template <class T, class BASE>
661 void DataVector<T, BASE>::resize(size_type sz)
663 if (sz < this->size()) {
664 this->erase (this->begin()+sz, this->end());
666 this->m_pCont.insert(this->m_pCont.end(), sz - this->m_pCont.size(), 0);
667 SG::AuxVectorBase::resize<DataVector> (sz);
673 * @brief Attempt to preallocate enough memory for a specified number
675 * @param n Number of elements required.
677 template <class T, class BASE>
679 void DataVector<T, BASE>::reserve (size_type n)
681 this->m_pCont.reserve (n);
682 SG::AuxVectorBase::reserve<DataVector> (n);
686 //=== Element access.
690 * @brief Access an element, as an rvalue.
691 * @param n Array index to access.
692 * @return The element at @a n.
694 * No bounds checking is done.
695 * Note that we return a @c const @c T* rather than a reference.
697 template <class T, class BASE>
699 const T* DataVector<T, BASE>::operator[] (size_type n) const
701 return do_cast(this->m_pCont[n]);
706 * @brief Access an element, as an rvalue.
707 * @param n Array index to access.
708 * @return The element at @a n.
710 * This is a synonym for operator[] const, to be used when calling from root
711 * (where we can't readily call just the const version of a method).
713 template <class T, class BASE>
715 const T* DataVector<T, BASE>::get (size_type n) const
717 return do_cast(this->m_pCont[n]);
722 * @brief Access an element, as an lvalue.
723 * @param n Array index to access.
724 * @return Proxy to the element at @a n.
726 * No bounds checking is done.
727 * Note that we return a proxy object rather than a reference;
728 * the proxy will handle deleting an owned element if it's assigned to.
730 template <class T, class BASE>
732 typename DataVector<T, BASE>::ElementProxy
733 DataVector<T, BASE>::operator[] (size_type n)
735 return ElementProxy (this->m_pCont.begin() + n, this);
740 * @brief Access an element, as an rvalue.
741 * @param n Array index to access.
742 * @return The element at @a n.
744 * Will raise @c std::out_of_range if the index is out-of-bounds.
745 * Note that we return a @c const @c T* rather than a reference.
747 template <class T, class BASE>
749 const T* DataVector<T, BASE>::at (size_type n) const
751 return do_cast(this->m_pCont.at(n));
756 * @brief Access an element, as an lvalue.
757 * @param n Array index to access.
758 * @return Proxy to the element at @a n.
760 * Will raise @c std::out_of_range if the index is out-of-bounds.
761 * Note that we return a proxy object rather than a reference;
762 * the proxy will handle deleting an owned element if it's assigned to.
764 template <class T, class BASE>
766 typename DataVector<T, BASE>::ElementProxy
767 DataVector<T, BASE>::at (size_type n)
769 // Can't use m_pCont's at here, because we need an iterator.
770 // So we have to do the bounds check ourselves.
771 if (n >= this->size())
772 throw std::out_of_range ("DataVector::at range check");
773 return ElementProxy (this->m_pCont.begin() + n, this);
778 * @brief Access the first element in the collection as an rvalue.
779 * @return The first element in the collection.
781 * No checking is done to ensure that the container is not empty.
782 * Note that we return a @c const @c T* rather than a reference.
784 template <class T, class BASE>
786 const T* DataVector<T, BASE>::front() const
788 return do_cast (this->m_pCont.front());
793 * @brief Access the last element in the collection as an rvalue.
794 * @return The last element in the collection.
796 * No checking is done to ensure that the container is not empty.
797 * Note that we return a @c const @c T* rather than a reference.
799 template <class T, class BASE>
801 const T* DataVector<T, BASE>::back() const
803 return do_cast (this->m_pCont.back());
808 * @brief Access the first element in the collection as an lvalue.
809 * @return Proxy to the first element in the collection.
811 * No checking is done to ensure that the container is not empty.
812 * Note that we return a proxy object rather than a reference;
813 * the proxy will handle deleting an owned element if it's assigned to.
815 template <class T, class BASE>
817 typename DataVector<T, BASE>::ElementProxy
818 DataVector<T, BASE>::front ()
820 return ElementProxy (this->m_pCont.begin(), this);
825 * @brief Access the last element in the collection as an lvalue.
826 * @return Proxy to the last element in the collection.
828 * No checking is done to ensure that the container is not empty.
829 * Note that we return a proxy object rather than a reference;
830 * the proxy will handle deleting an owned element if it's assigned to.
832 template <class T, class BASE>
834 typename DataVector<T, BASE>::ElementProxy
835 DataVector<T, BASE>::back ()
837 return ElementProxy (this->m_pCont.end()-1, this);
841 //=== Iterator creation.
845 * @brief Return a @c const_iterator pointing at the beginning
847 * @return A @c const_iterator.
849 * Note that dereferencing the iterator will yield a @c const @c T* rather
852 template <class T, class BASE>
854 typename DataVector<T, BASE>::const_iterator
855 DataVector<T, BASE>::begin() const noexcept
857 return const_iterator (this->m_pCont.begin());
862 * @brief Return a @c const_iterator pointing past the end
864 * @return A @c const_iterator.
866 * Note that dereferencing the iterator will yield a @c const @c T* rather
869 template <class T, class BASE>
871 typename DataVector<T, BASE>::const_iterator
872 DataVector<T, BASE>::end() const noexcept
874 return const_iterator (this->m_pCont.end());
879 * @brief Return an @c iterator pointing at the beginning
881 * @return An @c iterator.
883 * Note that dereferencing the iterator will yield a proxy rather
884 * than a reference; the proxy will handle deleting an owned element
885 * if it's assigned to.
887 template <class T, class BASE>
889 typename DataVector<T, BASE>::iterator
890 DataVector<T, BASE>::begin() noexcept
892 return iterator (this->m_pCont.begin(), this);
897 * @brief Return an @c iterator pointing past the end
899 * @return An @c iterator.
901 * Note that dereferencing the iterator will yield a proxy rather
902 * than a reference; the proxy will handle deleting an owned element
903 * if it's assigned to.
905 template <class T, class BASE>
907 typename DataVector<T, BASE>::iterator
908 DataVector<T, BASE>::end() noexcept
910 return iterator (this->m_pCont.end(), this);
915 * @brief Return a @c const_reverse_iterator pointing past the end
917 * @return A @c const_reverse_iterator.
919 * Note that dereferencing the iterator will yield a @c const @c T* rather
922 template <class T, class BASE>
924 typename DataVector<T, BASE>::const_reverse_iterator
925 DataVector<T, BASE>::rbegin() const noexcept
927 return const_reverse_iterator (end());
932 * @brief Return a @c const_reverse_iterator pointing at the beginning
934 * @return A @c const_reverse_iterator.
936 * Note that dereferencing the iterator will yield a @c const @c T* rather
939 template <class T, class BASE>
941 typename DataVector<T, BASE>::const_reverse_iterator
942 DataVector<T, BASE>::rend() const noexcept
944 return const_reverse_iterator (begin());
949 * @brief Return a @c reverse_iterator pointing past the end
951 * @return A @c reverse_iterator.
953 * Note that dereferencing the iterator will yield a proxy rather
954 * than a reference; the proxy will handle deleting an owned element
955 * if it's assigned to.
957 template <class T, class BASE>
959 typename DataVector<T, BASE>::reverse_iterator
960 DataVector<T, BASE>::rbegin() noexcept
962 return reverse_iterator (iterator (this->m_pCont.end(), this));
967 * @brief Return a @c reverse_iterator pointing at the beginning
969 * @return A @c reverse_iterator.
971 * Note that dereferencing the iterator will yield a proxy rather
972 * than a reference; the proxy will handle deleting an owned element
973 * if it's assigned to.
975 template <class T, class BASE>
977 typename DataVector<T, BASE>::reverse_iterator
978 DataVector<T, BASE>::rend() noexcept
980 return reverse_iterator (iterator (this->m_pCont.begin(), this));
985 * @brief Return a @c const_iterator pointing at the beginning
987 * @return A @c const_iterator.
989 * Note that dereferencing the iterator will yield a @c const @c T* rather
992 template <class T, class BASE>
994 typename DataVector<T, BASE>::const_iterator
995 DataVector<T, BASE>::cbegin() const noexcept
997 return const_iterator (this->m_pCont.begin());
1002 * @brief Return a @c const_iterator pointing past the end
1003 * of the collection.
1004 * @return A @c const_iterator.
1006 * Note that dereferencing the iterator will yield a @c const @c T* rather
1009 template <class T, class BASE>
1011 typename DataVector<T, BASE>::const_iterator
1012 DataVector<T, BASE>::cend() const noexcept
1014 return const_iterator (this->m_pCont.end());
1019 * @brief Return a @c const_reverse_iterator pointing past the end
1020 * of the collection.
1021 * @return A @c const_reverse_iterator.
1023 * Note that dereferencing the iterator will yield a @c const @c T* rather
1026 template <class T, class BASE>
1028 typename DataVector<T, BASE>::const_reverse_iterator
1029 DataVector<T, BASE>::crbegin() const noexcept
1031 return const_reverse_iterator (cend());
1036 * @brief Return a @c const_reverse_iterator pointing at the beginning
1037 * of the collection.
1038 * @return A @c const_reverse_iterator.
1040 * Note that dereferencing the iterator will yield a @c const @c T* rather
1043 template <class T, class BASE>
1045 typename DataVector<T, BASE>::const_reverse_iterator
1046 DataVector<T, BASE>::crend() const noexcept
1048 return const_reverse_iterator (cbegin());
1052 //=== Insertion operations.
1056 * @brief Add an element to the end of the collection.
1057 * @param pElem The element to add to the collection.
1059 * The container's ownership policy will determine if it takes ownership
1060 * of the new element.
1062 * Note: this method may only be called using the most derived
1063 * @c DataVector in the hierarchy.
1065 * Returns the pushed pointer.
1067 template <class T, class BASE>
1069 typename DataVector<T, BASE>::value_type
1070 DataVector<T, BASE>::push_back(value_type pElem)
1072 // Ensure we're not being called via a base class.
1073 testInsert ("push_back");
1074 this->m_pCont.push_back(static_cast<typename PtrVector::value_type>(pElem));
1075 SG::AuxVectorBase::resize<DataVector> (this->size());
1077 this->moveAux (this->size()-1, pElem, false, true);
1083 * @brief Add an element to the end of the collection.
1084 * @param pElem The element to add to the collection.
1086 * The container must be an owning container.
1088 * Note: this method may only be called using the most derived
1089 * @c DataVector in the hierarchy.
1091 * Returns the pushed pointer.
1093 template <class T, class BASE>
1095 typename DataVector<T, BASE>::value_type
1096 DataVector<T, BASE>::push_back(std::unique_ptr<base_value_type> pElem)
1098 // Container must own its elements.
1099 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
1100 SG::throwExcNonowningContainer();
1102 // Ensure we're not being called via a base class.
1103 testInsert ("push_back");
1104 value_type ptr = pElem.release();
1105 this->m_pCont.push_back(ptr);
1106 SG::AuxVectorBase::resize<DataVector> (this->size());
1108 this->moveAux (this->size()-1, ptr, false, true);
1114 * @brief Add an element to the end of the collection.
1115 * @param pElem The element to add to the collection.
1117 * The container's ownership policy will determine if it takes ownership
1118 * of the new element.
1120 * Note: this method may only be called using the most derived
1121 * @c DataVector in the hierarchy.
1123 * For @c DataVector, this is like the same as @c push_back, and
1124 * it returns the pushed element.
1125 * It's included just for interface compatibility with `std::vector`.
1127 template <class T, class BASE>
1129 typename DataVector<T, BASE>::value_type
1130 DataVector<T, BASE>::emplace_back(value_type pElem)
1132 return this->push_back (pElem);
1137 * @brief Add a new element to the collection.
1138 * @param position Iterator before which the element will be added.
1139 * @param pElem The element to add to the collection.
1140 * @return An iterator that points to the inserted data.
1142 * The container's ownership policy will determine if it takes ownership
1143 * of the new element.
1145 * Note: this method may only be called using the most derived
1146 * @c DataVector in the hierarchy.
1148 template <class T, class BASE>
1149 typename DataVector<T, BASE>::iterator
1150 DataVector<T, BASE>::insert(iterator position, value_type pElem)
1152 // Ensure we're not being called via a base class.
1153 testInsert ("insert");
1154 iterator ret (this->m_pCont.insert(position.base(), pElem), this);
1155 this->shift (ret - this->begin(), 1);
1156 this->moveAux (ret-this->begin(), pElem, false, true);
1162 * @brief Add a new element to the collection.
1163 * @param position Iterator before which the element will be added.
1164 * @param pElem The element to add to the collection.
1165 * @return An iterator that points to the inserted data.
1167 * The container must be an owning container.
1169 * Note: this method may only be called using the most derived
1170 * @c DataVector in the hierarchy.
1172 template <class T, class BASE>
1173 typename DataVector<T, BASE>::iterator
1174 DataVector<T, BASE>::insert(iterator position,
1175 std::unique_ptr<base_value_type> pElem)
1177 // Container must own its elements.
1178 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
1179 SG::throwExcNonowningContainer();
1181 // Ensure we're not being called via a base class.
1182 testInsert ("insert");
1183 value_type ptr = pElem.release();
1184 iterator ret (this->m_pCont.insert(position.base(), ptr), this);
1185 this->shift (ret - this->begin(), 1);
1186 this->moveAux (ret-this->begin(), ptr, false, true);
1192 * @brief Add a new element to the collection.
1193 * @param position Iterator before which the element will be added.
1194 * @param pElem The element to add to the collection.
1195 * @return An iterator that points to the inserted data.
1197 * The container's ownership policy will determine if it takes ownership
1198 * of the new element.
1200 * Note: this method may only be called using the most derived
1201 * @c DataVector in the hierarchy.
1203 * For @c DataVector, this is just the same as @c insert.
1204 * It's included just for interface compatibility with `std::vector`.
1206 template <class T, class BASE>
1207 typename DataVector<T, BASE>::iterator
1208 DataVector<T, BASE>::emplace(iterator position, value_type pElem)
1210 return this->insert (position, pElem);
1215 * @brief Add a group of new elements to the collection.
1216 * @param position Iterator before which the element will be added.
1217 * @param first The start of the range to put in the container.
1218 * @param last The end of the range to put in the container.
1220 * The container's ownership policy will determine if it takes ownership
1221 * of the new element.
1223 * Note: this method may only be called using the most derived
1224 * @c DataVector in the hierarchy.
1226 * This overload is for the case where the iterator value type
1227 * is convertible to T*.
1229 template <class T, class BASE>
1230 template <class InputIterator,
1231 DataVector_detail::enable_if_ptr_itr<InputIterator, T> >
1232 void DataVector<T, BASE>::insert(iterator position,
1233 InputIterator first,
1236 // Make sure that the input iterator can actually be converted
1237 // to a T*. Lets us give a compilation error for this:
1238 // DATAVECTOR_BASE(D, B);
1241 // d.insert (d.begin(), bb, bb+1);
1242 // which would otherwise compile.
1243 using ittype = typename std::iterator_traits<InputIterator>::value_type;
1244 static_assert (std::is_convertible_v<ittype, const T*>);
1246 // Ensure we're not being called via a base class.
1247 testInsert ("insert");
1248 size_t idx = position - this->begin();
1249 size_t old_sz = this->m_pCont.size();
1250 this->m_pCont.insert(position.base(), first, last);
1251 size_t n = this->m_pCont.size() - old_sz;
1252 this->shift (idx, n);
1253 this->moveAux (idx, first, last, false, true);
1258 * @brief Add a group of new elements to the collection.
1259 * @param position Iterator before which the element will be added.
1260 * @param first The start of the range to put in the container.
1261 * @param last The end of the range to put in the container.
1263 * The container's ownership policy will determine if it takes ownership
1264 * of the new element.
1266 * Note: this method may only be called using the most derived
1267 * @c DataVector in the hierarchy.
1269 * This overload is for the case where the iterator value type
1270 * is convertible to unique_ptr<T>.
1272 template <class T, class BASE>
1273 template <class InputIterator,
1274 DataVector_detail::enable_if_up_itr<InputIterator, T> >
1275 void DataVector<T, BASE>::insert(iterator position,
1276 InputIterator first,
1279 // Make sure that the input iterator can actually be converted
1280 // to a T*. Lets us give a compilation error for this:
1281 // DATAVECTOR_BASE(D, B);
1284 // d.insert (d.begin(), bb, bb+1);
1285 // which would otherwise compile.
1286 using ittype = typename std::iterator_traits<InputIterator>::value_type;
1287 static_assert (std::is_convertible_v<typename ittype::pointer, const T*>);
1289 // Ensure we're not being called via a base class.
1290 testInsert ("insert");
1291 size_t idx = position - this->begin();
1292 size_t old_sz = this->m_pCont.size();
1293 using CxxUtils::releasing_iterator;
1294 this->m_pCont.insert(position.base(), releasing_iterator(first), releasing_iterator(last));
1295 size_t n = this->m_pCont.size() - old_sz;
1296 this->shift (idx, n);
1297 this->moveAux (idx, this->begin()+idx, this->begin()+idx+n);
1302 * @brief Add a group of new elements to the collection.
1303 * @param position Iterator before which the element will be added.
1304 * @param l An initializer list.
1306 * The container's ownership policy will determine if it takes ownership
1307 * of the new element.
1309 * Note: this method may only be called using the most derived
1310 * @c DataVector in the hierarchy.
1312 template <class T, class BASE>
1313 void DataVector<T, BASE>::insert(iterator position,
1314 std::initializer_list<value_type> l)
1316 insert (position, l.begin(), l.end());
1321 * @brief Insert the contents of another @c DataVector,
1322 * with auxiliary data copied via move semantics.
1323 * @param position Iterator before which the new elements will be added.
1324 * @param other The vector to add.
1326 * The ownership mode of this vector must be the same as @c other;
1327 * otherwise, an exception will be thrown.
1329 * If both vectors are view vectors, then this is the same
1330 * as <code> insert (position, other.begin(), other.end()) </code>.
1332 * Otherwise, the elements from @c other will be inserted into this vector.
1333 * This vector will take ownership of the elements, and the ownership
1334 * mode of @c other will be changed to @c VIEW_ELEMENTS.
1335 * Auxiliary data for these elements will be transferred,
1336 * using move semantics if possible. (Thus, the auxiliary store
1337 * for @c other may be modified and must not be locked.)
1338 * Finally, the auxiliary store pointer for @c other will be cleared
1339 * (but the store itself will not be deleted since it's not owned
1342 * Note: this method may only be called using the most derived
1343 * @c DataVector in the hierarchy.
1345 template <class T, class BASE>
1347 DataVector<T, BASE>::insertMove (iterator position, DataVector& other)
1349 if (this->m_ownPolicy != other.ownPolicy())
1350 throw SG::ExcInsertMoveOwnershipMismatch();
1352 if (this->m_ownPolicy == SG::VIEW_ELEMENTS) {
1353 this->insert (position, other.begin(), other.end());
1357 testInsert ("insertMove");
1358 size_t pos = position.base() - this->m_pCont.begin();
1359 this->m_pCont.insert (position.base(), other.begin(), other.end());
1360 this->setIndices (this->begin()+pos, this->end(), pos);
1361 other.m_ownPolicy = SG::VIEW_ELEMENTS;
1363 SG::IAuxStore* otherStore = other.getStore();
1365 SG::IAuxStore* store = this->getStore();
1367 if (!store->insertMove (pos, *otherStore))
1370 else if (this->hasStore())
1371 throw SG::ExcConstAuxData ("insertMove");
1372 other.setStore (static_cast<SG::IAuxStore*>(nullptr));
1374 else if (other.hasStore())
1375 throw SG::ExcConstAuxData ("insertMove");
1379 //=== Erasure operations.
1383 * @brief Remove element at a given position.
1384 * @param position Iterator pointing to the element to be removed.
1385 * @return An iterator pointing to the next element (or @c end()).
1387 * If the container owns its elements, then the pointed-to element
1390 template <class T, class BASE>
1391 typename DataVector<T, BASE>::iterator
1392 DataVector<T, BASE>::erase(iterator position)
1394 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
1395 this->clearIndex (position);
1396 iterator ret (this->erase_base (position.base()), this);
1397 this->shift (ret - this->begin() + 1, -1);
1403 * @brief Remove a range of elements.
1404 * @param first Iterator pointing to the first element to be removed.
1405 * @param last Iterator pointing one past the last element to be removed.
1406 * @return An iterator pointing to the element pointed to by @a last
1407 * prior to erasing (or @c end()).
1409 * If the container owns its elements, then the removed elements
1410 * will be deleted. Any duplicates will be removed in this process,
1411 * but don't rely on this.
1413 template <class T, class BASE>
1414 typename DataVector<T, BASE>::iterator
1415 DataVector<T, BASE>::erase(iterator first, iterator last)
1417 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
1418 this->clearIndices (first, last);
1419 iterator ret (this->erase_base (first.base(), last.base()), this);
1420 this->shift (ret - this->begin() + (last-first), -(last-first));
1426 * @brief Remove the last element from the collection.
1428 * If the container owns its elements, then the removed element
1431 template <class T, class BASE>
1432 void DataVector<T, BASE>::pop_back()
1434 if (!this->m_pCont.empty()) {
1435 if (this->m_ownPolicy == SG::OWN_ELEMENTS)
1436 this->doDelete (this->m_pCont.back());
1438 this->clearIndex (iterator (this->m_pCont.end() - 1, this));
1439 this->m_pCont.pop_back();
1440 SG::AuxVectorBase::resize<DataVector> (this->m_pCont.size());
1446 * @brief Erase all the elements in the collection.
1448 * If the container owns its elements, then the removed elements
1449 * will be deleted. Any duplicates will be removed in this process,
1450 * but don't rely on this.
1452 template <class T, class BASE>
1454 void DataVector<T, BASE>::clear()
1456 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
1457 this->clearIndices (begin(), end());
1458 this->erase_base (this->m_pCont.begin(), this->m_pCont.end());
1459 SG::AuxVectorBase::resize<DataVector> (0);
1463 //=== Swap and sort.
1467 * @brief Swap this collection with another.
1468 * @param rhs The collection with which to swap.
1470 * Ownership is swapped along with the collection content.
1472 * Note: this method may only be called using the most-derived
1473 * @c DataVector in the hierarchy. The @a rhs must also be
1474 * referenced using the most-derived @c DataVector.
1476 * Warning: If this container has auxiliary data, then this
1477 * is an O(N) operation, not O(1).
1479 template <class T, class BASE>
1480 void DataVector<T, BASE>::swap(DataVector& rhs)
1482 testInsert ("swap");
1483 rhs.testInsert ("swap");
1484 std::swap(this->m_ownPolicy, rhs.m_ownPolicy);
1485 SG::AuxVectorBase::swap (rhs);
1486 this->m_pCont.swap(rhs.m_pCont);
1487 std::swap (this->m_deleter, rhs.m_deleter);
1488 this->setIndices (this->begin(), this->end());
1489 rhs.setIndices (rhs.begin(), rhs.end());
1494 * @brief Swap the referents of two @c DataVector iterators.
1495 * @param a The first iterator for the swap.
1496 * @param b The second iterator for the swap.
1498 template <class T, class BASE>
1499 void DataVector<T, BASE>::iter_swap (iterator a, iterator b)
1501 if (a.ownPolicy() != b.ownPolicy()) {
1502 throw SG::ExcBadIterSwap();
1504 a.testInsert ("iter_swap");
1505 b.testInsert ("iter_swap");
1506 std::iter_swap (a.base(), b.base());
1507 DataVector* acont = a.container();
1508 DataVector* bcont = b.container();
1509 if (typename SG::AuxStore_traits<DataVector>::flag())
1510 acont->swapElementsAux (a.base() - acont->stdcont().begin(),
1511 b.base() - bcont->stdcont().begin(),
1512 DataModel_detail::DVLCast<DataVector>::cast(*a.base()),
1513 DataModel_detail::DVLCast<DataVector>::cast(*b.base()),
1519 * @brief Sort the container.
1521 * This just sorts by pointer value, so it's probably not very useful.
1523 template <class T, class BASE>
1524 void DataVector<T, BASE>::sort()
1526 typedef std::less<typename PtrVector::value_type> less;
1527 std::sort (this->m_pCont.begin(), this->m_pCont.end(),
1528 DataModel_detail::Compwrapper<DataVector, less> (less()));
1529 this->resortAux (this->begin(), this->end());
1534 * @brief Sort the container with a user-specified comparison operator.
1535 * @param comp Functional to compare two values.
1537 template <class T, class BASE>
1538 template <class COMPARE>
1539 void DataVector<T, BASE>::sort(COMPARE comp)
1541 std::sort (this->m_pCont.begin(), this->m_pCont.end(),
1542 DataModel_detail::Compwrapper<DataVector, COMPARE> (comp));
1543 this->resortAux (this->begin(), this->end());
1547 //=== Non-standard operations.
1551 * @brief Swap one element out of the container.
1552 * @param index Index of the element in the container to swap.
1553 * @param newElement New element to put in the container.
1555 * @param oldElem Reference to receive the element removed from the
1558 * Reference @a oldElem is initialized with element @a index of the
1559 * collection (no bounds checking). Then element @a index is set
1560 * to @newElem. If the collection owns its elements, then it will
1561 * take ownership of @a newElem and release (without deleting)
1562 * the element returned through @a oldElem.
1564 * Note: this method may only be called using the most derived
1565 * @c DataVector in the hierarchy.
1567 template <class T, class BASE>
1568 void DataVector<T, BASE>::swapElement(size_type index,
1572 testInsert ("swapElement");
1574 DataModel_detail::DVLCast<DataVector>::cast(this->m_pCont[index]);
1575 this->clearIndex (iterator (this->m_pCont.begin() + index, this));
1576 this->m_pCont[index] = newElem;
1577 this->moveAux (index, newElem);
1582 * @brief Swap one element out of the container.
1583 * @param pos The element in the container to swap.
1584 * @param newElem New element to put in the container.
1586 * @param oldElem Reference to receive the element removed from the
1589 * Reference @a oldElem is initialized with element @a pos of the
1590 * collection (no bounds checking). Then element @a index is set
1591 * to @c newElem. If the collection owns its elements, then it will
1592 * take ownership of @a newElem and release (without deleting)
1593 * the element returned through @a oldElem.
1595 * Note: this method may only be called using the most derived
1596 * @c DataVector in the hierarchy.
1598 template <class T, class BASE>
1599 void DataVector<T, BASE>::swapElement(iterator pos,
1603 testInsert ("swapElement");
1605 DataModel_detail::DVLCast<DataVector>::cast(*pos.base());
1606 this->clearIndex (pos);
1607 *pos.base() = newElem;
1608 this->moveAux (pos.base() - this->m_pCont.begin(), newElem);
1613 * @brief Swap one element out of the container.
1614 * @param index Index of the element in the container to swap.
1615 * @param newElement New element to put in the container.
1617 * @param oldElem Reference to receive the element removed from the
1620 * Reference @a oldElem is initialized with element @a index of the
1621 * collection (no bounds checking). Then element @a index is set
1624 * The collection must own its elements to use its interface.
1625 * The collection will take ownership of @c newElem and will return
1626 * ownership of @c oldElem.
1628 * Note: this method may only be called using the most derived
1629 * @c DataVector in the hierarchy.
1631 template <class T, class BASE>
1632 void DataVector<T, BASE>::swapElement(size_type index,
1633 std::unique_ptr<base_value_type> newElem,
1634 std::unique_ptr<base_value_type>& oldElem)
1636 // Container must own its elements.
1637 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
1638 SG::throwExcNonowningContainer();
1640 testInsert ("swapElement");
1641 oldElem = std::unique_ptr<base_value_type>
1642 (DataModel_detail::DVLCast<DataVector>::cast(this->m_pCont[index]));
1643 this->clearIndex (iterator (this->m_pCont.begin() + index, this));
1644 value_type ptr = newElem.release();
1645 this->m_pCont[index] = ptr;
1646 this->moveAux (index, ptr);
1651 * @brief Swap one element out of the container.
1652 * @param pos The element in the container to swap.
1653 * @param newElem New element to put in the container.
1655 * @param oldElem Reference to receive the element removed from the
1658 * Reference @a oldElem is initialized with element @a pos of the
1659 * collection (no bounds checking). Then element @a index is set
1662 * The collection must own its elements to use its interface.
1663 * The collection will take ownership of @c newElem and will return
1664 * ownership of @c oldElem.
1666 * Note: this method may only be called using the most derived
1667 * @c DataVector in the hierarchy.
1669 template <class T, class BASE>
1670 void DataVector<T, BASE>::swapElement(iterator pos,
1671 std::unique_ptr<base_value_type> newElem,
1672 std::unique_ptr<base_value_type>& oldElem)
1674 // Container must own its elements.
1675 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
1676 SG::throwExcNonowningContainer();
1678 testInsert ("swapElement");
1679 oldElem = std::unique_ptr<base_value_type>
1680 (DataModel_detail::DVLCast<DataVector>::cast(*pos.base()));
1681 this->clearIndex (pos);
1682 value_type ptr = newElem.release();
1684 this->moveAux (pos.base() - this->m_pCont.begin(), ptr);
1689 * @brief Erase all the elements in the collection, and reset
1690 * the ownership mode.
1691 * @param ownPolicy The new ownership policy of the container.
1693 * If the container owns its elements, then the removed elements
1694 * will be deleted. Any duplicates will be removed in this process,
1695 * but don't rely on this.
1697 template <class T, class BASE>
1698 void DataVector<T, BASE>::clear (SG::OwnershipPolicy ownPolicy)
1701 this->m_ownPolicy = ownPolicy;
1702 this->template initAuxVectorBase<DataVector> (ownPolicy,
1703 SG::DEFAULT_TRACK_INDICES);
1708 * @brief Erase all the elements in the collection, and reset
1709 * the ownership mode.
1710 * @param ownPolicy The new ownership policy of the container.
1711 * @param trackIndices The index tracking policy.
1713 * If the container owns its elements, then the removed elements
1714 * will be deleted. Any duplicates will be removed in this process,
1715 * but don't rely on this.
1717 template <class T, class BASE>
1718 void DataVector<T, BASE>::clear (SG::OwnershipPolicy ownPolicy,
1719 SG::IndexTrackingPolicy trackIndices)
1722 this->m_ownPolicy = ownPolicy;
1723 this->template initAuxVectorBase<DataVector> (ownPolicy, trackIndices);
1728 * @brief Return the DV/DL info struct for this class.
1730 * This can be used to make sure that it's instantiated.
1732 template <class T, class BASE>
1733 const DataModel_detail::DVLInfoBase& DataVector<T, BASE>::dvlinfo()
1735 static const DataModel_detail::DVLInfo<DataVector<T, BASE> > info;
1741 * @brief Erase all the elements in the collection, and change
1742 * how elements are to be deleted.
1743 * @param deleter Object to be used to delete object.
1744 * Passing nullptr will change back to the default.
1746 * If the container owns its elements, then the removed elements
1747 * will be deleted. Any duplicates will be removed in this process,
1748 * but don't rely on this.
1749 * After the current elements are deleted, the Deleter object is changed.
1751 template <class T, class BASE>
1752 void DataVector<T, BASE>::clear (std::unique_ptr<Deleter> deleter)
1755 delete this->m_deleter;
1756 this->m_deleter = deleter.release();
1761 * @brief Return the DV/DL info struct for this class.
1763 * This can be used to make sure that it's instantiated.
1765 template <class T, class BASE>
1766 const DataModel_detail::DVLInfoBase& DataVector<T, BASE>::dvlinfo_v() const
1768 return DataVector<T, BASE>::dvlinfo();
1773 * @brief Return the offset of a base @c DataVector class.
1774 * @param ti @c std::type_info of the desired class.
1776 * If @c ti represents a @c DataVector base class of this one,
1777 * then return the offset of that base class. Otherwise, return -1.
1779 * This function is here due to limitations of root 6, which can't
1780 * calculate these offsets correctly from the dictionary if
1781 * virtual derivation is used.
1783 template <class T, class BASE>
1784 int DataVector<T, BASE>::baseOffset (const std::type_info& ti)
1787 return baseOffset1 (reinterpret_cast<const char*>(&dv), dv, ti);
1792 * @brief Convert to @c AuxVectorBase.
1794 * Needed to get @x AuxVectorBase from a @c ConstDataVector.
1795 * Present in @c DataVector as well for consistency.
1796 * We only really need it in the base class; however, root6 fails
1797 * constructing a @c TMethodCall for this if there is virtual
1798 * derivation. A workaround is to redeclare this in the derived
1801 template <class T, class BASE>
1802 const SG::AuxVectorBase& DataVector<T, BASE>::auxbase() const
1808 //=== Internal operations.
1812 * @brief Helper for @c baseOffset.
1813 * @param p Pointer to the start of the top-level object.
1814 * @param dv Reference to the DataVector object.
1815 * @param ti @c std::type_info of the desired class.
1817 * If @c ti represents a @c DataVector base class of this one,
1818 * then return the offset of that base class. Otherwise, return -1.
1821 template <class T, class BASE>
1822 int DataVector<T, BASE>::baseOffset1 (const char* p, const DataVector& dv,
1823 const std::type_info& ti)
1825 if (typeid(DataVector) == ti)
1826 return reinterpret_cast<const char*>(&dv) - p;
1827 return BASE::baseOffset1 (p, dv, ti);
1832 * @brief Reset indices / reorder aux data after elements have been permuted.
1833 * @param beg Start of the range of elements to process.
1834 * @param end End of the range of elements to process.
1836 * Call this after some operation that has permuted the elements in the
1837 * container (such as sort). The index information in the elements
1838 * will be used to permute all auxiliary data in the same way.
1839 * Finally, all the indices will be reset in the correct order.
1841 template <class T, class BASE>
1842 void DataVector<T, BASE>::resortAux (iterator beg, iterator end)
1844 if (typename SG::AuxStore_traits<DataVector>::flag() &&
1845 beg >= this->begin() && end <= this->end())
1847 SG::AuxVectorBase::resortAux (beg-begin(), beg, end);
1853 * @brief Test if we can insert; raise an exception if not.
1854 * @param op Description of the attempted operation.
1856 * In order to maintain type-safety, we can only allow insertions
1857 * using the most-derived instance of @c DataVector. This checks
1858 * this by testing the @c m_isMostDerived, which is set by the constructors
1859 * to true only for the most-derived instance.
1860 * If the test fails, we call to potentially out-of-line code to continue.
1862 template <class T, class BASE>
1864 void DataVector<T, BASE>::testInsert (const char* op)
1866 if (ATHCONTAINERS_LIKELY (m_isMostDerived))
1868 this->testInsertOol (op);
1873 * @brief Test if we can insert; raise an exception if not.
1874 * @param op Description of the attempted operation.
1876 * This continues the test of @c testInsert. There is one case
1877 * where @c m_isMostDerived may not be set correctly. If this container
1878 * was made via copy construction, then all the @c m_isMostDerived flags
1879 * will be false. So we call @c setMostDerived to set the flags correctly
1880 * and test again. If the test fails again, then we raise an exception.
1882 template <class T, class BASE>
1883 void DataVector<T, BASE>::testInsertOol (const char* op)
1885 this->setMostDerived();
1886 if (!m_isMostDerived)
1887 throw SG::ExcInsertionInBaseClass (op, typeid(DataVector), dv_typeid());
1892 * @brief Handle element assignment.
1893 * @param pos Position in the container to assign.
1894 * @param newElem The new element to assign.
1896 * The old element is freed if this container owns elements.
1897 * Auxiliary data are copied if appropriate.
1899 template <class T, class BASE>
1900 void DataVector<T, BASE>::assignElement (typename BaseContainer::iterator pos,
1903 testInsert ("assignElement");
1904 if (this->m_ownPolicy == SG::OWN_ELEMENTS)
1905 this->doDelete (*pos);
1907 this->clearIndex (iterator (pos, this));
1909 this->moveAux (pos - this->m_pCont.begin(), newElem);
1914 * @brief Handle element assignment.
1915 * @param pos Position in the container to assign.
1916 * @param newElem The new element to assign.
1918 * The container must own its elements.
1919 * Auxiliary data are copied if appropriate.
1921 template <class T, class BASE>
1923 DataVector<T, BASE>::assignElement (typename BaseContainer::iterator pos,
1924 std::unique_ptr<base_value_type> newElem)
1926 // Container must own its elements.
1927 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
1928 SG::throwExcNonowningContainer();
1930 testInsert ("assignElement");
1931 this->doDelete (*pos);
1932 value_type ptr = newElem.release();
1934 this->moveAux (pos - this->m_pCont.begin(), ptr);
1939 * @brief Handle element assignment from a base pointer.
1940 * @param pos Position in the container to assign.
1941 * @param newElem The new element to assign.
1943 * The old element is freed if this container owns elements.
1944 * Auxiliary data are copied if appropriate.
1946 template <class T, class BASE>
1948 DataVector<T, BASE>::assignBaseElement (typename BaseContainer::iterator pos,
1949 typename BaseContainer::value_type newElem)
1951 testInsert ("assignBaseElement");
1952 if (this->m_ownPolicy == SG::OWN_ELEMENTS)
1953 this->doDelete (*pos);
1955 this->clearIndex (iterator (pos, this));
1957 if (typename SG::AuxStore_traits<DataVector>::flag())
1958 this->moveAux (pos - this->m_pCont.begin(),
1959 DataModel_detail::DVLCast<DataVector>::cast(newElem));
1964 * @brief Shift the auxiliary elements of the container.
1965 * @param pos The starting index for the shift.
1966 * @param offs The (signed) amount of the shift.
1968 * The elements in the container should have already been shifted;
1969 * this operation will then adjust the element indices and also shift
1970 * the elements in the vectors for all aux data items.
1971 * @c offs may be either positive or negative.
1973 * If @c offs is positive, then the container is growing.
1974 * The container size should be increased by @c offs,
1975 * the element at @c pos moved to @c pos + @c offs,
1976 * and similarly for following elements.
1977 * The elements between @c pos and @c pos + @c offs should
1978 * be default-initialized.
1980 * If @c offs is negative, then the container is shrinking.
1981 * The element at @c pos should be moved to @c pos + @c offs,
1982 * and similarly for following elements.
1983 * The container should then be shrunk by @c -offs elements
1984 * (running destructors as appropriate).
1986 template <class T, class BASE>
1987 void DataVector<T, BASE>::shift (size_t pos, ptrdiff_t offs)
1989 SG::AuxVectorBase::shift (*this, pos, offs);
1994 * @brief Helper to shorten calls to @c DataVector_detail::DVLCast.
1995 * @param p The value to convert.
1996 * @return The value as a @c const @c T*.
1998 * The conversion will be done with @c static_cast if possible,
1999 * with @c dynamic_cast otherwise.
2001 template <class T, class BASE>
2004 DataVector<T, BASE>::do_cast (const typename PtrVector::value_type p)
2006 return DataModel_detail::DVLCast<DataVector>::cast (p);
2011 * @brief Helper to shorten calls to @c DataVector_detail::DVLCast.
2012 * @param p The value to convert.
2013 * @return The value as a @c T*.
2015 * The conversion will be done with @c static_cast if possible,
2016 * with @c dynamic_cast otherwise.
2018 template <class T, class BASE>
2021 DataVector<T, BASE>::do_cast_nc (typename PtrVector::value_type p)
2023 return DataModel_detail::DVLCast<DataVector>::cast (p);
2028 * @brief Find the most-derived @c DataVector class in the hierarchy.
2029 * @return The @c type_info for the class for which this method gets run.
2031 * This is used to generate a nice error message when the most-derived
2032 * check for insertions fails.
2033 * Every @c DataVector defines this virtual method, so when it's
2034 * called, the one corresponding to the most-derived @c DataVector
2037 template <class T, class BASE>
2038 const std::type_info& DataVector<T, BASE>::dv_typeid() const
2040 return typeid(DataVector);
2045 * @brief Clear @c m_isMostDerived for this instance and for all bases.
2047 * Called from the constructor after setting @c m_isMostDerived.
2049 template <class T, class BASE>
2051 void DataVector<T, BASE>::clearMostDerived()
2053 this->m_isMostDerived = false;
2054 BASE::clearMostDerived();
2059 * @brief Set @c m_isMostDerived for this instance and clear it for all bases.
2061 * Called from @c testInsert if the test fails. The flag may not have
2062 * been set if this container was made via copy construction, so set
2063 * it appropriately now so we can test again.
2065 template <class T, class BASE>
2066 void DataVector<T, BASE>::setMostDerived()
2068 m_isMostDerived = true;
2069 BASE::clearMostDerived();
2073 //****************************************************************************
2074 // Specialized (base) DataVector implementation.
2078 // An abbreviation for the DataVector specialization to try to make
2079 // things a little more readable.
2080 #define DATAVECTOR DataVector<T, DataModel_detail::NoBase>
2083 //=== Constructors, destructors, assignment.
2086 * @brief Default constructor.
2087 * @param ownPolicy The ownership mode for the container.
2088 * @param trackIndices The index tracking policy.
2090 * By default, a @c DataVector will own its elements.
2091 * To avoid this, pass @c SG::VIEW_ELEMENTS for @a ownPolicy.
2095 DATAVECTOR::DataVector
2096 (SG::OwnershipPolicy ownPolicy /*= SG::OWN_ELEMENTS*/,
2097 SG::IndexTrackingPolicy trackIndices /*=SG::DEFAULT_TRACK_INDICES*/)
2098 : m_ownPolicy(ownPolicy)
2100 this->template initAuxVectorBase<DataVector> (ownPolicy, trackIndices);
2101 this->m_isMostDerived = true;
2106 * @brief Sized constructor.
2107 * @param n The size of the container.
2108 * @param ownPolicy The ownership mode for the container.
2109 * @param trackIndices The index tracking policy.
2111 * Note that unlike the standard vector constructor, you can't specify
2112 * an initial value here. The container will be initialized with 0's.
2114 * By default, a @c DataVector will own its elements.
2115 * To avoid this, pass @c SG::VIEW_ELEMENTS for @a ownPolicy.
2119 DATAVECTOR::DataVector
2121 SG::OwnershipPolicy ownPolicy /*= SG::OWN_ELEMENTS*/,
2122 SG::IndexTrackingPolicy trackIndices /*= SG::DEFAULT_TRACK_INDICES*/)
2123 : m_ownPolicy(ownPolicy),
2126 this->template initAuxVectorBase<DataVector> (ownPolicy, trackIndices);
2127 this->m_isMostDerived = true;
2132 * @brief Copy constructor.
2133 * @param rhs The container from which to copy.
2135 * This is a `shallow' copy; the new container will not own its elements.
2139 DATAVECTOR::DataVector(const DataVector& rhs)
2141 m_ownPolicy(SG::VIEW_ELEMENTS),
2142 m_pCont(rhs.m_pCont)
2144 this->template initAuxVectorBase<DataVector> (m_ownPolicy,
2145 SG::DEFAULT_TRACK_INDICES);
2146 // Leave m_isMostDerived false here, because we may be being called
2147 // from a derived class implicit copy constructor. The flags will get
2148 // set correctly when @c testInsert gets called.
2153 * @brief Move constructor.
2154 * @param rhs The container from which to move.
2156 * Any auxiliary data will be moved along with the container contents.
2160 DATAVECTOR::DataVector(DataVector&& rhs) noexcept
2161 : AuxVectorBase (std::move (rhs)),
2162 m_ownPolicy(rhs.m_ownPolicy),
2163 m_pCont(std::move (rhs.m_pCont))
2165 m_deleter = std::move(rhs.m_deleter);
2166 rhs.m_deleter = nullptr;
2168 // Need to reset the container pointer on elements.
2169 // Functions called from here can throw GaudiException.
2170 // However, logically that should not actually happen; so leave this
2171 // declared as noexcept.
2172 this->setIndices (this->begin(), this->end());
2174 // This doesn't get called from derived classes.
2175 // Go ahead and set this flag now.
2176 m_isMostDerived = true;
2181 * @brief Constructor from iterators.
2182 * @param first The start of the range to put in the new container.
2183 * @param last The end of the range to put in the new container.
2184 * @param ownPolicy The ownership mode for the container.
2185 * @param trackIndices The index tracking policy.
2186 * @param store An associated auxiliary data store.
2188 * By default, a view container is made, which does not own its elements.
2189 * To have the container take ownership of the pointers passed
2190 * to this constructor, pass @c SG::OWN_ELEMENTS for @a ownPolicy.
2193 template <class InputIterator>
2195 DATAVECTOR::DataVector
2196 (InputIterator first,
2198 SG::OwnershipPolicy ownPolicy /*= SG::VIEW_ELEMENTS*/,
2199 SG::IndexTrackingPolicy trackIndices /*= SG::DEFAULT_TRACK_INDICES*/,
2200 SG::IAuxStore* store /*= 0*/)
2201 : m_ownPolicy(ownPolicy)
2203 this->template initAuxVectorBase<DataVector> (ownPolicy, trackIndices);
2204 this->m_isMostDerived = true;
2206 this->setStore (store);
2207 insert (this->begin(), first, last);
2212 * @brief Constructor from an initializer list.
2213 * @param l An initializer list.
2214 * @param last The end of the range to put in the new container.
2215 * @param ownPolicy The ownership mode for the container.
2216 * @param trackIndices The index tracking policy.
2217 * @param store An associated auxiliary data store.
2220 * A @c DataVector constructed this way will *not* own its elements
2221 * by default. To change this, pass @c SG::OWN_ELEMENTS for @a ownPolicy.
2225 DATAVECTOR::DataVector
2226 (std::initializer_list<value_type> l,
2227 SG::OwnershipPolicy ownPolicy /*= SG::VIEW_ELEMENTS*/,
2228 SG::IndexTrackingPolicy trackIndices /*= SG::DEFAULT_TRACK_INDICES*/,
2229 SG::IAuxStore* store /*= 0*/)
2230 : DataVector (l.begin(), l.end(), ownPolicy, trackIndices, store)
2236 * @brief Assignment operator.
2237 * @param rhs The DataVector from which to assign.
2238 * @return This object.
2240 * This is a `shallow' copy; after the completion of this, the @c DataVector
2241 * will not own its elements. Any elements it owned prior to this call
2244 * Note: this method may only be called using the most derived
2245 * @c DataVector in the hierarchy.
2249 DATAVECTOR& DATAVECTOR::operator= (const DataVector& rhs)
2252 // Ensure we're not being called via a base class.
2253 // This can throw an exception, so this method should not be noexcept.
2254 testInsert ("assignment operator");
2255 clear(); // Release any currently-owned elements.
2256 m_ownPolicy = SG::VIEW_ELEMENTS;
2257 this->setStore ((SG::IConstAuxStore*)0);
2258 this->template initAuxVectorBase<DataVector> (m_ownPolicy,
2259 SG::DEFAULT_TRACK_INDICES);
2260 m_pCont = rhs.m_pCont;
2267 * @brief Move assignment.
2268 * @param rhs The container from which to move.
2270 * Any auxiliary data will be moved along with the container contents.
2273 DATAVECTOR& DATAVECTOR::operator= (DATAVECTOR&& rhs)
2276 // Ensure we're not being called via a base class.
2277 // This can throw an exception, so this method should not be noexcept.
2278 testInsert ("assignment operator");
2280 this->clear(); // Release any currently-owned elements.
2282 SG::AuxVectorBase::operator= (std::move (rhs));
2283 this->m_ownPolicy = rhs.m_ownPolicy;
2284 this->m_pCont = std::move (rhs.m_pCont);
2286 delete this->m_deleter;
2287 this->m_deleter = std::move(rhs.m_deleter);
2288 rhs.m_deleter = nullptr;
2290 // Need to reset the container pointer on elements.
2291 this->setIndices (this->begin(), this->end());
2298 * @brief Assignment operator, from an initializer list.
2299 * @param l An initializer list.
2300 * @return This object.
2302 * This is equivalent to @c assign.
2303 * Any existing owned elements will be released.
2304 * The @c DataVector's ownership policy determines whether it will take
2305 * ownership of the new elements.
2309 DATAVECTOR& DATAVECTOR::operator= (std::initializer_list<value_type> l)
2311 this->assign (l.begin(), l.end());
2317 * @brief Assign from iterators.
2318 * @param first The start of the range to put in the container.
2319 * @param last The end of the range to put in the container.
2321 * Any existing owned elements will be released.
2322 * The @c DataVector's ownership policy determines whether it will take
2323 * ownership of the new elements.
2326 template <class InputIterator>
2327 void DATAVECTOR::assign (InputIterator first,
2330 // Ensure we're not being called via a base class.
2331 testInsert ("assign");
2332 clear(); // Release any currently-owned elements.
2333 insert(begin(), first, last);
2338 * @brief Assign from an initializer list.
2339 * @param l An initializer list.
2341 * Any existing owned elements will be released.
2342 * The @c DataVector's ownership policy determines whether it will take
2343 * ownership of the new elements.
2346 void DATAVECTOR::assign (std::initializer_list<value_type> l)
2348 this->assign (l.begin(), l.end());
2353 * @brief Destructor.
2355 * If this container owns its elements, the contained elements will
2356 * be deleted as well. Before doing this, the destructor will scan
2357 * for duplicate pointers (takes @f$n \log n@f$ time); duplicates are only
2358 * destroyed once. Duplicates should, however, be considered an error;
2359 * don't rely on this behavior.
2362 DATAVECTOR::~DataVector()
2364 if (m_ownPolicy == SG::OWN_ELEMENTS) {
2365 typename PtrVector::iterator new_end =
2366 DataVector_detail::remove_duplicates(m_pCont.begin(), m_pCont.end());
2367 this->doDelete (m_pCont.begin(), new_end);
2373 //=== Size and capacity.
2377 * @brief Returns the number of elements in the collection.
2381 typename DATAVECTOR::size_type DATAVECTOR::size() const noexcept
2383 return m_pCont.size();
2388 * @brief Returns the number of elements in the collection.
2390 * This version is virtual, to be callable from the AuxData
2395 typename DATAVECTOR::size_type DATAVECTOR::size_v() const
2397 return this->size();
2402 * @brief Returns the @c size() of the largest possible collection.
2406 typename DATAVECTOR::size_type DATAVECTOR::max_size() const noexcept
2408 return m_pCont.max_size();
2413 * @brief Resizes the collection to the specified number of elements.
2414 * @param sz The new size of the collection.
2416 * Note that this function differs from the standard in that it does
2417 * not allow specifying the value of any inserted elements.
2418 * They will always be 0.
2420 * If the container is shrunk, elements will be deleted as with @c erase().
2423 void DATAVECTOR::resize(size_type sz)
2425 if (sz < this->size()) {
2426 this->erase (this->begin()+sz, this->end());
2428 this->m_pCont.insert(this->m_pCont.end(), sz - this->m_pCont.size(), 0);
2429 SG::AuxVectorBase::resize<DataVector> (sz);
2435 * @brief Returns the total number of elements that the collection can hold
2436 * before needing to allocate more memory.
2440 typename DATAVECTOR::size_type DATAVECTOR::capacity() const noexcept
2442 return m_pCont.capacity();
2447 * @brief Returns the total number of elements that the collection can hold
2448 * before needing to allocate more memory.
2450 * This version is virtual, to be callable from the AuxData
2455 typename DATAVECTOR::size_type DATAVECTOR::capacity_v() const
2462 * @brief Returns @c true if the collection is empty.
2466 bool DATAVECTOR::empty() const noexcept
2468 return m_pCont.empty();
2473 * @brief Attempt to preallocate enough memory for a specified number
2475 * @param n Number of elements required.
2479 void DATAVECTOR::reserve (size_type n)
2481 m_pCont.reserve (n);
2482 SG::AuxVectorBase::reserve<DataVector> (n);
2487 * @brief Change the vector capacity to match the current size.
2489 * Note: this does not affect auxiliary data.
2493 void DATAVECTOR::shrink_to_fit()
2495 m_pCont.shrink_to_fit();
2499 //=== Element access.
2503 * @brief Access an element, as an rvalue.
2504 * @param n Array index to access.
2505 * @return The element at @a n.
2507 * No bounds checking is done.
2508 * Note that we return a @c const @c T* rather than a reference.
2512 const T* DATAVECTOR::operator[] (size_type n) const
2519 * @brief Access an element, as an rvalue.
2520 * @param n Array index to access.
2521 * @return The element at @a n.
2523 * This is a synonym for operator[] const, to be used when calling from root
2524 * (where we can't readily call just the const version of a method).
2528 const T* DATAVECTOR::get (size_type n) const
2530 return do_cast(this->m_pCont[n]);
2535 * @brief Access an element, as an lvalue.
2536 * @param n Array index to access.
2537 * @return Proxy to the element at @a n.
2539 * No bounds checking is done.
2540 * Note that we return a proxy object rather than a reference;
2541 * the proxy will handle deleting an owned element if it's assigned to.
2545 typename DATAVECTOR::ElementProxy DATAVECTOR::operator[] (size_type n)
2547 return ElementProxy (m_pCont.begin() + n, this);
2552 * @brief Access an element, as an rvalue.
2553 * @param n Array index to access.
2554 * @return The element at @a n.
2556 * Will raise @c std::out_of_range if the index is out-of-bounds.
2557 * Note that we return a @c const @c T* rather than a reference.
2561 const T* DATAVECTOR::at (size_type n) const
2563 return m_pCont.at(n);
2568 * @brief Access an element, as an lvalue.
2569 * @param n Array index to access.
2570 * @return Proxy to the element at @a n.
2572 * Will raise @c std::out_of_range if the index is out-of-bounds.
2573 * Note that we return a proxy object rather than a reference;
2574 * the proxy will handle deleting an owned element if it's assigned to.
2578 typename DATAVECTOR::ElementProxy DATAVECTOR::at (size_type n)
2580 // Can't use m_pCont's at here, because we need an iterator.
2581 // So we have to do the bounds check ourselves.
2583 throw std::out_of_range ("DataVector::at range check");
2584 return ElementProxy (m_pCont.begin() + n, this);
2589 * @brief Access the first element in the collection as an rvalue.
2590 * @return The first element in the collection.
2592 * No checking is done to ensure that the container is not empty.
2593 * Note that we return a @c const @c T* rather than a reference.
2597 const T* DATAVECTOR::front() const
2599 return m_pCont.front();
2604 * @brief Access the last element in the collection as an rvalue.
2605 * @return The last element in the collection.
2607 * No checking is done to ensure that the container is not empty.
2608 * Note that we return a @c const @c T* rather than a reference.
2612 const T* DATAVECTOR::back() const
2614 return m_pCont.back();
2619 * @brief Access the first element in the collection as an lvalue.
2620 * @return Proxy to the first element in the collection.
2622 * No checking is done to ensure that the container is not empty.
2623 * Note that we return a proxy object rather than a reference;
2624 * the proxy will handle deleting an owned element if it's assigned to.
2628 typename DATAVECTOR::ElementProxy DATAVECTOR::front ()
2630 return ElementProxy (m_pCont.begin(), this);
2635 * @brief Access the last element in the collection as an lvalue.
2636 * @return Proxy to the last element in the collection.
2638 * No checking is done to ensure that the container is not empty.
2639 * Note that we return a proxy object rather than a reference;
2640 * the proxy will handle deleting an owned element if it's assigned to.
2644 typename DATAVECTOR::ElementProxy DATAVECTOR::back ()
2646 return ElementProxy (m_pCont.end()-1, this);
2650 //=== Iterator creation.
2654 * @brief Return a @c const_iterator pointing at the beginning
2655 * of the collection.
2656 * @return A @c const_iterator.
2658 * Note that dereferencing the iterator will yield a @c const @c T* rather
2663 typename DATAVECTOR::const_iterator DATAVECTOR::begin() const noexcept
2665 return m_pCont.begin();
2670 * @brief Return a @c const_iterator pointing past the end
2671 * of the collection.
2672 * @return A @c const_iterator.
2674 * Note that dereferencing the iterator will yield a @c const @c T* rather
2679 typename DATAVECTOR::const_iterator DATAVECTOR::end() const noexcept
2681 return m_pCont.end();
2686 * @brief Return an @c iterator pointing at the beginning
2687 * of the collection.
2688 * @return An @c iterator.
2690 * Note that dereferencing the iterator will yield a proxy rather
2691 * than a reference; the proxy will handle deleting an owned element
2692 * if it's assigned to.
2696 typename DATAVECTOR::iterator DATAVECTOR::begin() noexcept
2698 return iterator (m_pCont.begin(), this);
2703 * @brief Return an @c iterator pointing past the end
2704 * of the collection.
2705 * @return An @c iterator.
2707 * Note that dereferencing the iterator will yield a proxy rather
2708 * than a reference; the proxy will handle deleting an owned element
2709 * if it's assigned to.
2713 typename DATAVECTOR::iterator DATAVECTOR::end() noexcept
2715 return iterator (m_pCont.end(), this);
2720 * @brief Return a @c const_reverse_iterator pointing past the end
2721 * of the collection.
2722 * @return A @c const_reverse_iterator.
2724 * Note that dereferencing the iterator will yield a @c const @c T* rather
2729 typename DATAVECTOR::const_reverse_iterator DATAVECTOR::rbegin() const noexcept
2731 return const_reverse_iterator (m_pCont.end());
2736 * @brief Return a @c const_reverse_iterator pointing at the beginning
2737 * of the collection.
2738 * @return A @c const_reverse_iterator.
2740 * Note that dereferencing the iterator will yield a @c const @c T* rather
2745 typename DATAVECTOR::const_reverse_iterator DATAVECTOR::rend() const noexcept
2747 return const_reverse_iterator (const_iterator (m_pCont.begin()));
2752 * @brief Return a @c reverse_iterator pointing past the end
2753 * of the collection.
2754 * @return A @c reverse_iterator.
2756 * Note that dereferencing the iterator will yield a proxy rather
2757 * than a reference; the proxy will handle deleting an owned element
2758 * if it's assigned to.
2762 typename DATAVECTOR::reverse_iterator DATAVECTOR::rbegin() noexcept
2764 return reverse_iterator(iterator (m_pCont.end(), this));
2769 * @brief Return a @c reverse_iterator pointing at the beginning
2770 * of the collection.
2771 * @return A @c reverse_iterator.
2773 * Note that dereferencing the iterator will yield a proxy rather
2774 * than a reference; the proxy will handle deleting an owned element
2775 * if it's assigned to.
2779 typename DATAVECTOR::reverse_iterator DATAVECTOR::rend() noexcept
2781 return reverse_iterator(iterator (m_pCont.begin(), this));
2786 * @brief Return a @c const_iterator pointing at the beginning
2787 * of the collection.
2788 * @return A @c const_iterator.
2790 * Note that dereferencing the iterator will yield a @c const @c T* rather
2795 typename DATAVECTOR::const_iterator DATAVECTOR::cbegin() const noexcept
2797 return m_pCont.begin();
2802 * @brief Return a @c const_iterator pointing past the end
2803 * of the collection.
2804 * @return A @c const_iterator.
2806 * Note that dereferencing the iterator will yield a @c const @c T* rather
2811 typename DATAVECTOR::const_iterator DATAVECTOR::cend() const noexcept
2813 return m_pCont.end();
2818 * @brief Return a @c const_reverse_iterator pointing past the end
2819 * of the collection.
2820 * @return A @c const_reverse_iterator.
2822 * Note that dereferencing the iterator will yield a @c const @c T* rather
2827 typename DATAVECTOR::const_reverse_iterator DATAVECTOR::crbegin() const noexcept
2829 return const_reverse_iterator (m_pCont.end());
2834 * @brief Return a @c const_reverse_iterator pointing at the beginning
2835 * of the collection.
2836 * @return A @c const_reverse_iterator.
2838 * Note that dereferencing the iterator will yield a @c const @c T* rather
2843 typename DATAVECTOR::const_reverse_iterator DATAVECTOR::crend() const noexcept
2845 return const_reverse_iterator (const_iterator (m_pCont.begin()));
2849 //=== Insertion operations.
2853 * @brief Add an element to the end of the collection.
2854 * @param pElem The element to add to the collection.
2856 * The container's ownership policy will determine if it takes ownership
2857 * of the new element.
2859 * Note: this method may only be called using the most derived
2860 * @c DataVector in the hierarchy.
2862 * Returns the pushed pointer.
2866 typename DATAVECTOR::value_type
2867 DATAVECTOR::push_back(value_type pElem)
2869 // Ensure we're not being called via a base class.
2870 testInsert ("push_back");
2871 m_pCont.push_back(pElem);
2872 SG::AuxVectorBase::resize<DataVector> (this->size());
2874 this->moveAux (this->size()-1, pElem, false, true);
2880 * @brief Add an element to the end of the collection.
2881 * @param pElem The element to add to the collection.
2883 * The container must be an owning container.
2885 * Note: this method may only be called using the most derived
2886 * @c DataVector in the hierarchy.
2888 * Returns the pushed pointer.
2892 typename DATAVECTOR::value_type
2893 DATAVECTOR::push_back(std::unique_ptr<base_value_type> pElem)
2895 // Container must own its elements.
2896 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
2897 SG::throwExcNonowningContainer();
2899 // Ensure we're not being called via a base class.
2900 testInsert ("push_back");
2901 value_type ptr = pElem.release();
2902 m_pCont.push_back(ptr);
2903 SG::AuxVectorBase::resize<DataVector> (this->size());
2905 this->moveAux (this->size()-1, ptr, false, true);
2911 * @brief Add an element to the end of the collection.
2912 * @param pElem The element to add to the collection.
2914 * The container's ownership policy will determine if it takes ownership
2915 * of the new element.
2917 * Note: this method may only be called using the most derived
2918 * @c DataVector in the hierarchy.
2920 * For @c DataVector, this is like the same as @c push_back, and
2921 * it returns the pushed element.
2922 * It's included just for interface compatibility with `std::vector`.
2926 typename DATAVECTOR::value_type
2927 DATAVECTOR::emplace_back(value_type pElem)
2929 return this->push_back (pElem);
2934 * @brief Add a new element to the collection.
2935 * @param position Iterator before which the element will be added.
2936 * @param pElem The element to add to the collection.
2937 * @return An iterator that points to the inserted data.
2939 * The container's ownership policy will determine if it takes ownership
2940 * of the new element.
2942 * Note: this method may only be called using the most derived
2943 * @c DataVector in the hierarchy.
2947 typename DATAVECTOR::iterator
2948 DATAVECTOR::insert(iterator position, value_type pElem)
2950 // Ensure we're not being called via a base class.
2951 testInsert ("insert");
2952 iterator ret (m_pCont.insert(position.base(), pElem), this);
2953 this->shift (ret - this->begin(), 1);
2954 this->moveAux (ret-this->begin(), pElem, false, true);
2960 * @brief Add a new element to the collection.
2961 * @param position Iterator before which the element will be added.
2962 * @param pElem The element to add to the collection.
2963 * @return An iterator that points to the inserted data.
2965 * The container must be an owning container.
2967 * Note: this method may only be called using the most derived
2968 * @c DataVector in the hierarchy.
2972 typename DATAVECTOR::iterator
2973 DATAVECTOR::insert(iterator position, std::unique_ptr<base_value_type> pElem)
2975 // Container must own its elements.
2976 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
2977 SG::throwExcNonowningContainer();
2979 // Ensure we're not being called via a base class.
2980 testInsert ("insert");
2981 value_type ptr = pElem.release();
2982 iterator ret (m_pCont.insert(position.base(), ptr), this);
2983 this->shift (ret - this->begin(), 1);
2984 this->moveAux (ret-this->begin(), ptr, false, true);
2990 * @brief Add a new element to the collection.
2991 * @param position Iterator before which the element will be added.
2992 * @param pElem The element to add to the collection.
2993 * @return An iterator that points to the inserted data.
2995 * The container's ownership policy will determine if it takes ownership
2996 * of the new element.
2998 * Note: this method may only be called using the most derived
2999 * @c DataVector in the hierarchy.
3001 * For @c DataVector, this is just the same as @c insert.
3002 * It's included just for interface compatibility with `std::vector`.
3006 typename DATAVECTOR::iterator
3007 DATAVECTOR::emplace(iterator position, value_type pElem)
3009 return this->insert (position, pElem);
3014 * @brief Add a group of new elements to the collection.
3015 * @param position Iterator before which the element will be added.
3016 * @param first The start of the range to put in the container.
3017 * @param last The end of the range to put in the container.
3019 * The container's ownership policy will determine if it takes ownership
3020 * of the new element.
3022 * Note: this method may only be called using the most derived
3023 * @c DataVector in the hierarchy.
3025 * This overload is for the case where the iterator value type
3026 * is convertible to T*.
3029 template <class InputIterator,
3030 DataVector_detail::enable_if_ptr_itr<InputIterator, T> >
3033 DATAVECTOR::insert (iterator position, InputIterator first, InputIterator last)
3035 static_assert (std::is_same_v<T*, typename DATAVECTOR::value_type>);
3036 // Ensure we're not being called via a base class.
3037 testInsert ("insert");
3038 size_t idx = position - this->begin();
3039 size_t old_sz = this->m_pCont.size();
3040 m_pCont.insert(position.base(), first, last);
3041 size_t n = this->m_pCont.size() - old_sz;
3042 this->shift (idx, n);
3043 this->moveAux (idx, first, last, false, true);
3048 * @brief Add a group of new elements to the collection.
3049 * @param position Iterator before which the element will be added.
3050 * @param first The start of the range to put in the container.
3051 * @param last The end of the range to put in the container.
3053 * The container's ownership policy will determine if it takes ownership
3054 * of the new element.
3056 * Note: this method may only be called using the most derived
3057 * @c DataVector in the hierarchy.
3059 * This overload is for the case where the iterator value type
3060 * is convertible to unique_ptr<T>.
3063 template <class InputIterator,
3064 DataVector_detail::enable_if_up_itr<InputIterator, T> >
3067 DATAVECTOR::insert (iterator position, InputIterator first, InputIterator last)
3069 // Ensure we're not being called via a base class.
3070 testInsert ("insert");
3071 size_t idx = position - this->begin();
3072 size_t old_sz = this->m_pCont.size();
3073 using CxxUtils::releasing_iterator;
3074 m_pCont.insert(position.base(), releasing_iterator(first), releasing_iterator(last));
3075 size_t n = this->m_pCont.size() - old_sz;
3076 this->shift (idx, n);
3077 this->moveAux (idx, this->begin()+idx, this->begin()+idx+n);
3082 * @brief Add a group of new elements to the collection.
3083 * @param position Iterator before which the element will be added.
3084 * @param l An initializer list.
3086 * The container's ownership policy will determine if it takes ownership
3087 * of the new element.
3089 * Note: this method may only be called using the most derived
3090 * @c DataVector in the hierarchy.
3095 DATAVECTOR::insert (iterator position, std::initializer_list<value_type> l)
3097 this->insert (position, l.begin(), l.end());
3102 * @brief Insert the contents of another @c DataVector,
3103 * with auxiliary data copied via move semantics.
3104 * @param position Iterator before which the new elements will be added.
3105 * @param other The vector to add.
3107 * The ownership mode of this vector must be the same as @c other;
3108 * otherwise, an exception will be thrown.
3110 * If both vectors are view vectors, then this is the same
3111 * as <code> insert (position, other.begin(), other.end()) </code>.
3113 * Otherwise, the elements from @c other will be inserted into this vector.
3114 * This vector will take ownership of the elements, and the ownership
3115 * mode of @c other will be changed to @c VIEW_ELEMENTS.
3116 * Auxiliary data for these elements will be transferred,
3117 * using move semantics if possible. (Thus, the auxiliary store
3118 * for @c other may be modified and must not be locked.)
3119 * Finally, the auxiliary store pointer for @c other will be cleared
3120 * (but the store itself will not be deleted since it's not owned
3123 * Note: this method may only be called using the most derived
3124 * @c DataVector in the hierarchy.
3128 DATAVECTOR::insertMove (iterator position, DataVector& other)
3130 if (this->m_ownPolicy != other.ownPolicy())
3131 throw SG::ExcInsertMoveOwnershipMismatch();
3133 if (this->m_ownPolicy == SG::VIEW_ELEMENTS) {
3134 this->insert (position, other.begin(), other.end());
3138 testInsert ("insertMove");
3139 size_t pos = position.base() - this->m_pCont.begin();
3140 this->m_pCont.insert (position.base(), other.begin(), other.end());
3141 this->setIndices (this->begin()+pos, this->end(), pos);
3142 other.m_ownPolicy = SG::VIEW_ELEMENTS;
3144 SG::IAuxStore* otherStore = other.getStore();
3146 SG::IAuxStore* store = this->getStore();
3148 if (!store->insertMove (pos, *otherStore))
3151 else if (this->hasStore())
3152 throw SG::ExcConstAuxData ("insertMove");
3153 other.setStore (static_cast<SG::IAuxStore*>(nullptr));
3155 else if (other.hasStore())
3156 throw SG::ExcConstAuxData ("insertMove");
3160 //=== Erasure operations.
3164 * @brief Remove element at a given position.
3165 * @param position Iterator pointing to the element to be removed.
3166 * @return An iterator pointing to the next element (or @c end()).
3168 * If the container owns its elements, then the pointed-to element
3173 typename DATAVECTOR::iterator DATAVECTOR::erase(iterator position)
3175 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
3176 this->clearIndex (position);
3177 iterator ret (this->erase_base (position.base()), this);
3178 this->shift (ret - this->begin() + 1, -1);
3184 * @brief Remove a range of elements.
3185 * @param first Iterator pointing to the first element to be removed.
3186 * @param last Iterator pointing one past the last element to be removed.
3187 * @return An iterator pointing to the element pointed to by @a last
3188 * prior to erasing (or @c end()).
3190 * If the container owns its elements, then the removed elements
3191 * will be deleted. Any duplicates will be removed in this process,
3192 * but don't rely on this.
3196 typename DATAVECTOR::iterator DATAVECTOR::erase(iterator first, iterator last)
3198 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
3199 this->clearIndices (first, last);
3200 iterator ret (this->erase_base (first.base(), last.base()), this);
3201 this->shift (ret - this->begin() + (last-first), -(last-first));
3207 * @brief Remove the last element from the collection.
3209 * If the container owns its elements, then the removed element
3213 void DATAVECTOR::pop_back()
3215 if (!m_pCont.empty()) {
3216 if (m_ownPolicy == SG::OWN_ELEMENTS)
3217 this->doDelete (m_pCont.back());
3219 this->clearIndex (m_pCont.end() - 1);
3221 SG::AuxVectorBase::resize<DataVector> (this->m_pCont.size());
3227 * @brief Erase all the elements in the collection.
3229 * If the container owns its elements, then the removed elements
3230 * will be deleted. Any duplicates will be removed in this process,
3231 * but don't rely on this.
3235 void DATAVECTOR::clear()
3237 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
3238 this->clearIndices (begin(), end());
3239 this->erase_base (m_pCont.begin(), m_pCont.end());
3240 SG::AuxVectorBase::resize<DataVector> (0);
3244 //=== Swap and sort.
3248 * @brief Swap this collection with another.
3249 * @param rhs The collection with which to swap.
3251 * Ownership is swapped along with the collection content.
3253 * Note: this method may only be called using the most-derived
3254 * @c DataVector in the hierarchy. The @a rhs must also be
3255 * referenced using the most-derived @c DataVector.
3257 * Warning: If this container has auxiliary data, then this
3258 * is an O(N) operation, not O(1).
3261 void DATAVECTOR::swap(DataVector& rhs)
3263 testInsert ("swap");
3264 rhs.testInsert ("swap");
3265 std::swap(m_ownPolicy, rhs.m_ownPolicy);
3266 SG::AuxVectorBase::swap (rhs);
3267 m_pCont.swap(rhs.m_pCont);
3268 std::swap (this->m_deleter, rhs.m_deleter);
3269 this->setIndices (this->begin(), this->end());
3270 rhs.setIndices (rhs.begin(), rhs.end());
3275 * @brief Swap the referents of two @c DataVector iterators.
3276 * @param a The first iterator for the swap.
3277 * @param b The second iterator for the swap.
3280 void DATAVECTOR::iter_swap (iterator a, iterator b)
3282 if (a.ownPolicy() != b.ownPolicy()) {
3283 throw SG::ExcBadIterSwap();
3285 a.testInsert ("iter_swap");
3286 b.testInsert ("iter_swap");
3287 std::iter_swap (a.base(), b.base());
3288 DataVector* acont = a.container();
3289 DataVector* bcont = b.container();
3290 if (typename SG::AuxStore_traits<DataVector>::flag())
3291 acont->swapElementsAux (a.base() - acont->stdcont().begin(),
3292 b.base() - bcont->stdcont().begin(),
3300 * @brief Sort the container.
3302 * This just sorts by pointer value, so it's probably not very useful.
3305 void DATAVECTOR::sort()
3307 std::sort(m_pCont.begin(), m_pCont.end());
3308 this->resortAux (this->begin(), this->end());
3313 * @brief Sort the container with a user-specified comparison operator.
3314 * @param comp Functional to compare two values.
3317 template <class COMPARE>
3318 void DATAVECTOR::sort(COMPARE comp)
3320 std::sort(m_pCont.begin(), m_pCont.end(), comp);
3321 this->resortAux (this->begin(), this->end());
3325 //=== Non-standard operations.
3329 * @brief Swap one element out of the container.
3330 * @param index Index of the element in the container to swap.
3331 * @param newElement New element to put in the container.
3333 * @param oldElem Reference to receive the element removed from the
3336 * Reference @a oldElem is initialized with element @a index of the
3337 * collection (no bounds checking). Then element @a index is set
3338 * to @newElem. If the collection owns its elements, then it will
3339 * take ownership of @a newElem and release (without deleting)
3340 * the element returned through @a oldElem.
3342 * Note: this method may only be called using the most derived
3343 * @c DataVector in the hierarchy.
3347 DATAVECTOR::swapElement (size_type index,
3351 testInsert ("swapElement");
3352 oldElem = m_pCont[index];
3353 this->clearIndex (iterator (m_pCont.begin() + index, this));
3354 m_pCont[index] = newElem;
3355 this->moveAux (index, newElem);
3360 * @brief Swap one element out of the container.
3361 * @param pos The element in the container to swap.
3362 * @param newElem New element to put in the container.
3364 * @param oldElem Reference to receive the element removed from the
3367 * Reference @a oldElem is initialized with element @a pos of the
3368 * collection (no bounds checking). Then element @a index is set
3369 * to @c newElem. If the collection owns its elements, then it will
3370 * take ownership of @a newElem and release (without deleting)
3371 * the element returned through @a oldElem.
3373 * Note: this method may only be called using the most derived
3374 * @c DataVector in the hierarchy.
3378 DATAVECTOR::swapElement (iterator pos,
3382 testInsert ("swapElement");
3383 oldElem = *pos.base();
3384 this->clearIndex (pos);
3385 *pos.base() = newElem;
3386 this->moveAux (pos.base() - this->m_pCont.begin(), newElem);
3391 * @brief Swap one element out of the container.
3392 * @param index Index of the element in the container to swap.
3393 * @param newElement New element to put in the container.
3395 * @param oldElem Reference to receive the element removed from the
3398 * Reference @a oldElem is initialized with element @a index of the
3399 * collection (no bounds checking). Then element @a index is set
3402 * The collection must own its elements to use its interface.
3403 * The collection will take ownership of @c newElem and will return
3404 * ownership of @c oldElem.
3406 * Note: this method may only be called using the most derived
3407 * @c DataVector in the hierarchy.
3411 DATAVECTOR::swapElement (size_type index,
3412 std::unique_ptr<base_value_type> newElem,
3413 std::unique_ptr<base_value_type>& oldElem)
3415 // Container must own its elements.
3416 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
3417 SG::throwExcNonowningContainer();
3419 testInsert ("swapElement");
3420 oldElem = std::unique_ptr<base_value_type> (m_pCont[index]);
3421 this->clearIndex (iterator (m_pCont.begin() + index, this));
3422 value_type ptr = newElem.release();
3423 m_pCont[index] = ptr;
3424 this->moveAux (index, ptr);
3429 * @brief Swap one element out of the container.
3430 * @param pos The element in the container to swap.
3431 * @param newElem New element to put in the container.
3433 * @param oldElem Reference to receive the element removed from the
3436 * Reference @a oldElem is initialized with element @a pos of the
3437 * collection (no bounds checking). Then element @a index is set
3440 * The collection must own its elements to use its interface.
3441 * The collection will take ownership of @c newElem and will return
3442 * ownership of @c oldElem.
3444 * Note: this method may only be called using the most derived
3445 * @c DataVector in the hierarchy.
3449 DATAVECTOR::swapElement (iterator pos,
3450 std::unique_ptr<base_value_type> newElem,
3451 std::unique_ptr<base_value_type>& oldElem)
3453 // Container must own its elements.
3454 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
3455 SG::throwExcNonowningContainer();
3457 testInsert ("swapElement");
3458 oldElem = std::unique_ptr<base_value_type> (*pos.base());
3459 this->clearIndex (pos);
3460 value_type ptr = newElem.release();
3462 this->moveAux (pos.base() - this->m_pCont.begin(), ptr);
3467 * @brief Return the underlying @c std::vector of the container.
3468 * @return Reference to the @c std::vector actually holding the collection.
3470 * Note that @c DataVector<T>::stdcont does not necessarily return
3471 * a @c std::vector<T*> if @c DataVector inheritance is being used.
3475 const typename DATAVECTOR::PtrVector& DATAVECTOR::stdcont() const
3482 * @brief Return the ownership policy setting for this container.
3486 SG::OwnershipPolicy DATAVECTOR::ownPolicy() const
3493 * @brief Erase all the elements in the collection, and reset
3494 * the ownership mode.
3495 * @param ownPolicy The new ownership policy of the container.
3496 * @param trackIndices The index tracking policy.
3498 * If the container owns its elements, then the removed elements
3499 * will be deleted. Any duplicates will be removed in this process,
3500 * but don't rely on this.
3503 void DATAVECTOR::clear (SG::OwnershipPolicy ownPolicy)
3506 m_ownPolicy = ownPolicy;
3507 this->template initAuxVectorBase<DataVector> (ownPolicy,
3508 SG::DEFAULT_TRACK_INDICES);
3513 * @brief Erase all the elements in the collection, and reset
3514 * the ownership mode.
3515 * @param ownPolicy The new ownership policy of the container.
3516 * @param trackIndices The index tracking policy.
3518 * If the container owns its elements, then the removed elements
3519 * will be deleted. Any duplicates will be removed in this process,
3520 * but don't rely on this.
3523 void DATAVECTOR::clear (SG::OwnershipPolicy ownPolicy,
3524 SG::IndexTrackingPolicy trackIndices)
3527 m_ownPolicy = ownPolicy;
3528 this->template initAuxVectorBase<DataVector> (ownPolicy, trackIndices);
3533 * @brief Return the DV/DL info struct for this class.
3535 * This can be used to make sure that it's instantiated.
3538 const DataModel_detail::DVLInfoBase& DATAVECTOR::dvlinfo()
3540 static const DataModel_detail::DVLInfo<DataVector<T, DataModel_detail::NoBase> > info;
3546 * @brief Erase all the elements in the collection, and change
3547 * how elements are to be deleted.
3548 * @param deleter Object to be used to delete object.
3549 * (The DataVector does not take ownership.)
3550 * Passing nullptr will change back to the default.
3552 * If the container owns its elements, then the removed elements
3553 * will be deleted. Any duplicates will be removed in this process,
3554 * but don't rely on this.
3555 * After the current elements are deleted, the Deleter object is changed.
3558 void DATAVECTOR::clear (std::unique_ptr<Deleter> deleter)
3561 delete this->m_deleter;
3562 this->m_deleter = deleter.release();
3567 * @brief Return the DV/DL info struct for this class.
3569 * This can be used to make sure that it's instantiated.
3572 const DataModel_detail::DVLInfoBase& DATAVECTOR::dvlinfo_v() const
3574 return DATAVECTOR::dvlinfo();
3579 * @brief Return the offset of a base @c DataVector class.
3580 * @param ti @c std::type_info of the desired class.
3582 * If @c ti represents a @c DataVector base class of this one,
3583 * then return the offset of that base class. Otherwise, return -1.
3585 * This function is here due to limitations of root 6, which can't
3586 * calculate these offsets correctly from the dictionary if
3587 * virtual derivation is used.
3590 int DATAVECTOR::baseOffset (const std::type_info& ti)
3592 if (typeid(DataVector) == ti)
3599 * @brief Convert to @c AuxVectorBase.
3601 * Needed to get @x AuxVectorBase from a @c ConstDataVector.
3602 * Present in @c DataVector as well for consistency.
3606 const SG::AuxVectorBase& DATAVECTOR::auxbase() const
3612 //=== Internal operations.
3616 * @brief Helper for @c baseOffset.
3617 * @param p Pointer to the start of the top-level object.
3618 * @param dv Reference to the DataVector object.
3619 * @param ti @c std::type_info of the desired class.
3621 * If @c ti represents a @c DataVector base class of this one,
3622 * then return the offset of that base class. Otherwise, return -1.
3626 int DATAVECTOR::baseOffset1 (const char* p, const DataVector& dv,
3627 const std::type_info& ti)
3629 if (typeid(DataVector) == ti)
3630 return reinterpret_cast<const char*>(&dv) - p;
3636 * @brief Reset indices / reorder aux data after elements have been permuted.
3637 * @param beg Start of the range of elements to process.
3638 * @param end End of the range of elements to process.
3640 * Call this after some operation that has permuted the elements in the
3641 * container (such as sort). The index information in the elements
3642 * will be used to permute all auxiliary data in the same way.
3643 * Finally, all the indices will be reset in the correct order.
3646 void DATAVECTOR::resortAux (iterator beg, iterator end)
3648 if (typename SG::AuxStore_traits<DataVector>::flag() &&
3649 beg >= this->begin() && end <= this->end())
3651 SG::AuxVectorBase::resortAux (beg-begin(), beg, end);
3657 * @brief Handle element assignment.
3658 * @param pos Position in the container to assign.
3659 * @param newElem The new element to assign.
3661 * The old element is freed if this container owns elements.
3662 * Auxiliary data are copied if appropriate.
3665 void DATAVECTOR::assignElement (typename BaseContainer::iterator pos,
3668 testInsert ("assignElement");
3669 if (this->m_ownPolicy == SG::OWN_ELEMENTS)
3670 this->doDelete (*pos);
3672 this->clearIndex (iterator (pos, this));
3674 this->moveAux (pos - this->m_pCont.begin(), newElem);
3679 * @brief Handle element assignment.
3680 * @param pos Position in the container to assign.
3681 * @param newElem The new element to assign.
3683 * The container must own its elements.
3684 * Auxiliary data are copied if appropriate.
3688 DATAVECTOR::assignElement (typename BaseContainer::iterator pos,
3689 std::unique_ptr<base_value_type> newElem)
3691 // Container must own its elements.
3692 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
3693 SG::throwExcNonowningContainer();
3695 testInsert ("assignElement");
3696 this->doDelete (*pos);
3697 value_type ptr = newElem.release();
3699 this->moveAux (pos - this->m_pCont.begin(), ptr);
3704 * @brief Handle element assignment from a base pointer.
3705 * @param pos Position in the container to assign.
3706 * @param newElem The new element to assign.
3708 * The old element is freed if this container owns elements.
3709 * Auxiliary data are copied if appropriate.
3712 void DATAVECTOR::assignBaseElement (typename BaseContainer::iterator pos,
3713 typename BaseContainer::value_type newElem)
3715 testInsert ("assignBaseElement");
3716 if (this->m_ownPolicy == SG::OWN_ELEMENTS)
3717 this->doDelete (*pos);
3719 this->clearIndex (iterator (pos, this));
3721 if (typename SG::AuxStore_traits<DataVector>::flag())
3722 this->moveAux (pos - this->m_pCont.begin(), newElem);
3727 * @brief Shift the auxiliary elements of the container.
3728 * @param pos The starting index for the shift.
3729 * @param offs The (signed) amount of the shift.
3731 * The elements in the container should have already been shifted;
3732 * this operation will then adjust the element indices and also shift
3733 * the elements in the vectors for all aux data items.
3734 * @c offs may be either positive or negative.
3736 * If @c offs is positive, then the container is growing.
3737 * The container size should be increased by @c offs,
3738 * the element at @c pos moved to @c pos + @c offs,
3739 * and similarly for following elements.
3740 * The elements between @c pos and @c pos + @c offs should
3741 * be default-initialized.
3743 * If @c offs is negative, then the container is shrinking.
3744 * The element at @c pos should be moved to @c pos + @c offs,
3745 * and similarly for following elements.
3746 * The container should then be shrunk by @c -offs elements
3747 * (running destructors as appropriate).
3750 void DATAVECTOR::shift (size_t pos, ptrdiff_t offs)
3752 SG::AuxVectorBase::shift (*this, pos, offs);
3757 * @brief Helper to shorten calls to @c DataModel_detail::DVLCast.
3758 * @param p The value to convert.
3759 * @return The value as a @c const @c T*.
3761 * This is a no-op for the base class.
3765 const T* DATAVECTOR::do_cast (const typename PtrVector::value_type p)
3772 * @brief Helper to shorten calls to @c DataModel_detail::DVLCast.
3773 * @param p The value to convert.
3774 * @return The value as a @c T*.
3776 * This is a no-op for the base class.
3780 T* DATAVECTOR::do_cast_nc (typename PtrVector::value_type p)
3787 * @brief Find the most-derived @c DataVector class in the hierarchy.
3788 * @return The @c type_info for the class for which this method gets run.
3790 * This is used to generate a nice error message when the most-derived
3791 * check for insertions fails.
3792 * Every @c DataVector defines this virtual method, so when it's
3793 * called, the one corresponding to the most-derived @c DataVector
3797 const std::type_info& DATAVECTOR::dv_typeid() const
3799 return typeid(DataVector);
3804 * @brief Helper for @c erase(). Remove element at a given position.
3805 * @param position Iterator pointing to the element to be removed.
3806 * @return An iterator pointing to the next element (or @c end()).
3808 * This function factors out common code between @c erase() in the
3809 * base and derived @c DataVector classes. It deals with the
3810 * @c std::vector iterators directly.
3813 typename DATAVECTOR::PtrVector::iterator
3814 DATAVECTOR::erase_base(typename PtrVector::iterator position)
3816 if (m_ownPolicy == SG::OWN_ELEMENTS && position != m_pCont.end())
3817 this->doDelete (*position);
3818 return m_pCont.erase(position);
3823 * @brief Helper for @c erase(). Remove a range of elements.
3824 * @param first Iterator pointing to the first element to be removed.
3825 * @param last Iterator pointing one past the last element to be removed.
3826 * @return An iterator pointing to the element pointed to by @a last
3827 * prior to erasing (or @c end()).
3829 * This function factors out common code between @c erase() in the
3830 * base and derived @c DataVector classes. It deals with the
3831 * @c std::vector iterators directly.
3834 typename DATAVECTOR::PtrVector::iterator
3835 DATAVECTOR::erase_base(typename PtrVector::iterator first,
3836 typename PtrVector::iterator last)
3838 if (first == last) return first;
3839 if (m_ownPolicy == SG::OWN_ELEMENTS) {
3840 typename PtrVector::iterator new_end =
3841 DataVector_detail::remove_duplicates(first, last);
3842 this->doDelete (first, new_end);
3844 return m_pCont.erase(first, last);
3849 * @brief Delete an element
3850 * @param p The element to delete.
3854 void DATAVECTOR::doDelete (value_type p)
3857 m_deleter->doDelete (p);
3866 * @brief Delete a range of elements
3867 * @param first Start of range to delete.
3868 * @param last End of range to delete.
3872 void DATAVECTOR::doDelete (typename PtrVector::iterator first,
3873 typename PtrVector::iterator last)
3876 m_deleter->doDelete (first, last);
3879 for (; first != last; ++first) {
3887 * @brief Test if we can insert; raise an exception if not.
3888 * @param op Description of the attempted operation.
3890 * In order to maintain type-safety, we can only allow insertions
3891 * using the most-derived instance of @c DataVector. This checks
3892 * this by testing the @c m_isMostDerived, which is set by the constructors
3893 * to true only for the most-derived instance.
3894 * If the test fails, we call to potentially out-of-line code to continue.
3898 void DATAVECTOR::testInsert (const char* op)
3900 if (ATHCONTAINERS_LIKELY (m_isMostDerived))
3902 this->testInsertOol (op);
3907 * @brief Test if we can insert; raise an exception if not.
3908 * @param op Description of the attempted operation.
3910 * This continues the test of @c testInsert. There is one case
3911 * where @c m_isMostDerived may not be set correctly. If this container
3912 * was made via copy construction, then all the @c m_isMostDerived flags
3913 * will be false. So we call @c setMostDerived to set the flags correctly
3914 * and test again. If the test fails again, then we raise an exception.
3917 void DATAVECTOR::testInsertOol (const char* op)
3919 this->setMostDerived();
3920 if (!m_isMostDerived)
3921 throw SG::ExcInsertionInBaseClass (op, typeid(DataVector), dv_typeid());
3926 * @brief Clear @c m_isMostDerived for this instance and for all bases.
3928 * Called from the constructor after setting @c m_isMostDerived.
3932 void DATAVECTOR::clearMostDerived()
3934 this->m_isMostDerived = false;
3939 * @brief Set @c m_isMostDerived for this instance and clear it for all bases.
3941 * Called from @c testInsert if the test fails. The flag may not have
3942 * been set if this container was made via copy construction, so set
3943 * it appropriately now so we can test again.
3946 void DATAVECTOR::setMostDerived()
3948 m_isMostDerived = true;
3955 //****************************************************************************
3956 // Free function implementations.
3961 * @brief Vector equality comparison.
3962 * @param a A @c DataVector.
3963 * @param b A @c DataVector of the same type as @a b.
3964 * @return True iff the size and elements of the vectors are equal.
3966 * This is an equivalence relation. It is linear in the size of the
3967 * vectors. Vectors are considered equivalent if their sizes are equal,
3968 * and if corresponding elements compare equal.
3971 bool operator== (const DataVector<T>& a, const DataVector<T>& b)
3973 return a.stdcont() == b.stdcont();
3977 /// Based on operator==
3979 bool operator!= (const DataVector<T>& a, const DataVector<T>& b)
3981 return a.stdcont() != b.stdcont();
3986 * @brief Vector ordering relation.
3987 * @param a A @c DataVector.
3988 * @param b A @c DataVector of the same type as @a x.
3989 * @return True iff @a a is lexicographically less than @a b.
3991 * This is a total ordering relation. It is linear in the size of the
3992 * vectors. Comparisons are done on the pointer values of the elements.
3994 * See @c std::lexicographical_compare() for how the determination is made.
3997 bool operator< (const DataVector<T>& a, const DataVector<T>& b)
3999 return a.stdcont() < b.stdcont();
4003 /// Based on operator<
4005 bool operator> (const DataVector<T>& a, const DataVector<T>& b)
4007 return a.stdcont() > b.stdcont();
4011 /// Based on operator<
4013 bool operator<= (const DataVector<T>& a, const DataVector<T>& b)
4015 return a.stdcont() <= b.stdcont();
4019 /// Based on operator<
4021 bool operator>= (const DataVector<T>& a, const DataVector<T>& b)
4023 return a.stdcont() >= b.stdcont();
4027 /// See @c DataVector<T, BASE>::swap().
4029 void swap (DataVector<T>& a, DataVector<T>& b)
4036 * @brief Specialization of @c ClassName for @c DataVector.
4038 * This overrides the default implementation of @c ClassName
4039 * to hide @c DataVector's second template parameter.
4042 std::string ClassName<DataVector<T> >::name()
4044 std::string out = "DataVector<";
4045 out += ClassName<T>::name();
4046 if (out[out.size()-1] == '>')
4053 #ifndef XAOD_STANDALONE
4056 // Set up initialization of element type BaseInfo
4057 namespace DataVector_detail {
4058 #define DVLTYPE DataVector
4059 #include "AthContainers/tools/DVLEltBaseInfo.icc"
4061 } // namespace DataVector_detail
4067 namespace DataVector_detail {
4068 /// Dummy implementation for the DVLEltBaseInit structure
4070 struct DVLEltBaseInit {};
4071 } // namespace DataVector_detail
4074 #endif // not XAOD_STANDALONE
4078 // We need to specialize the function that DVLInfo uses to create the container
4081 * @brief Construct a new container.
4082 * @param nreserve Number of elements for which to reserve space.
4083 * (Ignored if not appropriate.)
4084 * @param cont[out] Pointer to the constructed container.
4085 * (Returned via an argument to allow for template
4086 * argument deduction.)
4088 * Specialization for DataVector.
4091 void dvl_makecontainer (size_t nreserve, DataVector<T>*& cont)
4093 cont = new DataVector<T> (SG::VIEW_ELEMENTS);
4094 cont->reserve (nreserve);