1 // Dear emacs, this is -*- c++ -*-
4 Copyright (C) 2002-2023 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 ENTER_ROOT_SELECTION_NS
28 namespace DataVector_detail {
29 template <class B1, class B2, class B3> class VirtBases;
31 EXIT_ROOT_SELECTION_NS
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
110 return typeid(VirtBases);
112 virtual const DataModel_detail::DVLInfoBase& dvlinfo_v() const
114 return DataVector<B1>::dvlinfo();
116 virtual void setMostDerived()
123 int baseOffset1 (const char* p, const VirtBases& dv,
124 const std::type_info& ti)
126 return DataVector<B1>::baseOffset1 (p, dv, ti);
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
191 return typeid(VirtBases);
193 virtual const DataModel_detail::DVLInfoBase& dvlinfo_v() const
195 return DataVector<B1>::dvlinfo();
197 virtual void setMostDerived()
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);
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
280 return typeid(VirtBases);
282 virtual const DataModel_detail::DVLInfoBase& dvlinfo_v() const
284 return DataVector<B1>::dvlinfo();
286 virtual void setMostDerived()
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_SELECTION_NS::DataVector_detail::VirtBases<B1, B2, B3>::self
313 } // namespace DataVector_detail
316 ENTER_ROOT_SELECTION_NS
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 EXIT_ROOT_SELECTION_NS
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 template <class T, class BASE>
554 DataVector<T, BASE>::operator= (DataVector<T, BASE>&& rhs) noexcept
557 // Ensure we're not being called via a base class.
558 testInsert ("assignment operator");
560 this->clear(); // Release any currently-owned elements.
562 SG::AuxVectorBase::operator= (std::move (rhs));
563 this->m_ownPolicy = rhs.m_ownPolicy;
564 this->m_pCont = std::move (rhs.m_pCont);
566 delete this->m_deleter;
567 this->m_deleter = std::move(rhs.m_deleter);
568 rhs.m_deleter = nullptr;
570 // Need to reset the container pointer on elements.
571 this->setIndices (this->begin(), this->end());
578 * @brief Assignment operator, from an initializer list.
579 * @param l An initializer list.
580 * @return This object.
582 * This is equivalent to @c assign.
583 * Any existing owned elements will be released.
584 * The @c DataVector's ownership policy determines whether it will take
585 * ownership of the new elements.
587 template <class T, class BASE>
590 DataVector<T, BASE>::operator= (std::initializer_list<value_type> l)
592 this->assign (l.begin(), l.end());
598 * @brief Assign from iterators.
599 * @param first The start of the range to put in the container.
600 * @param last The end of the range to put in the container.
602 * Any existing owned elements will be released.
603 * The @c DataVector's ownership policy determines whether it will take
604 * ownership of the new elements.
606 template <class T, class BASE>
607 template <class InputIterator>
608 void DataVector<T, BASE>::assign(InputIterator first, InputIterator last)
610 // Ensure we're not being called via a base class.
611 testInsert ("assign");
612 this->clear(); // Release any currently-owned elements.
613 insert(begin(), first, last);
618 * @brief Assign from an initializer list.
619 * @param l An initializer list.
621 * Any existing owned elements will be released.
622 * The @c DataVector's ownership policy determines whether it will take
623 * ownership of the new elements.
625 template <class T, class BASE>
626 void DataVector<T, BASE>::assign(std::initializer_list<value_type> l)
628 this->assign (l.begin(), l.end());
632 //=== Size and capacity.
636 * @fn size_type size() const
637 * @brief Returns the number of elements in the collection.
639 template <class T, class BASE>
641 typename DataVector<T, BASE>::size_type
642 DataVector<T, BASE>::size() const noexcept
644 return this->m_pCont.size();
649 * @brief Resizes the collection to the specified number of elements.
650 * @param sz The new size of the collection.
652 * Note that this function differs from the standard in that it does
653 * not allow specifying the value of any inserted elements.
654 * They will always be 0.
656 * If the container is shrunk, elements will be deleted as with @c erase().
658 template <class T, class BASE>
659 void DataVector<T, BASE>::resize(size_type sz)
661 if (sz < this->size()) {
662 this->erase (this->begin()+sz, this->end());
664 this->m_pCont.insert(this->m_pCont.end(), sz - this->m_pCont.size(), 0);
665 SG::AuxVectorBase::resize<DataVector> (sz);
671 * @brief Attempt to preallocate enough memory for a specified number
673 * @param n Number of elements required.
675 template <class T, class BASE>
677 void DataVector<T, BASE>::reserve (size_type n)
679 this->m_pCont.reserve (n);
680 SG::AuxVectorBase::reserve<DataVector> (n);
684 //=== Element access.
688 * @brief Access an element, as an rvalue.
689 * @param n Array index to access.
690 * @return The element at @a n.
692 * No bounds checking is done.
693 * Note that we return a @c const @c T* rather than a reference.
695 template <class T, class BASE>
697 const T* DataVector<T, BASE>::operator[] (size_type n) const
699 return do_cast(this->m_pCont[n]);
704 * @brief Access an element, as an rvalue.
705 * @param n Array index to access.
706 * @return The element at @a n.
708 * This is a synonym for operator[] const, to be used when calling from root
709 * (where we can't readily call just the const version of a method).
711 template <class T, class BASE>
713 const T* DataVector<T, BASE>::get (size_type n) const
715 return do_cast(this->m_pCont[n]);
720 * @brief Access an element, as an lvalue.
721 * @param n Array index to access.
722 * @return Proxy to the element at @a n.
724 * No bounds checking is done.
725 * Note that we return a proxy object rather than a reference;
726 * the proxy will handle deleting an owned element if it's assigned to.
728 template <class T, class BASE>
730 typename DataVector<T, BASE>::ElementProxy
731 DataVector<T, BASE>::operator[] (size_type n)
733 return ElementProxy (this->m_pCont.begin() + n, this);
738 * @brief Access an element, as an rvalue.
739 * @param n Array index to access.
740 * @return The element at @a n.
742 * Will raise @c std::out_of_range if the index is out-of-bounds.
743 * Note that we return a @c const @c T* rather than a reference.
745 template <class T, class BASE>
747 const T* DataVector<T, BASE>::at (size_type n) const
749 return do_cast(this->m_pCont.at(n));
754 * @brief Access an element, as an lvalue.
755 * @param n Array index to access.
756 * @return Proxy to the element at @a n.
758 * Will raise @c std::out_of_range if the index is out-of-bounds.
759 * Note that we return a proxy object rather than a reference;
760 * the proxy will handle deleting an owned element if it's assigned to.
762 template <class T, class BASE>
764 typename DataVector<T, BASE>::ElementProxy
765 DataVector<T, BASE>::at (size_type n)
767 // Can't use m_pCont's at here, because we need an iterator.
768 // So we have to do the bounds check ourselves.
769 if (n >= this->size())
770 throw std::out_of_range ("DataVector::at range check");
771 return ElementProxy (this->m_pCont.begin() + n, this);
776 * @brief Access the first element in the collection as an rvalue.
777 * @return The first element in the collection.
779 * No checking is done to ensure that the container is not empty.
780 * Note that we return a @c const @c T* rather than a reference.
782 template <class T, class BASE>
784 const T* DataVector<T, BASE>::front() const
786 return do_cast (this->m_pCont.front());
791 * @brief Access the last element in the collection as an rvalue.
792 * @return The last element in the collection.
794 * No checking is done to ensure that the container is not empty.
795 * Note that we return a @c const @c T* rather than a reference.
797 template <class T, class BASE>
799 const T* DataVector<T, BASE>::back() const
801 return do_cast (this->m_pCont.back());
806 * @brief Access the first element in the collection as an lvalue.
807 * @return Proxy to the first element in the collection.
809 * No checking is done to ensure that the container is not empty.
810 * Note that we return a proxy object rather than a reference;
811 * the proxy will handle deleting an owned element if it's assigned to.
813 template <class T, class BASE>
815 typename DataVector<T, BASE>::ElementProxy
816 DataVector<T, BASE>::front ()
818 return ElementProxy (this->m_pCont.begin(), this);
823 * @brief Access the last element in the collection as an lvalue.
824 * @return Proxy to the last element in the collection.
826 * No checking is done to ensure that the container is not empty.
827 * Note that we return a proxy object rather than a reference;
828 * the proxy will handle deleting an owned element if it's assigned to.
830 template <class T, class BASE>
832 typename DataVector<T, BASE>::ElementProxy
833 DataVector<T, BASE>::back ()
835 return ElementProxy (this->m_pCont.end()-1, this);
839 //=== Iterator creation.
843 * @brief Return a @c const_iterator pointing at the beginning
845 * @return A @c const_iterator.
847 * Note that dereferencing the iterator will yield a @c const @c T* rather
850 template <class T, class BASE>
852 typename DataVector<T, BASE>::const_iterator
853 DataVector<T, BASE>::begin() const noexcept
855 return const_iterator (this->m_pCont.begin());
860 * @brief Return a @c const_iterator pointing past the end
862 * @return A @c const_iterator.
864 * Note that dereferencing the iterator will yield a @c const @c T* rather
867 template <class T, class BASE>
869 typename DataVector<T, BASE>::const_iterator
870 DataVector<T, BASE>::end() const noexcept
872 return const_iterator (this->m_pCont.end());
877 * @brief Return an @c iterator pointing at the beginning
879 * @return An @c iterator.
881 * Note that dereferencing the iterator will yield a proxy rather
882 * than a reference; the proxy will handle deleting an owned element
883 * if it's assigned to.
885 template <class T, class BASE>
887 typename DataVector<T, BASE>::iterator
888 DataVector<T, BASE>::begin() noexcept
890 return iterator (this->m_pCont.begin(), this);
895 * @brief Return an @c iterator pointing past the end
897 * @return An @c iterator.
899 * Note that dereferencing the iterator will yield a proxy rather
900 * than a reference; the proxy will handle deleting an owned element
901 * if it's assigned to.
903 template <class T, class BASE>
905 typename DataVector<T, BASE>::iterator
906 DataVector<T, BASE>::end() noexcept
908 return iterator (this->m_pCont.end(), this);
913 * @brief Return a @c const_reverse_iterator pointing past the end
915 * @return A @c const_reverse_iterator.
917 * Note that dereferencing the iterator will yield a @c const @c T* rather
920 template <class T, class BASE>
922 typename DataVector<T, BASE>::const_reverse_iterator
923 DataVector<T, BASE>::rbegin() const noexcept
925 return const_reverse_iterator (end());
930 * @brief Return a @c const_reverse_iterator pointing at the beginning
932 * @return A @c const_reverse_iterator.
934 * Note that dereferencing the iterator will yield a @c const @c T* rather
937 template <class T, class BASE>
939 typename DataVector<T, BASE>::const_reverse_iterator
940 DataVector<T, BASE>::rend() const noexcept
942 return const_reverse_iterator (begin());
947 * @brief Return a @c reverse_iterator pointing past the end
949 * @return A @c reverse_iterator.
951 * Note that dereferencing the iterator will yield a proxy rather
952 * than a reference; the proxy will handle deleting an owned element
953 * if it's assigned to.
955 template <class T, class BASE>
957 typename DataVector<T, BASE>::reverse_iterator
958 DataVector<T, BASE>::rbegin() noexcept
960 return reverse_iterator (iterator (this->m_pCont.end(), this));
965 * @brief Return a @c reverse_iterator pointing at the beginning
967 * @return A @c reverse_iterator.
969 * Note that dereferencing the iterator will yield a proxy rather
970 * than a reference; the proxy will handle deleting an owned element
971 * if it's assigned to.
973 template <class T, class BASE>
975 typename DataVector<T, BASE>::reverse_iterator
976 DataVector<T, BASE>::rend() noexcept
978 return reverse_iterator (iterator (this->m_pCont.begin(), this));
983 * @brief Return a @c const_iterator pointing at the beginning
985 * @return A @c const_iterator.
987 * Note that dereferencing the iterator will yield a @c const @c T* rather
990 template <class T, class BASE>
992 typename DataVector<T, BASE>::const_iterator
993 DataVector<T, BASE>::cbegin() const noexcept
995 return const_iterator (this->m_pCont.begin());
1000 * @brief Return a @c const_iterator pointing past the end
1001 * of the collection.
1002 * @return A @c const_iterator.
1004 * Note that dereferencing the iterator will yield a @c const @c T* rather
1007 template <class T, class BASE>
1009 typename DataVector<T, BASE>::const_iterator
1010 DataVector<T, BASE>::cend() const noexcept
1012 return const_iterator (this->m_pCont.end());
1017 * @brief Return a @c const_reverse_iterator pointing past the end
1018 * of the collection.
1019 * @return A @c const_reverse_iterator.
1021 * Note that dereferencing the iterator will yield a @c const @c T* rather
1024 template <class T, class BASE>
1026 typename DataVector<T, BASE>::const_reverse_iterator
1027 DataVector<T, BASE>::crbegin() const noexcept
1029 return const_reverse_iterator (cend());
1034 * @brief Return a @c const_reverse_iterator pointing at the beginning
1035 * of the collection.
1036 * @return A @c const_reverse_iterator.
1038 * Note that dereferencing the iterator will yield a @c const @c T* rather
1041 template <class T, class BASE>
1043 typename DataVector<T, BASE>::const_reverse_iterator
1044 DataVector<T, BASE>::crend() const noexcept
1046 return const_reverse_iterator (cbegin());
1050 //=== Insertion operations.
1054 * @brief Add an element to the end of the collection.
1055 * @param pElem The element to add to the collection.
1057 * The container's ownership policy will determine if it takes ownership
1058 * of the new element.
1060 * Note: this method may only be called using the most derived
1061 * @c DataVector in the hierarchy.
1063 * Returns the pushed pointer.
1065 template <class T, class BASE>
1067 typename DataVector<T, BASE>::value_type
1068 DataVector<T, BASE>::push_back(value_type pElem)
1070 // Ensure we're not being called via a base class.
1071 testInsert ("push_back");
1072 this->m_pCont.push_back(static_cast<typename PtrVector::value_type>(pElem));
1073 SG::AuxVectorBase::resize<DataVector> (this->size());
1075 this->moveAux (this->size()-1, pElem, false, true);
1081 * @brief Add an element to the end of the collection.
1082 * @param pElem The element to add to the collection.
1084 * The container must be an owning container.
1086 * Note: this method may only be called using the most derived
1087 * @c DataVector in the hierarchy.
1089 * Returns the pushed pointer.
1091 template <class T, class BASE>
1093 typename DataVector<T, BASE>::value_type
1094 DataVector<T, BASE>::push_back(std::unique_ptr<base_value_type> pElem)
1096 // Container must own its elements.
1097 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
1098 SG::throwExcNonowningContainer();
1100 // Ensure we're not being called via a base class.
1101 testInsert ("push_back");
1102 value_type ptr = pElem.release();
1103 this->m_pCont.push_back(ptr);
1104 SG::AuxVectorBase::resize<DataVector> (this->size());
1106 this->moveAux (this->size()-1, ptr, false, true);
1112 * @brief Add an element to the end of the collection.
1113 * @param pElem The element to add to the collection.
1115 * The container's ownership policy will determine if it takes ownership
1116 * of the new element.
1118 * Note: this method may only be called using the most derived
1119 * @c DataVector in the hierarchy.
1121 * For @c DataVector, this is like the same as @c push_back, and
1122 * it returns the pushed element.
1123 * It's included just for interface compatibility with `std::vector`.
1125 template <class T, class BASE>
1127 typename DataVector<T, BASE>::value_type
1128 DataVector<T, BASE>::emplace_back(value_type pElem)
1130 return this->push_back (pElem);
1135 * @brief Add a new element to the collection.
1136 * @param position Iterator before which the element will be added.
1137 * @param pElem The element to add to the collection.
1138 * @return An iterator that points to the inserted data.
1140 * The container's ownership policy will determine if it takes ownership
1141 * of the new element.
1143 * Note: this method may only be called using the most derived
1144 * @c DataVector in the hierarchy.
1146 template <class T, class BASE>
1147 typename DataVector<T, BASE>::iterator
1148 DataVector<T, BASE>::insert(iterator position, value_type pElem)
1150 // Ensure we're not being called via a base class.
1151 testInsert ("insert");
1152 iterator ret (this->m_pCont.insert(position.base(), pElem), this);
1153 this->shift (ret - this->begin(), 1);
1154 this->moveAux (ret-this->begin(), pElem, false, true);
1160 * @brief Add a new element to the collection.
1161 * @param position Iterator before which the element will be added.
1162 * @param pElem The element to add to the collection.
1163 * @return An iterator that points to the inserted data.
1165 * The container must be an owning container.
1167 * Note: this method may only be called using the most derived
1168 * @c DataVector in the hierarchy.
1170 template <class T, class BASE>
1171 typename DataVector<T, BASE>::iterator
1172 DataVector<T, BASE>::insert(iterator position,
1173 std::unique_ptr<base_value_type> pElem)
1175 // Container must own its elements.
1176 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
1177 SG::throwExcNonowningContainer();
1179 // Ensure we're not being called via a base class.
1180 testInsert ("insert");
1181 value_type ptr = pElem.release();
1182 iterator ret (this->m_pCont.insert(position.base(), ptr), this);
1183 this->shift (ret - this->begin(), 1);
1184 this->moveAux (ret-this->begin(), ptr, false, true);
1190 * @brief Add a new element to the collection.
1191 * @param position Iterator before which the element will be added.
1192 * @param pElem The element to add to the collection.
1193 * @return An iterator that points to the inserted data.
1195 * The container's ownership policy will determine if it takes ownership
1196 * of the new element.
1198 * Note: this method may only be called using the most derived
1199 * @c DataVector in the hierarchy.
1201 * For @c DataVector, this is just the same as @c insert.
1202 * It's included just for interface compatibility with `std::vector`.
1204 template <class T, class BASE>
1205 typename DataVector<T, BASE>::iterator
1206 DataVector<T, BASE>::emplace(iterator position, value_type pElem)
1208 return this->insert (position, pElem);
1213 * @brief Add a group of new elements to the collection.
1214 * @param position Iterator before which the element will be added.
1215 * @param first The start of the range to put in the container.
1216 * @param last The end of the range to put in the container.
1218 * The container's ownership policy will determine if it takes ownership
1219 * of the new element.
1221 * Note: this method may only be called using the most derived
1222 * @c DataVector in the hierarchy.
1224 * This overload is for the case where the iterator value type
1225 * is convertible to T*.
1227 template <class T, class BASE>
1228 template <class InputIterator,
1229 DataVector_detail::enable_if_ptr_itr<InputIterator, T> >
1230 void DataVector<T, BASE>::insert(iterator position,
1231 InputIterator first,
1234 // Make sure that the input iterator can actually be converted
1235 // to a T*. Lets us give a compilation error for this:
1236 // DATAVECTOR_BASE(D, B);
1239 // d.insert (d.begin(), bb, bb+1);
1240 // which would otherwise compile.
1241 using ittype = typename std::iterator_traits<InputIterator>::value_type;
1242 static_assert (std::is_convertible_v<ittype, const T*>);
1244 // Ensure we're not being called via a base class.
1245 testInsert ("insert");
1246 size_t idx = position - this->begin();
1247 size_t old_sz = this->m_pCont.size();
1248 this->m_pCont.insert(position.base(), first, last);
1249 size_t n = this->m_pCont.size() - old_sz;
1250 this->shift (idx, n);
1251 this->moveAux (idx, first, last, false, true);
1256 * @brief Add a group of new elements to the collection.
1257 * @param position Iterator before which the element will be added.
1258 * @param first The start of the range to put in the container.
1259 * @param last The end of the range to put in the container.
1261 * The container's ownership policy will determine if it takes ownership
1262 * of the new element.
1264 * Note: this method may only be called using the most derived
1265 * @c DataVector in the hierarchy.
1267 * This overload is for the case where the iterator value type
1268 * is convertible to unique_ptr<T>.
1270 template <class T, class BASE>
1271 template <class InputIterator,
1272 DataVector_detail::enable_if_up_itr<InputIterator, T> >
1273 void DataVector<T, BASE>::insert(iterator position,
1274 InputIterator first,
1277 // Make sure that the input iterator can actually be converted
1278 // to a T*. Lets us give a compilation error for this:
1279 // DATAVECTOR_BASE(D, B);
1282 // d.insert (d.begin(), bb, bb+1);
1283 // which would otherwise compile.
1284 using ittype = typename std::iterator_traits<InputIterator>::value_type;
1285 static_assert (std::is_convertible_v<typename ittype::pointer, const T*>);
1287 // Ensure we're not being called via a base class.
1288 testInsert ("insert");
1289 size_t idx = position - this->begin();
1290 size_t old_sz = this->m_pCont.size();
1291 using CxxUtils::releasing_iterator;
1292 this->m_pCont.insert(position.base(), releasing_iterator(first), releasing_iterator(last));
1293 size_t n = this->m_pCont.size() - old_sz;
1294 this->shift (idx, n);
1295 this->moveAux (idx, this->begin()+idx, this->begin()+idx+n);
1300 * @brief Add a group of new elements to the collection.
1301 * @param position Iterator before which the element will be added.
1302 * @param l An initializer list.
1304 * The container's ownership policy will determine if it takes ownership
1305 * of the new element.
1307 * Note: this method may only be called using the most derived
1308 * @c DataVector in the hierarchy.
1310 template <class T, class BASE>
1311 void DataVector<T, BASE>::insert(iterator position,
1312 std::initializer_list<value_type> l)
1314 insert (position, l.begin(), l.end());
1319 * @brief Insert the contents of another @c DataVector,
1320 * with auxiliary data copied via move semantics.
1321 * @param position Iterator before which the new elements will be added.
1322 * @param other The vector to add.
1324 * The ownership mode of this vector must be the same as @c other;
1325 * otherwise, an exception will be thrown.
1327 * If both vectors are view vectors, then this is the same
1328 * as <code> insert (position, other.begin(), other.end()) </code>.
1330 * Otherwise, the elements from @c other will be inserted into this vector.
1331 * This vector will take ownership of the elements, and the ownership
1332 * mode of @c other will be changed to @c VIEW_ELEMENTS.
1333 * Auxiliary data for these elements will be transferred,
1334 * using move semantics if possible. (Thus, the auxiliary store
1335 * for @c other may be modified and must not be locked.)
1336 * Finally, the auxiliary store pointer for @c other will be cleared
1337 * (but the store itself will not be deleted since it's not owned
1340 * Note: this method may only be called using the most derived
1341 * @c DataVector in the hierarchy.
1343 template <class T, class BASE>
1345 DataVector<T, BASE>::insertMove (iterator position, DataVector& other)
1347 if (this->m_ownPolicy != other.ownPolicy())
1348 throw SG::ExcInsertMoveOwnershipMismatch();
1350 if (this->m_ownPolicy == SG::VIEW_ELEMENTS) {
1351 this->insert (position, other.begin(), other.end());
1355 testInsert ("insertMove");
1356 size_t pos = position.base() - this->m_pCont.begin();
1357 this->m_pCont.insert (position.base(), other.begin(), other.end());
1358 this->setIndices (this->begin()+pos, this->end(), pos);
1359 other.m_ownPolicy = SG::VIEW_ELEMENTS;
1361 SG::IAuxStore* otherStore = other.getStore();
1363 SG::IAuxStore* store = this->getStore();
1365 if (!store->insertMove (pos, *otherStore))
1368 else if (this->hasStore())
1369 throw SG::ExcConstAuxData ("insertMove");
1370 other.setStore (static_cast<SG::IAuxStore*>(nullptr));
1372 else if (other.hasStore())
1373 throw SG::ExcConstAuxData ("insertMove");
1377 //=== Erasure operations.
1381 * @brief Remove element at a given position.
1382 * @param position Iterator pointing to the element to be removed.
1383 * @return An iterator pointing to the next element (or @c end()).
1385 * If the container owns its elements, then the pointed-to element
1388 template <class T, class BASE>
1389 typename DataVector<T, BASE>::iterator
1390 DataVector<T, BASE>::erase(iterator position)
1392 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
1393 this->clearIndex (position);
1394 iterator ret (this->erase_base (position.base()), this);
1395 this->shift (ret - this->begin() + 1, -1);
1401 * @brief Remove a range of elements.
1402 * @param first Iterator pointing to the first element to be removed.
1403 * @param last Iterator pointing one past the last element to be removed.
1404 * @return An iterator pointing to the element pointed to by @a last
1405 * prior to erasing (or @c end()).
1407 * If the container owns its elements, then the removed elements
1408 * will be deleted. Any duplicates will be removed in this process,
1409 * but don't rely on this.
1411 template <class T, class BASE>
1412 typename DataVector<T, BASE>::iterator
1413 DataVector<T, BASE>::erase(iterator first, iterator last)
1415 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
1416 this->clearIndices (first, last);
1417 iterator ret (this->erase_base (first.base(), last.base()), this);
1418 this->shift (ret - this->begin() + (last-first), -(last-first));
1424 * @brief Remove the last element from the collection.
1426 * If the container owns its elements, then the removed element
1429 template <class T, class BASE>
1430 void DataVector<T, BASE>::pop_back()
1432 if (!this->m_pCont.empty()) {
1433 if (this->m_ownPolicy == SG::OWN_ELEMENTS)
1434 this->doDelete (this->m_pCont.back());
1436 this->clearIndex (iterator (this->m_pCont.end() - 1, this));
1437 this->m_pCont.pop_back();
1438 SG::AuxVectorBase::resize<DataVector> (this->m_pCont.size());
1444 * @brief Erase all the elements in the collection.
1446 * If the container owns its elements, then the removed elements
1447 * will be deleted. Any duplicates will be removed in this process,
1448 * but don't rely on this.
1450 template <class T, class BASE>
1452 void DataVector<T, BASE>::clear()
1454 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
1455 this->clearIndices (begin(), end());
1456 this->erase_base (this->m_pCont.begin(), this->m_pCont.end());
1457 SG::AuxVectorBase::resize<DataVector> (0);
1461 //=== Swap and sort.
1465 * @brief Swap this collection with another.
1466 * @param rhs The collection with which to swap.
1468 * Ownership is swapped along with the collection content.
1470 * Note: this method may only be called using the most-derived
1471 * @c DataVector in the hierarchy. The @a rhs must also be
1472 * referenced using the most-derived @c DataVector.
1474 * Warning: If this container has auxiliary data, then this
1475 * is an O(N) operation, not O(1).
1477 template <class T, class BASE>
1478 void DataVector<T, BASE>::swap(DataVector& rhs)
1480 testInsert ("swap");
1481 rhs.testInsert ("swap");
1482 std::swap(this->m_ownPolicy, rhs.m_ownPolicy);
1483 SG::AuxVectorBase::swap (rhs);
1484 this->m_pCont.swap(rhs.m_pCont);
1485 std::swap (this->m_deleter, rhs.m_deleter);
1486 this->setIndices (this->begin(), this->end());
1487 rhs.setIndices (rhs.begin(), rhs.end());
1492 * @brief Swap the referents of two @c DataVector iterators.
1493 * @param a The first iterator for the swap.
1494 * @param b The second iterator for the swap.
1496 template <class T, class BASE>
1497 void DataVector<T, BASE>::iter_swap (iterator a, iterator b)
1499 if (a.ownPolicy() != b.ownPolicy()) {
1500 throw SG::ExcBadIterSwap();
1502 a.testInsert ("iter_swap");
1503 b.testInsert ("iter_swap");
1504 std::iter_swap (a.base(), b.base());
1505 DataVector* acont = a.container();
1506 DataVector* bcont = b.container();
1507 if (typename SG::AuxStore_traits<DataVector>::flag())
1508 acont->swapElementsAux (a.base() - acont->stdcont().begin(),
1509 b.base() - bcont->stdcont().begin(),
1510 DataModel_detail::DVLCast<DataVector>::cast(*a.base()),
1511 DataModel_detail::DVLCast<DataVector>::cast(*b.base()),
1517 * @brief Sort the container.
1519 * This just sorts by pointer value, so it's probably not very useful.
1521 template <class T, class BASE>
1522 void DataVector<T, BASE>::sort()
1524 typedef std::less<typename PtrVector::value_type> less;
1525 std::sort (this->m_pCont.begin(), this->m_pCont.end(),
1526 DataModel_detail::Compwrapper<DataVector, less> (less()));
1527 this->resortAux (this->begin(), this->end());
1532 * @brief Sort the container with a user-specified comparison operator.
1533 * @param comp Functional to compare two values.
1535 template <class T, class BASE>
1536 template <class COMPARE>
1537 void DataVector<T, BASE>::sort(COMPARE comp)
1539 std::sort (this->m_pCont.begin(), this->m_pCont.end(),
1540 DataModel_detail::Compwrapper<DataVector, COMPARE> (comp));
1541 this->resortAux (this->begin(), this->end());
1545 //=== Non-standard operations.
1549 * @brief Swap one element out of the container.
1550 * @param index Index of the element in the container to swap.
1551 * @param newElement New element to put in the container.
1553 * @param oldElem Reference to receive the element removed from the
1556 * Reference @a oldElem is initialized with element @a index of the
1557 * collection (no bounds checking). Then element @a index is set
1558 * to @newElem. If the collection owns its elements, then it will
1559 * take ownership of @a newElem and release (without deleting)
1560 * the element returned through @a oldElem.
1562 * Note: this method may only be called using the most derived
1563 * @c DataVector in the hierarchy.
1565 template <class T, class BASE>
1566 void DataVector<T, BASE>::swapElement(size_type index,
1570 testInsert ("swapElement");
1572 DataModel_detail::DVLCast<DataVector>::cast(this->m_pCont[index]);
1573 this->clearIndex (iterator (this->m_pCont.begin() + index, this));
1574 this->m_pCont[index] = newElem;
1575 this->moveAux (index, newElem);
1580 * @brief Swap one element out of the container.
1581 * @param pos The element in the container to swap.
1582 * @param newElem New element to put in the container.
1584 * @param oldElem Reference to receive the element removed from the
1587 * Reference @a oldElem is initialized with element @a pos of the
1588 * collection (no bounds checking). Then element @a index is set
1589 * to @c newElem. If the collection owns its elements, then it will
1590 * take ownership of @a newElem and release (without deleting)
1591 * the element returned through @a oldElem.
1593 * Note: this method may only be called using the most derived
1594 * @c DataVector in the hierarchy.
1596 template <class T, class BASE>
1597 void DataVector<T, BASE>::swapElement(iterator pos,
1601 testInsert ("swapElement");
1603 DataModel_detail::DVLCast<DataVector>::cast(*pos.base());
1604 this->clearIndex (pos);
1605 *pos.base() = newElem;
1606 this->moveAux (pos.base() - this->m_pCont.begin(), newElem);
1611 * @brief Swap one element out of the container.
1612 * @param index Index of the element in the container to swap.
1613 * @param newElement New element to put in the container.
1615 * @param oldElem Reference to receive the element removed from the
1618 * Reference @a oldElem is initialized with element @a index of the
1619 * collection (no bounds checking). Then element @a index is set
1622 * The collection must own its elements to use its interface.
1623 * The collection will take ownership of @c newElem and will return
1624 * ownership of @c oldElem.
1626 * Note: this method may only be called using the most derived
1627 * @c DataVector in the hierarchy.
1629 template <class T, class BASE>
1630 void DataVector<T, BASE>::swapElement(size_type index,
1631 std::unique_ptr<base_value_type> newElem,
1632 std::unique_ptr<base_value_type>& oldElem)
1634 // Container must own its elements.
1635 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
1636 SG::throwExcNonowningContainer();
1638 testInsert ("swapElement");
1639 oldElem = std::unique_ptr<base_value_type>
1640 (DataModel_detail::DVLCast<DataVector>::cast(this->m_pCont[index]));
1641 this->clearIndex (iterator (this->m_pCont.begin() + index, this));
1642 value_type ptr = newElem.release();
1643 this->m_pCont[index] = ptr;
1644 this->moveAux (index, ptr);
1649 * @brief Swap one element out of the container.
1650 * @param pos The element in the container to swap.
1651 * @param newElem New element to put in the container.
1653 * @param oldElem Reference to receive the element removed from the
1656 * Reference @a oldElem is initialized with element @a pos of the
1657 * collection (no bounds checking). Then element @a index is set
1660 * The collection must own its elements to use its interface.
1661 * The collection will take ownership of @c newElem and will return
1662 * ownership of @c oldElem.
1664 * Note: this method may only be called using the most derived
1665 * @c DataVector in the hierarchy.
1667 template <class T, class BASE>
1668 void DataVector<T, BASE>::swapElement(iterator pos,
1669 std::unique_ptr<base_value_type> newElem,
1670 std::unique_ptr<base_value_type>& oldElem)
1672 // Container must own its elements.
1673 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
1674 SG::throwExcNonowningContainer();
1676 testInsert ("swapElement");
1677 oldElem = std::unique_ptr<base_value_type>
1678 (DataModel_detail::DVLCast<DataVector>::cast(*pos.base()));
1679 this->clearIndex (pos);
1680 value_type ptr = newElem.release();
1682 this->moveAux (pos.base() - this->m_pCont.begin(), ptr);
1687 * @brief Erase all the elements in the collection, and reset
1688 * the ownership mode.
1689 * @param ownPolicy The new ownership policy of the container.
1691 * If the container owns its elements, then the removed elements
1692 * will be deleted. Any duplicates will be removed in this process,
1693 * but don't rely on this.
1695 template <class T, class BASE>
1696 void DataVector<T, BASE>::clear (SG::OwnershipPolicy ownPolicy)
1699 this->m_ownPolicy = ownPolicy;
1700 this->template initAuxVectorBase<DataVector> (ownPolicy,
1701 SG::DEFAULT_TRACK_INDICES);
1706 * @brief Erase all the elements in the collection, and reset
1707 * the ownership mode.
1708 * @param ownPolicy The new ownership policy of the container.
1709 * @param trackIndices The index tracking policy.
1711 * If the container owns its elements, then the removed elements
1712 * will be deleted. Any duplicates will be removed in this process,
1713 * but don't rely on this.
1715 template <class T, class BASE>
1716 void DataVector<T, BASE>::clear (SG::OwnershipPolicy ownPolicy,
1717 SG::IndexTrackingPolicy trackIndices)
1720 this->m_ownPolicy = ownPolicy;
1721 this->template initAuxVectorBase<DataVector> (ownPolicy, trackIndices);
1726 * @brief Return the DV/DL info struct for this class.
1728 * This can be used to make sure that it's instantiated.
1730 template <class T, class BASE>
1731 const DataModel_detail::DVLInfoBase& DataVector<T, BASE>::dvlinfo()
1733 static const DataModel_detail::DVLInfo<DataVector<T, BASE> > info;
1739 * @brief Erase all the elements in the collection, and change
1740 * how elements are to be deleted.
1741 * @param deleter Object to be used to delete object.
1742 * Passing nullptr will change back to the default.
1744 * If the container owns its elements, then the removed elements
1745 * will be deleted. Any duplicates will be removed in this process,
1746 * but don't rely on this.
1747 * After the current elements are deleted, the Deleter object is changed.
1749 template <class T, class BASE>
1750 void DataVector<T, BASE>::clear (std::unique_ptr<Deleter> deleter)
1753 delete this->m_deleter;
1754 this->m_deleter = deleter.release();
1759 * @brief Return the DV/DL info struct for this class.
1761 * This can be used to make sure that it's instantiated.
1763 template <class T, class BASE>
1764 const DataModel_detail::DVLInfoBase& DataVector<T, BASE>::dvlinfo_v() const
1766 return DataVector<T, BASE>::dvlinfo();
1771 * @brief Return the offset of a base @c DataVector class.
1772 * @param ti @c std::type_info of the desired class.
1774 * If @c ti represents a @c DataVector base class of this one,
1775 * then return the offset of that base class. Otherwise, return -1.
1777 * This function is here due to limitations of root 6, which can't
1778 * calculate these offsets correctly from the dictionary if
1779 * virtual derivation is used.
1781 template <class T, class BASE>
1782 int DataVector<T, BASE>::baseOffset (const std::type_info& ti)
1785 return baseOffset1 (reinterpret_cast<const char*>(&dv), dv, ti);
1790 * @brief Convert to @c AuxVectorBase.
1792 * Needed to get @x AuxVectorBase from a @c ConstDataVector.
1793 * Present in @c DataVector as well for consistency.
1794 * We only really need it in the base class; however, root6 fails
1795 * constructing a @c TMethodCall for this if there is virtual
1796 * derivation. A workaround is to redeclare this in the derived
1799 template <class T, class BASE>
1800 const SG::AuxVectorBase& DataVector<T, BASE>::auxbase() const
1806 //=== Internal operations.
1810 * @brief Helper for @c baseOffset.
1811 * @param p Pointer to the start of the top-level object.
1812 * @param dv Reference to the DataVector object.
1813 * @param ti @c std::type_info of the desired class.
1815 * If @c ti represents a @c DataVector base class of this one,
1816 * then return the offset of that base class. Otherwise, return -1.
1819 template <class T, class BASE>
1820 int DataVector<T, BASE>::baseOffset1 (const char* p, const DataVector& dv,
1821 const std::type_info& ti)
1823 if (typeid(DataVector) == ti)
1824 return reinterpret_cast<const char*>(&dv) - p;
1825 return BASE::baseOffset1 (p, dv, ti);
1830 * @brief Reset indices / reorder aux data after elements have been permuted.
1831 * @param beg Start of the range of elements to process.
1832 * @param end End of the range of elements to process.
1834 * Call this after some operation that has permuted the elements in the
1835 * container (such as sort). The index information in the elements
1836 * will be used to permute all auxiliary data in the same way.
1837 * Finally, all the indices will be reset in the correct order.
1839 template <class T, class BASE>
1840 void DataVector<T, BASE>::resortAux (iterator beg, iterator end)
1842 if (typename SG::AuxStore_traits<DataVector>::flag() &&
1843 beg >= this->begin() && end <= this->end())
1845 SG::AuxVectorBase::resortAux (beg-begin(), beg, end);
1851 * @brief Test if we can insert; raise an exception if not.
1852 * @param op Description of the attempted operation.
1854 * In order to maintain type-safety, we can only allow insertions
1855 * using the most-derived instance of @c DataVector. This checks
1856 * this by testing the @c m_isMostDerived, which is set by the constructors
1857 * to true only for the most-derived instance.
1858 * If the test fails, we call to potentially out-of-line code to continue.
1860 template <class T, class BASE>
1862 void DataVector<T, BASE>::testInsert (const char* op)
1864 if (ATHCONTAINERS_LIKELY (m_isMostDerived))
1866 this->testInsertOol (op);
1871 * @brief Test if we can insert; raise an exception if not.
1872 * @param op Description of the attempted operation.
1874 * This continues the test of @c testInsert. There is one case
1875 * where @c m_isMostDerived may not be set correctly. If this container
1876 * was made via copy construction, then all the @c m_isMostDerived flags
1877 * will be false. So we call @c setMostDerived to set the flags correctly
1878 * and test again. If the test fails again, then we raise an exception.
1880 template <class T, class BASE>
1881 void DataVector<T, BASE>::testInsertOol (const char* op)
1883 this->setMostDerived();
1884 if (!m_isMostDerived)
1885 throw SG::ExcInsertionInBaseClass (op, typeid(DataVector), dv_typeid());
1890 * @brief Handle element assignment.
1891 * @param pos Position in the container to assign.
1892 * @param newElem The new element to assign.
1894 * The old element is freed if this container owns elements.
1895 * Auxiliary data are copied if appropriate.
1897 template <class T, class BASE>
1898 void DataVector<T, BASE>::assignElement (typename BaseContainer::iterator pos,
1901 testInsert ("assignElement");
1902 if (this->m_ownPolicy == SG::OWN_ELEMENTS)
1903 this->doDelete (*pos);
1905 this->clearIndex (iterator (pos, this));
1907 this->moveAux (pos - this->m_pCont.begin(), newElem);
1912 * @brief Handle element assignment.
1913 * @param pos Position in the container to assign.
1914 * @param newElem The new element to assign.
1916 * The container must own its elements.
1917 * Auxiliary data are copied if appropriate.
1919 template <class T, class BASE>
1921 DataVector<T, BASE>::assignElement (typename BaseContainer::iterator pos,
1922 std::unique_ptr<base_value_type> newElem)
1924 // Container must own its elements.
1925 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
1926 SG::throwExcNonowningContainer();
1928 testInsert ("assignElement");
1929 this->doDelete (*pos);
1930 value_type ptr = newElem.release();
1932 this->moveAux (pos - this->m_pCont.begin(), ptr);
1937 * @brief Handle element assignment from a base pointer.
1938 * @param pos Position in the container to assign.
1939 * @param newElem The new element to assign.
1941 * The old element is freed if this container owns elements.
1942 * Auxiliary data are copied if appropriate.
1944 template <class T, class BASE>
1946 DataVector<T, BASE>::assignBaseElement (typename BaseContainer::iterator pos,
1947 typename BaseContainer::value_type newElem)
1949 testInsert ("assignBaseElement");
1950 if (this->m_ownPolicy == SG::OWN_ELEMENTS)
1951 this->doDelete (*pos);
1953 this->clearIndex (iterator (pos, this));
1955 if (typename SG::AuxStore_traits<DataVector>::flag())
1956 this->moveAux (pos - this->m_pCont.begin(),
1957 DataModel_detail::DVLCast<DataVector>::cast(newElem));
1962 * @brief Shift the auxiliary elements of the container.
1963 * @param pos The starting index for the shift.
1964 * @param offs The (signed) amount of the shift.
1966 * The elements in the container should have already been shifted;
1967 * this operation will then adjust the element indices and also shift
1968 * the elements in the vectors for all aux data items.
1969 * @c offs may be either positive or negative.
1971 * If @c offs is positive, then the container is growing.
1972 * The container size should be increased by @c offs,
1973 * the element at @c pos moved to @c pos + @c offs,
1974 * and similarly for following elements.
1975 * The elements between @c pos and @c pos + @c offs should
1976 * be default-initialized.
1978 * If @c offs is negative, then the container is shrinking.
1979 * The element at @c pos should be moved to @c pos + @c offs,
1980 * and similarly for following elements.
1981 * The container should then be shrunk by @c -offs elements
1982 * (running destructors as appropriate).
1984 template <class T, class BASE>
1985 void DataVector<T, BASE>::shift (size_t pos, ptrdiff_t offs)
1987 SG::AuxVectorBase::shift (*this, pos, offs);
1992 * @brief Helper to shorten calls to @c DataVector_detail::DVLCast.
1993 * @param p The value to convert.
1994 * @return The value as a @c const @c T*.
1996 * The conversion will be done with @c static_cast if possible,
1997 * with @c dynamic_cast otherwise.
1999 template <class T, class BASE>
2002 DataVector<T, BASE>::do_cast (const typename PtrVector::value_type p)
2004 return DataModel_detail::DVLCast<DataVector>::cast (p);
2009 * @brief Helper to shorten calls to @c DataVector_detail::DVLCast.
2010 * @param p The value to convert.
2011 * @return The value as a @c T*.
2013 * The conversion will be done with @c static_cast if possible,
2014 * with @c dynamic_cast otherwise.
2016 template <class T, class BASE>
2019 DataVector<T, BASE>::do_cast_nc (typename PtrVector::value_type p)
2021 return DataModel_detail::DVLCast<DataVector>::cast (p);
2026 * @brief Find the most-derived @c DataVector class in the hierarchy.
2027 * @return The @c type_info for the class for which this method gets run.
2029 * This is used to generate a nice error message when the most-derived
2030 * check for insertions fails.
2031 * Every @c DataVector defines this virtual method, so when it's
2032 * called, the one corresponding to the most-derived @c DataVector
2035 template <class T, class BASE>
2036 const std::type_info& DataVector<T, BASE>::dv_typeid() const
2038 return typeid(DataVector);
2043 * @brief Clear @c m_isMostDerived for this instance and for all bases.
2045 * Called from the constructor after setting @c m_isMostDerived.
2047 template <class T, class BASE>
2049 void DataVector<T, BASE>::clearMostDerived()
2051 this->m_isMostDerived = false;
2052 BASE::clearMostDerived();
2057 * @brief Set @c m_isMostDerived for this instance and clear it for all bases.
2059 * Called from @c testInsert if the test fails. The flag may not have
2060 * been set if this container was made via copy construction, so set
2061 * it appropriately now so we can test again.
2063 template <class T, class BASE>
2064 void DataVector<T, BASE>::setMostDerived()
2066 m_isMostDerived = true;
2067 BASE::clearMostDerived();
2071 //****************************************************************************
2072 // Specialized (base) DataVector implementation.
2076 // An abbreviation for the DataVector specialization to try to make
2077 // things a little more readable.
2078 #define DATAVECTOR DataVector<T, DataModel_detail::NoBase>
2081 //=== Constructors, destructors, assignment.
2084 * @brief Default constructor.
2085 * @param ownPolicy The ownership mode for the container.
2086 * @param trackIndices The index tracking policy.
2088 * By default, a @c DataVector will own its elements.
2089 * To avoid this, pass @c SG::VIEW_ELEMENTS for @a ownPolicy.
2093 DATAVECTOR::DataVector
2094 (SG::OwnershipPolicy ownPolicy /*= SG::OWN_ELEMENTS*/,
2095 SG::IndexTrackingPolicy trackIndices /*=SG::DEFAULT_TRACK_INDICES*/)
2096 : m_ownPolicy(ownPolicy)
2098 this->template initAuxVectorBase<DataVector> (ownPolicy, trackIndices);
2099 this->m_isMostDerived = true;
2104 * @brief Sized constructor.
2105 * @param n The size of the container.
2106 * @param ownPolicy The ownership mode for the container.
2107 * @param trackIndices The index tracking policy.
2109 * Note that unlike the standard vector constructor, you can't specify
2110 * an initial value here. The container will be initialized with 0's.
2112 * By default, a @c DataVector will own its elements.
2113 * To avoid this, pass @c SG::VIEW_ELEMENTS for @a ownPolicy.
2117 DATAVECTOR::DataVector
2119 SG::OwnershipPolicy ownPolicy /*= SG::OWN_ELEMENTS*/,
2120 SG::IndexTrackingPolicy trackIndices /*= SG::DEFAULT_TRACK_INDICES*/)
2121 : m_ownPolicy(ownPolicy),
2124 this->template initAuxVectorBase<DataVector> (ownPolicy, trackIndices);
2125 this->m_isMostDerived = true;
2130 * @brief Copy constructor.
2131 * @param rhs The container from which to copy.
2133 * This is a `shallow' copy; the new container will not own its elements.
2137 DATAVECTOR::DataVector(const DataVector& rhs)
2139 m_ownPolicy(SG::VIEW_ELEMENTS),
2140 m_pCont(rhs.m_pCont)
2142 this->template initAuxVectorBase<DataVector> (m_ownPolicy,
2143 SG::DEFAULT_TRACK_INDICES);
2144 // Leave m_isMostDerived false here, because we may be being called
2145 // from a derived class implicit copy constructor. The flags will get
2146 // set correctly when @c testInsert gets called.
2151 * @brief Move constructor.
2152 * @param rhs The container from which to move.
2154 * Any auxiliary data will be moved along with the container contents.
2158 DATAVECTOR::DataVector(DataVector&& rhs) noexcept
2159 : AuxVectorBase (std::move (rhs)),
2160 m_ownPolicy(rhs.m_ownPolicy),
2161 m_pCont(std::move (rhs.m_pCont))
2163 m_deleter = std::move(rhs.m_deleter);
2164 rhs.m_deleter = nullptr;
2166 // Need to reset the container pointer on elements.
2167 this->setIndices (this->begin(), this->end());
2169 // This doesn't get called from derived classes.
2170 // Go ahead and set this flag now.
2171 m_isMostDerived = true;
2176 * @brief Constructor from iterators.
2177 * @param first The start of the range to put in the new container.
2178 * @param last The end of the range to put in the new container.
2179 * @param ownPolicy The ownership mode for the container.
2180 * @param trackIndices The index tracking policy.
2181 * @param store An associated auxiliary data store.
2183 * By default, a view container is made, which does not own its elements.
2184 * To have the container take ownership of the pointers passed
2185 * to this constructor, pass @c SG::OWN_ELEMENTS for @a ownPolicy.
2188 template <class InputIterator>
2190 DATAVECTOR::DataVector
2191 (InputIterator first,
2193 SG::OwnershipPolicy ownPolicy /*= SG::VIEW_ELEMENTS*/,
2194 SG::IndexTrackingPolicy trackIndices /*= SG::DEFAULT_TRACK_INDICES*/,
2195 SG::IAuxStore* store /*= 0*/)
2196 : m_ownPolicy(ownPolicy)
2198 this->template initAuxVectorBase<DataVector> (ownPolicy, trackIndices);
2199 this->m_isMostDerived = true;
2201 this->setStore (store);
2202 insert (this->begin(), first, last);
2207 * @brief Constructor from an initializer list.
2208 * @param l An initializer list.
2209 * @param last The end of the range to put in the new container.
2210 * @param ownPolicy The ownership mode for the container.
2211 * @param trackIndices The index tracking policy.
2212 * @param store An associated auxiliary data store.
2215 * A @c DataVector constructed this way will *not* own its elements
2216 * by default. To change this, pass @c SG::OWN_ELEMENTS for @a ownPolicy.
2220 DATAVECTOR::DataVector
2221 (std::initializer_list<value_type> l,
2222 SG::OwnershipPolicy ownPolicy /*= SG::VIEW_ELEMENTS*/,
2223 SG::IndexTrackingPolicy trackIndices /*= SG::DEFAULT_TRACK_INDICES*/,
2224 SG::IAuxStore* store /*= 0*/)
2225 : DataVector (l.begin(), l.end(), ownPolicy, trackIndices, store)
2231 * @brief Assignment operator.
2232 * @param rhs The DataVector from which to assign.
2233 * @return This object.
2235 * This is a `shallow' copy; after the completion of this, the @c DataVector
2236 * will not own its elements. Any elements it owned prior to this call
2239 * Note: this method may only be called using the most derived
2240 * @c DataVector in the hierarchy.
2244 DATAVECTOR& DATAVECTOR::operator= (const DataVector& rhs)
2247 // Ensure we're not being called via a base class.
2248 testInsert ("assignment operator");
2249 clear(); // Release any currently-owned elements.
2250 m_ownPolicy = SG::VIEW_ELEMENTS;
2251 this->setStore ((SG::IConstAuxStore*)0);
2252 this->template initAuxVectorBase<DataVector> (m_ownPolicy,
2253 SG::DEFAULT_TRACK_INDICES);
2254 m_pCont = rhs.m_pCont;
2261 * @brief Move assignment.
2262 * @param rhs The container from which to move.
2264 * Any auxiliary data will be moved along with the container contents.
2267 DATAVECTOR& DATAVECTOR::operator= (DATAVECTOR&& rhs) noexcept
2270 // Ensure we're not being called via a base class.
2271 testInsert ("assignment operator");
2273 this->clear(); // Release any currently-owned elements.
2275 SG::AuxVectorBase::operator= (std::move (rhs));
2276 this->m_ownPolicy = rhs.m_ownPolicy;
2277 this->m_pCont = std::move (rhs.m_pCont);
2279 delete this->m_deleter;
2280 this->m_deleter = std::move(rhs.m_deleter);
2281 rhs.m_deleter = nullptr;
2283 // Need to reset the container pointer on elements.
2284 this->setIndices (this->begin(), this->end());
2291 * @brief Assignment operator, from an initializer list.
2292 * @param l An initializer list.
2293 * @return This object.
2295 * This is equivalent to @c assign.
2296 * Any existing owned elements will be released.
2297 * The @c DataVector's ownership policy determines whether it will take
2298 * ownership of the new elements.
2302 DATAVECTOR& DATAVECTOR::operator= (std::initializer_list<value_type> l)
2304 this->assign (l.begin(), l.end());
2310 * @brief Assign from iterators.
2311 * @param first The start of the range to put in the container.
2312 * @param last The end of the range to put in the container.
2314 * Any existing owned elements will be released.
2315 * The @c DataVector's ownership policy determines whether it will take
2316 * ownership of the new elements.
2319 template <class InputIterator>
2320 void DATAVECTOR::assign (InputIterator first,
2323 // Ensure we're not being called via a base class.
2324 testInsert ("assign");
2325 clear(); // Release any currently-owned elements.
2326 insert(begin(), first, last);
2331 * @brief Assign from an initializer list.
2332 * @param l An initializer list.
2334 * Any existing owned elements will be released.
2335 * The @c DataVector's ownership policy determines whether it will take
2336 * ownership of the new elements.
2339 void DATAVECTOR::assign (std::initializer_list<value_type> l)
2341 this->assign (l.begin(), l.end());
2346 * @brief Destructor.
2348 * If this container owns its elements, the contained elements will
2349 * be deleted as well. Before doing this, the destructor will scan
2350 * for duplicate pointers (takes @f$n \log n@f$ time); duplicates are only
2351 * destroyed once. Duplicates should, however, be considered an error;
2352 * don't rely on this behavior.
2355 DATAVECTOR::~DataVector()
2357 if (m_ownPolicy == SG::OWN_ELEMENTS) {
2358 typename PtrVector::iterator new_end =
2359 DataVector_detail::remove_duplicates(m_pCont.begin(), m_pCont.end());
2360 this->doDelete (m_pCont.begin(), new_end);
2366 //=== Size and capacity.
2370 * @brief Returns the number of elements in the collection.
2374 typename DATAVECTOR::size_type DATAVECTOR::size() const noexcept
2376 return m_pCont.size();
2381 * @brief Returns the number of elements in the collection.
2383 * This version is virtual, to be callable from the AuxData
2388 typename DATAVECTOR::size_type DATAVECTOR::size_v() const
2390 return this->size();
2395 * @brief Returns the @c size() of the largest possible collection.
2399 typename DATAVECTOR::size_type DATAVECTOR::max_size() const noexcept
2401 return m_pCont.max_size();
2406 * @brief Resizes the collection to the specified number of elements.
2407 * @param sz The new size of the collection.
2409 * Note that this function differs from the standard in that it does
2410 * not allow specifying the value of any inserted elements.
2411 * They will always be 0.
2413 * If the container is shrunk, elements will be deleted as with @c erase().
2416 void DATAVECTOR::resize(size_type sz)
2418 if (sz < this->size()) {
2419 this->erase (this->begin()+sz, this->end());
2421 this->m_pCont.insert(this->m_pCont.end(), sz - this->m_pCont.size(), 0);
2422 SG::AuxVectorBase::resize<DataVector> (sz);
2428 * @brief Returns the total number of elements that the collection can hold
2429 * before needing to allocate more memory.
2433 typename DATAVECTOR::size_type DATAVECTOR::capacity() const noexcept
2435 return m_pCont.capacity();
2440 * @brief Returns the total number of elements that the collection can hold
2441 * before needing to allocate more memory.
2443 * This version is virtual, to be callable from the AuxData
2448 typename DATAVECTOR::size_type DATAVECTOR::capacity_v() const
2455 * @brief Returns @c true if the collection is empty.
2459 bool DATAVECTOR::empty() const noexcept
2461 return m_pCont.empty();
2466 * @brief Attempt to preallocate enough memory for a specified number
2468 * @param n Number of elements required.
2472 void DATAVECTOR::reserve (size_type n)
2474 m_pCont.reserve (n);
2475 SG::AuxVectorBase::reserve<DataVector> (n);
2480 * @brief Change the vector capacity to match the current size.
2482 * Note: this does not affect auxiliary data.
2486 void DATAVECTOR::shrink_to_fit()
2488 m_pCont.shrink_to_fit();
2492 //=== Element access.
2496 * @brief Access an element, as an rvalue.
2497 * @param n Array index to access.
2498 * @return The element at @a n.
2500 * No bounds checking is done.
2501 * Note that we return a @c const @c T* rather than a reference.
2505 const T* DATAVECTOR::operator[] (size_type n) const
2512 * @brief Access an element, as an rvalue.
2513 * @param n Array index to access.
2514 * @return The element at @a n.
2516 * This is a synonym for operator[] const, to be used when calling from root
2517 * (where we can't readily call just the const version of a method).
2521 const T* DATAVECTOR::get (size_type n) const
2523 return do_cast(this->m_pCont[n]);
2528 * @brief Access an element, as an lvalue.
2529 * @param n Array index to access.
2530 * @return Proxy to the element at @a n.
2532 * No bounds checking is done.
2533 * Note that we return a proxy object rather than a reference;
2534 * the proxy will handle deleting an owned element if it's assigned to.
2538 typename DATAVECTOR::ElementProxy DATAVECTOR::operator[] (size_type n)
2540 return ElementProxy (m_pCont.begin() + n, this);
2545 * @brief Access an element, as an rvalue.
2546 * @param n Array index to access.
2547 * @return The element at @a n.
2549 * Will raise @c std::out_of_range if the index is out-of-bounds.
2550 * Note that we return a @c const @c T* rather than a reference.
2554 const T* DATAVECTOR::at (size_type n) const
2556 return m_pCont.at(n);
2561 * @brief Access an element, as an lvalue.
2562 * @param n Array index to access.
2563 * @return Proxy to the element at @a n.
2565 * Will raise @c std::out_of_range if the index is out-of-bounds.
2566 * Note that we return a proxy object rather than a reference;
2567 * the proxy will handle deleting an owned element if it's assigned to.
2571 typename DATAVECTOR::ElementProxy DATAVECTOR::at (size_type n)
2573 // Can't use m_pCont's at here, because we need an iterator.
2574 // So we have to do the bounds check ourselves.
2576 throw std::out_of_range ("DataVector::at range check");
2577 return ElementProxy (m_pCont.begin() + n, this);
2582 * @brief Access the first element in the collection as an rvalue.
2583 * @return The first element in the collection.
2585 * No checking is done to ensure that the container is not empty.
2586 * Note that we return a @c const @c T* rather than a reference.
2590 const T* DATAVECTOR::front() const
2592 return m_pCont.front();
2597 * @brief Access the last element in the collection as an rvalue.
2598 * @return The last element in the collection.
2600 * No checking is done to ensure that the container is not empty.
2601 * Note that we return a @c const @c T* rather than a reference.
2605 const T* DATAVECTOR::back() const
2607 return m_pCont.back();
2612 * @brief Access the first element in the collection as an lvalue.
2613 * @return Proxy to the first element in the collection.
2615 * No checking is done to ensure that the container is not empty.
2616 * Note that we return a proxy object rather than a reference;
2617 * the proxy will handle deleting an owned element if it's assigned to.
2621 typename DATAVECTOR::ElementProxy DATAVECTOR::front ()
2623 return ElementProxy (m_pCont.begin(), this);
2628 * @brief Access the last element in the collection as an lvalue.
2629 * @return Proxy to the last element in the collection.
2631 * No checking is done to ensure that the container is not empty.
2632 * Note that we return a proxy object rather than a reference;
2633 * the proxy will handle deleting an owned element if it's assigned to.
2637 typename DATAVECTOR::ElementProxy DATAVECTOR::back ()
2639 return ElementProxy (m_pCont.end()-1, this);
2643 //=== Iterator creation.
2647 * @brief Return a @c const_iterator pointing at the beginning
2648 * of the collection.
2649 * @return A @c const_iterator.
2651 * Note that dereferencing the iterator will yield a @c const @c T* rather
2656 typename DATAVECTOR::const_iterator DATAVECTOR::begin() const noexcept
2658 return m_pCont.begin();
2663 * @brief Return a @c const_iterator pointing past the end
2664 * of the collection.
2665 * @return A @c const_iterator.
2667 * Note that dereferencing the iterator will yield a @c const @c T* rather
2672 typename DATAVECTOR::const_iterator DATAVECTOR::end() const noexcept
2674 return m_pCont.end();
2679 * @brief Return an @c iterator pointing at the beginning
2680 * of the collection.
2681 * @return An @c iterator.
2683 * Note that dereferencing the iterator will yield a proxy rather
2684 * than a reference; the proxy will handle deleting an owned element
2685 * if it's assigned to.
2689 typename DATAVECTOR::iterator DATAVECTOR::begin() noexcept
2691 return iterator (m_pCont.begin(), this);
2696 * @brief Return an @c iterator pointing past the end
2697 * of the collection.
2698 * @return An @c iterator.
2700 * Note that dereferencing the iterator will yield a proxy rather
2701 * than a reference; the proxy will handle deleting an owned element
2702 * if it's assigned to.
2706 typename DATAVECTOR::iterator DATAVECTOR::end() noexcept
2708 return iterator (m_pCont.end(), this);
2713 * @brief Return a @c const_reverse_iterator pointing past the end
2714 * of the collection.
2715 * @return A @c const_reverse_iterator.
2717 * Note that dereferencing the iterator will yield a @c const @c T* rather
2722 typename DATAVECTOR::const_reverse_iterator DATAVECTOR::rbegin() const noexcept
2724 return const_reverse_iterator (m_pCont.end());
2729 * @brief Return a @c const_reverse_iterator pointing at the beginning
2730 * of the collection.
2731 * @return A @c const_reverse_iterator.
2733 * Note that dereferencing the iterator will yield a @c const @c T* rather
2738 typename DATAVECTOR::const_reverse_iterator DATAVECTOR::rend() const noexcept
2740 return const_reverse_iterator (const_iterator (m_pCont.begin()));
2745 * @brief Return a @c reverse_iterator pointing past the end
2746 * of the collection.
2747 * @return A @c reverse_iterator.
2749 * Note that dereferencing the iterator will yield a proxy rather
2750 * than a reference; the proxy will handle deleting an owned element
2751 * if it's assigned to.
2755 typename DATAVECTOR::reverse_iterator DATAVECTOR::rbegin() noexcept
2757 return reverse_iterator(iterator (m_pCont.end(), this));
2762 * @brief Return a @c reverse_iterator pointing at the beginning
2763 * of the collection.
2764 * @return A @c reverse_iterator.
2766 * Note that dereferencing the iterator will yield a proxy rather
2767 * than a reference; the proxy will handle deleting an owned element
2768 * if it's assigned to.
2772 typename DATAVECTOR::reverse_iterator DATAVECTOR::rend() noexcept
2774 return reverse_iterator(iterator (m_pCont.begin(), this));
2779 * @brief Return a @c const_iterator pointing at the beginning
2780 * of the collection.
2781 * @return A @c const_iterator.
2783 * Note that dereferencing the iterator will yield a @c const @c T* rather
2788 typename DATAVECTOR::const_iterator DATAVECTOR::cbegin() const noexcept
2790 return m_pCont.begin();
2795 * @brief Return a @c const_iterator pointing past the end
2796 * of the collection.
2797 * @return A @c const_iterator.
2799 * Note that dereferencing the iterator will yield a @c const @c T* rather
2804 typename DATAVECTOR::const_iterator DATAVECTOR::cend() const noexcept
2806 return m_pCont.end();
2811 * @brief Return a @c const_reverse_iterator pointing past the end
2812 * of the collection.
2813 * @return A @c const_reverse_iterator.
2815 * Note that dereferencing the iterator will yield a @c const @c T* rather
2820 typename DATAVECTOR::const_reverse_iterator DATAVECTOR::crbegin() const noexcept
2822 return const_reverse_iterator (m_pCont.end());
2827 * @brief Return a @c const_reverse_iterator pointing at the beginning
2828 * of the collection.
2829 * @return A @c const_reverse_iterator.
2831 * Note that dereferencing the iterator will yield a @c const @c T* rather
2836 typename DATAVECTOR::const_reverse_iterator DATAVECTOR::crend() const noexcept
2838 return const_reverse_iterator (const_iterator (m_pCont.begin()));
2842 //=== Insertion operations.
2846 * @brief Add an element to the end of the collection.
2847 * @param pElem The element to add to the collection.
2849 * The container's ownership policy will determine if it takes ownership
2850 * of the new element.
2852 * Note: this method may only be called using the most derived
2853 * @c DataVector in the hierarchy.
2855 * Returns the pushed pointer.
2859 typename DATAVECTOR::value_type
2860 DATAVECTOR::push_back(value_type pElem)
2862 // Ensure we're not being called via a base class.
2863 testInsert ("push_back");
2864 m_pCont.push_back(pElem);
2865 SG::AuxVectorBase::resize<DataVector> (this->size());
2867 this->moveAux (this->size()-1, pElem, false, true);
2873 * @brief Add an element to the end of the collection.
2874 * @param pElem The element to add to the collection.
2876 * The container must be an owning container.
2878 * Note: this method may only be called using the most derived
2879 * @c DataVector in the hierarchy.
2881 * Returns the pushed pointer.
2885 typename DATAVECTOR::value_type
2886 DATAVECTOR::push_back(std::unique_ptr<base_value_type> pElem)
2888 // Container must own its elements.
2889 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
2890 SG::throwExcNonowningContainer();
2892 // Ensure we're not being called via a base class.
2893 testInsert ("push_back");
2894 value_type ptr = pElem.release();
2895 m_pCont.push_back(ptr);
2896 SG::AuxVectorBase::resize<DataVector> (this->size());
2898 this->moveAux (this->size()-1, ptr, false, true);
2904 * @brief Add an element to the end of the collection.
2905 * @param pElem The element to add to the collection.
2907 * The container's ownership policy will determine if it takes ownership
2908 * of the new element.
2910 * Note: this method may only be called using the most derived
2911 * @c DataVector in the hierarchy.
2913 * For @c DataVector, this is like the same as @c push_back, and
2914 * it returns the pushed element.
2915 * It's included just for interface compatibility with `std::vector`.
2919 typename DATAVECTOR::value_type
2920 DATAVECTOR::emplace_back(value_type pElem)
2922 return this->push_back (pElem);
2927 * @brief Add a new element to the collection.
2928 * @param position Iterator before which the element will be added.
2929 * @param pElem The element to add to the collection.
2930 * @return An iterator that points to the inserted data.
2932 * The container's ownership policy will determine if it takes ownership
2933 * of the new element.
2935 * Note: this method may only be called using the most derived
2936 * @c DataVector in the hierarchy.
2940 typename DATAVECTOR::iterator
2941 DATAVECTOR::insert(iterator position, value_type pElem)
2943 // Ensure we're not being called via a base class.
2944 testInsert ("insert");
2945 iterator ret (m_pCont.insert(position.base(), pElem), this);
2946 this->shift (ret - this->begin(), 1);
2947 this->moveAux (ret-this->begin(), pElem, false, true);
2953 * @brief Add a new element to the collection.
2954 * @param position Iterator before which the element will be added.
2955 * @param pElem The element to add to the collection.
2956 * @return An iterator that points to the inserted data.
2958 * The container must be an owning container.
2960 * Note: this method may only be called using the most derived
2961 * @c DataVector in the hierarchy.
2965 typename DATAVECTOR::iterator
2966 DATAVECTOR::insert(iterator position, std::unique_ptr<base_value_type> pElem)
2968 // Container must own its elements.
2969 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
2970 SG::throwExcNonowningContainer();
2972 // Ensure we're not being called via a base class.
2973 testInsert ("insert");
2974 value_type ptr = pElem.release();
2975 iterator ret (m_pCont.insert(position.base(), ptr), this);
2976 this->shift (ret - this->begin(), 1);
2977 this->moveAux (ret-this->begin(), ptr, false, true);
2983 * @brief Add a new element to the collection.
2984 * @param position Iterator before which the element will be added.
2985 * @param pElem The element to add to the collection.
2986 * @return An iterator that points to the inserted data.
2988 * The container's ownership policy will determine if it takes ownership
2989 * of the new element.
2991 * Note: this method may only be called using the most derived
2992 * @c DataVector in the hierarchy.
2994 * For @c DataVector, this is just the same as @c insert.
2995 * It's included just for interface compatibility with `std::vector`.
2999 typename DATAVECTOR::iterator
3000 DATAVECTOR::emplace(iterator position, value_type pElem)
3002 return this->insert (position, pElem);
3007 * @brief Add a group of new elements to the collection.
3008 * @param position Iterator before which the element will be added.
3009 * @param first The start of the range to put in the container.
3010 * @param last The end of the range to put in the container.
3012 * The container's ownership policy will determine if it takes ownership
3013 * of the new element.
3015 * Note: this method may only be called using the most derived
3016 * @c DataVector in the hierarchy.
3018 * This overload is for the case where the iterator value type
3019 * is convertible to T*.
3022 template <class InputIterator,
3023 DataVector_detail::enable_if_ptr_itr<InputIterator, T> >
3026 DATAVECTOR::insert (iterator position, InputIterator first, InputIterator last)
3028 static_assert (std::is_same_v<T*, typename DATAVECTOR::value_type>);
3029 // Ensure we're not being called via a base class.
3030 testInsert ("insert");
3031 size_t idx = position - this->begin();
3032 size_t old_sz = this->m_pCont.size();
3033 m_pCont.insert(position.base(), first, last);
3034 size_t n = this->m_pCont.size() - old_sz;
3035 this->shift (idx, n);
3036 this->moveAux (idx, first, last, false, true);
3041 * @brief Add a group of new elements to the collection.
3042 * @param position Iterator before which the element will be added.
3043 * @param first The start of the range to put in the container.
3044 * @param last The end of the range to put in the container.
3046 * The container's ownership policy will determine if it takes ownership
3047 * of the new element.
3049 * Note: this method may only be called using the most derived
3050 * @c DataVector in the hierarchy.
3052 * This overload is for the case where the iterator value type
3053 * is convertible to unique_ptr<T>.
3056 template <class InputIterator,
3057 DataVector_detail::enable_if_up_itr<InputIterator, T> >
3060 DATAVECTOR::insert (iterator position, InputIterator first, InputIterator last)
3062 // Ensure we're not being called via a base class.
3063 testInsert ("insert");
3064 size_t idx = position - this->begin();
3065 size_t old_sz = this->m_pCont.size();
3066 using CxxUtils::releasing_iterator;
3067 m_pCont.insert(position.base(), releasing_iterator(first), releasing_iterator(last));
3068 size_t n = this->m_pCont.size() - old_sz;
3069 this->shift (idx, n);
3070 this->moveAux (idx, this->begin()+idx, this->begin()+idx+n);
3075 * @brief Add a group of new elements to the collection.
3076 * @param position Iterator before which the element will be added.
3077 * @param l An initializer list.
3079 * The container's ownership policy will determine if it takes ownership
3080 * of the new element.
3082 * Note: this method may only be called using the most derived
3083 * @c DataVector in the hierarchy.
3088 DATAVECTOR::insert (iterator position, std::initializer_list<value_type> l)
3090 this->insert (position, l.begin(), l.end());
3095 * @brief Insert the contents of another @c DataVector,
3096 * with auxiliary data copied via move semantics.
3097 * @param position Iterator before which the new elements will be added.
3098 * @param other The vector to add.
3100 * The ownership mode of this vector must be the same as @c other;
3101 * otherwise, an exception will be thrown.
3103 * If both vectors are view vectors, then this is the same
3104 * as <code> insert (position, other.begin(), other.end()) </code>.
3106 * Otherwise, the elements from @c other will be inserted into this vector.
3107 * This vector will take ownership of the elements, and the ownership
3108 * mode of @c other will be changed to @c VIEW_ELEMENTS.
3109 * Auxiliary data for these elements will be transferred,
3110 * using move semantics if possible. (Thus, the auxiliary store
3111 * for @c other may be modified and must not be locked.)
3112 * Finally, the auxiliary store pointer for @c other will be cleared
3113 * (but the store itself will not be deleted since it's not owned
3116 * Note: this method may only be called using the most derived
3117 * @c DataVector in the hierarchy.
3121 DATAVECTOR::insertMove (iterator position, DataVector& other)
3123 if (this->m_ownPolicy != other.ownPolicy())
3124 throw SG::ExcInsertMoveOwnershipMismatch();
3126 if (this->m_ownPolicy == SG::VIEW_ELEMENTS) {
3127 this->insert (position, other.begin(), other.end());
3131 testInsert ("insertMove");
3132 size_t pos = position.base() - this->m_pCont.begin();
3133 this->m_pCont.insert (position.base(), other.begin(), other.end());
3134 this->setIndices (this->begin()+pos, this->end(), pos);
3135 other.m_ownPolicy = SG::VIEW_ELEMENTS;
3137 SG::IAuxStore* otherStore = other.getStore();
3139 SG::IAuxStore* store = this->getStore();
3141 if (!store->insertMove (pos, *otherStore))
3144 else if (this->hasStore())
3145 throw SG::ExcConstAuxData ("insertMove");
3146 other.setStore (static_cast<SG::IAuxStore*>(nullptr));
3148 else if (other.hasStore())
3149 throw SG::ExcConstAuxData ("insertMove");
3153 //=== Erasure operations.
3157 * @brief Remove element at a given position.
3158 * @param position Iterator pointing to the element to be removed.
3159 * @return An iterator pointing to the next element (or @c end()).
3161 * If the container owns its elements, then the pointed-to element
3166 typename DATAVECTOR::iterator DATAVECTOR::erase(iterator position)
3168 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
3169 this->clearIndex (position);
3170 iterator ret (this->erase_base (position.base()), this);
3171 this->shift (ret - this->begin() + 1, -1);
3177 * @brief Remove a range of elements.
3178 * @param first Iterator pointing to the first element to be removed.
3179 * @param last Iterator pointing one past the last element to be removed.
3180 * @return An iterator pointing to the element pointed to by @a last
3181 * prior to erasing (or @c end()).
3183 * If the container owns its elements, then the removed elements
3184 * will be deleted. Any duplicates will be removed in this process,
3185 * but don't rely on this.
3189 typename DATAVECTOR::iterator DATAVECTOR::erase(iterator first, iterator last)
3191 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
3192 this->clearIndices (first, last);
3193 iterator ret (this->erase_base (first.base(), last.base()), this);
3194 this->shift (ret - this->begin() + (last-first), -(last-first));
3200 * @brief Remove the last element from the collection.
3202 * If the container owns its elements, then the removed element
3206 void DATAVECTOR::pop_back()
3208 if (!m_pCont.empty()) {
3209 if (m_ownPolicy == SG::OWN_ELEMENTS)
3210 this->doDelete (m_pCont.back());
3212 this->clearIndex (m_pCont.end() - 1);
3214 SG::AuxVectorBase::resize<DataVector> (this->m_pCont.size());
3220 * @brief Erase all the elements in the collection.
3222 * If the container owns its elements, then the removed elements
3223 * will be deleted. Any duplicates will be removed in this process,
3224 * but don't rely on this.
3228 void DATAVECTOR::clear()
3230 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
3231 this->clearIndices (begin(), end());
3232 this->erase_base (m_pCont.begin(), m_pCont.end());
3233 SG::AuxVectorBase::resize<DataVector> (0);
3237 //=== Swap and sort.
3241 * @brief Swap this collection with another.
3242 * @param rhs The collection with which to swap.
3244 * Ownership is swapped along with the collection content.
3246 * Note: this method may only be called using the most-derived
3247 * @c DataVector in the hierarchy. The @a rhs must also be
3248 * referenced using the most-derived @c DataVector.
3250 * Warning: If this container has auxiliary data, then this
3251 * is an O(N) operation, not O(1).
3254 void DATAVECTOR::swap(DataVector& rhs)
3256 testInsert ("swap");
3257 rhs.testInsert ("swap");
3258 std::swap(m_ownPolicy, rhs.m_ownPolicy);
3259 SG::AuxVectorBase::swap (rhs);
3260 m_pCont.swap(rhs.m_pCont);
3261 std::swap (this->m_deleter, rhs.m_deleter);
3262 this->setIndices (this->begin(), this->end());
3263 rhs.setIndices (rhs.begin(), rhs.end());
3268 * @brief Swap the referents of two @c DataVector iterators.
3269 * @param a The first iterator for the swap.
3270 * @param b The second iterator for the swap.
3273 void DATAVECTOR::iter_swap (iterator a, iterator b)
3275 if (a.ownPolicy() != b.ownPolicy()) {
3276 throw SG::ExcBadIterSwap();
3278 a.testInsert ("iter_swap");
3279 b.testInsert ("iter_swap");
3280 std::iter_swap (a.base(), b.base());
3281 DataVector* acont = a.container();
3282 DataVector* bcont = b.container();
3283 if (typename SG::AuxStore_traits<DataVector>::flag())
3284 acont->swapElementsAux (a.base() - acont->stdcont().begin(),
3285 b.base() - bcont->stdcont().begin(),
3293 * @brief Sort the container.
3295 * This just sorts by pointer value, so it's probably not very useful.
3298 void DATAVECTOR::sort()
3300 std::sort(m_pCont.begin(), m_pCont.end());
3301 this->resortAux (this->begin(), this->end());
3306 * @brief Sort the container with a user-specified comparison operator.
3307 * @param comp Functional to compare two values.
3310 template <class COMPARE>
3311 void DATAVECTOR::sort(COMPARE comp)
3313 std::sort(m_pCont.begin(), m_pCont.end(), comp);
3314 this->resortAux (this->begin(), this->end());
3318 //=== Non-standard operations.
3322 * @brief Swap one element out of the container.
3323 * @param index Index of the element in the container to swap.
3324 * @param newElement New element to put in the container.
3326 * @param oldElem Reference to receive the element removed from the
3329 * Reference @a oldElem is initialized with element @a index of the
3330 * collection (no bounds checking). Then element @a index is set
3331 * to @newElem. If the collection owns its elements, then it will
3332 * take ownership of @a newElem and release (without deleting)
3333 * the element returned through @a oldElem.
3335 * Note: this method may only be called using the most derived
3336 * @c DataVector in the hierarchy.
3340 DATAVECTOR::swapElement (size_type index,
3344 testInsert ("swapElement");
3345 oldElem = m_pCont[index];
3346 this->clearIndex (iterator (m_pCont.begin() + index, this));
3347 m_pCont[index] = newElem;
3348 this->moveAux (index, newElem);
3353 * @brief Swap one element out of the container.
3354 * @param pos The element in the container to swap.
3355 * @param newElem New element to put in the container.
3357 * @param oldElem Reference to receive the element removed from the
3360 * Reference @a oldElem is initialized with element @a pos of the
3361 * collection (no bounds checking). Then element @a index is set
3362 * to @c newElem. If the collection owns its elements, then it will
3363 * take ownership of @a newElem and release (without deleting)
3364 * the element returned through @a oldElem.
3366 * Note: this method may only be called using the most derived
3367 * @c DataVector in the hierarchy.
3371 DATAVECTOR::swapElement (iterator pos,
3375 testInsert ("swapElement");
3376 oldElem = *pos.base();
3377 this->clearIndex (pos);
3378 *pos.base() = newElem;
3379 this->moveAux (pos.base() - this->m_pCont.begin(), newElem);
3384 * @brief Swap one element out of the container.
3385 * @param index Index of the element in the container to swap.
3386 * @param newElement New element to put in the container.
3388 * @param oldElem Reference to receive the element removed from the
3391 * Reference @a oldElem is initialized with element @a index of the
3392 * collection (no bounds checking). Then element @a index is set
3395 * The collection must own its elements to use its interface.
3396 * The collection will take ownership of @c newElem and will return
3397 * ownership of @c oldElem.
3399 * Note: this method may only be called using the most derived
3400 * @c DataVector in the hierarchy.
3404 DATAVECTOR::swapElement (size_type index,
3405 std::unique_ptr<base_value_type> newElem,
3406 std::unique_ptr<base_value_type>& oldElem)
3408 // Container must own its elements.
3409 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
3410 SG::throwExcNonowningContainer();
3412 testInsert ("swapElement");
3413 oldElem = std::unique_ptr<base_value_type> (m_pCont[index]);
3414 this->clearIndex (iterator (m_pCont.begin() + index, this));
3415 value_type ptr = newElem.release();
3416 m_pCont[index] = ptr;
3417 this->moveAux (index, ptr);
3422 * @brief Swap one element out of the container.
3423 * @param pos The element in the container to swap.
3424 * @param newElem New element to put in the container.
3426 * @param oldElem Reference to receive the element removed from the
3429 * Reference @a oldElem is initialized with element @a pos of the
3430 * collection (no bounds checking). Then element @a index is set
3433 * The collection must own its elements to use its interface.
3434 * The collection will take ownership of @c newElem and will return
3435 * ownership of @c oldElem.
3437 * Note: this method may only be called using the most derived
3438 * @c DataVector in the hierarchy.
3442 DATAVECTOR::swapElement (iterator pos,
3443 std::unique_ptr<base_value_type> newElem,
3444 std::unique_ptr<base_value_type>& oldElem)
3446 // Container must own its elements.
3447 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
3448 SG::throwExcNonowningContainer();
3450 testInsert ("swapElement");
3451 oldElem = std::unique_ptr<base_value_type> (*pos.base());
3452 this->clearIndex (pos);
3453 value_type ptr = newElem.release();
3455 this->moveAux (pos.base() - this->m_pCont.begin(), ptr);
3460 * @brief Return the underlying @c std::vector of the container.
3461 * @return Reference to the @c std::vector actually holding the collection.
3463 * Note that @c DataVector<T>::stdcont does not necessarily return
3464 * a @c std::vector<T*> if @c DataVector inheritance is being used.
3468 const typename DATAVECTOR::PtrVector& DATAVECTOR::stdcont() const
3475 * @brief Return the ownership policy setting for this container.
3479 SG::OwnershipPolicy DATAVECTOR::ownPolicy() const
3486 * @brief Erase all the elements in the collection, and reset
3487 * the ownership mode.
3488 * @param ownPolicy The new ownership policy of the container.
3489 * @param trackIndices The index tracking policy.
3491 * If the container owns its elements, then the removed elements
3492 * will be deleted. Any duplicates will be removed in this process,
3493 * but don't rely on this.
3496 void DATAVECTOR::clear (SG::OwnershipPolicy ownPolicy)
3499 m_ownPolicy = ownPolicy;
3500 this->template initAuxVectorBase<DataVector> (ownPolicy,
3501 SG::DEFAULT_TRACK_INDICES);
3506 * @brief Erase all the elements in the collection, and reset
3507 * the ownership mode.
3508 * @param ownPolicy The new ownership policy of the container.
3509 * @param trackIndices The index tracking policy.
3511 * If the container owns its elements, then the removed elements
3512 * will be deleted. Any duplicates will be removed in this process,
3513 * but don't rely on this.
3516 void DATAVECTOR::clear (SG::OwnershipPolicy ownPolicy,
3517 SG::IndexTrackingPolicy trackIndices)
3520 m_ownPolicy = ownPolicy;
3521 this->template initAuxVectorBase<DataVector> (ownPolicy, trackIndices);
3526 * @brief Return the DV/DL info struct for this class.
3528 * This can be used to make sure that it's instantiated.
3531 const DataModel_detail::DVLInfoBase& DATAVECTOR::dvlinfo()
3533 static const DataModel_detail::DVLInfo<DataVector<T, DataModel_detail::NoBase> > info;
3539 * @brief Erase all the elements in the collection, and change
3540 * how elements are to be deleted.
3541 * @param deleter Object to be used to delete object.
3542 * (The DataVector does not take ownership.)
3543 * Passing nullptr will change back to the default.
3545 * If the container owns its elements, then the removed elements
3546 * will be deleted. Any duplicates will be removed in this process,
3547 * but don't rely on this.
3548 * After the current elements are deleted, the Deleter object is changed.
3551 void DATAVECTOR::clear (std::unique_ptr<Deleter> deleter)
3554 delete this->m_deleter;
3555 this->m_deleter = deleter.release();
3560 * @brief Return the DV/DL info struct for this class.
3562 * This can be used to make sure that it's instantiated.
3565 const DataModel_detail::DVLInfoBase& DATAVECTOR::dvlinfo_v() const
3567 return DATAVECTOR::dvlinfo();
3572 * @brief Return the offset of a base @c DataVector class.
3573 * @param ti @c std::type_info of the desired class.
3575 * If @c ti represents a @c DataVector base class of this one,
3576 * then return the offset of that base class. Otherwise, return -1.
3578 * This function is here due to limitations of root 6, which can't
3579 * calculate these offsets correctly from the dictionary if
3580 * virtual derivation is used.
3583 int DATAVECTOR::baseOffset (const std::type_info& ti)
3585 if (typeid(DataVector) == ti)
3592 * @brief Convert to @c AuxVectorBase.
3594 * Needed to get @x AuxVectorBase from a @c ConstDataVector.
3595 * Present in @c DataVector as well for consistency.
3599 const SG::AuxVectorBase& DATAVECTOR::auxbase() const
3605 //=== Internal operations.
3609 * @brief Helper for @c baseOffset.
3610 * @param p Pointer to the start of the top-level object.
3611 * @param dv Reference to the DataVector object.
3612 * @param ti @c std::type_info of the desired class.
3614 * If @c ti represents a @c DataVector base class of this one,
3615 * then return the offset of that base class. Otherwise, return -1.
3619 int DATAVECTOR::baseOffset1 (const char* p, const DataVector& dv,
3620 const std::type_info& ti)
3622 if (typeid(DataVector) == ti)
3623 return reinterpret_cast<const char*>(&dv) - p;
3629 * @brief Reset indices / reorder aux data after elements have been permuted.
3630 * @param beg Start of the range of elements to process.
3631 * @param end End of the range of elements to process.
3633 * Call this after some operation that has permuted the elements in the
3634 * container (such as sort). The index information in the elements
3635 * will be used to permute all auxiliary data in the same way.
3636 * Finally, all the indices will be reset in the correct order.
3639 void DATAVECTOR::resortAux (iterator beg, iterator end)
3641 if (typename SG::AuxStore_traits<DataVector>::flag() &&
3642 beg >= this->begin() && end <= this->end())
3644 SG::AuxVectorBase::resortAux (beg-begin(), beg, end);
3650 * @brief Handle element assignment.
3651 * @param pos Position in the container to assign.
3652 * @param newElem The new element to assign.
3654 * The old element is freed if this container owns elements.
3655 * Auxiliary data are copied if appropriate.
3658 void DATAVECTOR::assignElement (typename BaseContainer::iterator pos,
3661 testInsert ("assignElement");
3662 if (this->m_ownPolicy == SG::OWN_ELEMENTS)
3663 this->doDelete (*pos);
3665 this->clearIndex (iterator (pos, this));
3667 this->moveAux (pos - this->m_pCont.begin(), newElem);
3672 * @brief Handle element assignment.
3673 * @param pos Position in the container to assign.
3674 * @param newElem The new element to assign.
3676 * The container must own its elements.
3677 * Auxiliary data are copied if appropriate.
3681 DATAVECTOR::assignElement (typename BaseContainer::iterator pos,
3682 std::unique_ptr<base_value_type> newElem)
3684 // Container must own its elements.
3685 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
3686 SG::throwExcNonowningContainer();
3688 testInsert ("assignElement");
3689 this->doDelete (*pos);
3690 value_type ptr = newElem.release();
3692 this->moveAux (pos - this->m_pCont.begin(), ptr);
3697 * @brief Handle element assignment from a base pointer.
3698 * @param pos Position in the container to assign.
3699 * @param newElem The new element to assign.
3701 * The old element is freed if this container owns elements.
3702 * Auxiliary data are copied if appropriate.
3705 void DATAVECTOR::assignBaseElement (typename BaseContainer::iterator pos,
3706 typename BaseContainer::value_type newElem)
3708 testInsert ("assignBaseElement");
3709 if (this->m_ownPolicy == SG::OWN_ELEMENTS)
3710 this->doDelete (*pos);
3712 this->clearIndex (iterator (pos, this));
3714 if (typename SG::AuxStore_traits<DataVector>::flag())
3715 this->moveAux (pos - this->m_pCont.begin(), newElem);
3720 * @brief Shift the auxiliary elements of the container.
3721 * @param pos The starting index for the shift.
3722 * @param offs The (signed) amount of the shift.
3724 * The elements in the container should have already been shifted;
3725 * this operation will then adjust the element indices and also shift
3726 * the elements in the vectors for all aux data items.
3727 * @c offs may be either positive or negative.
3729 * If @c offs is positive, then the container is growing.
3730 * The container size should be increased by @c offs,
3731 * the element at @c pos moved to @c pos + @c offs,
3732 * and similarly for following elements.
3733 * The elements between @c pos and @c pos + @c offs should
3734 * be default-initialized.
3736 * If @c offs is negative, then the container is shrinking.
3737 * The element at @c pos should be moved to @c pos + @c offs,
3738 * and similarly for following elements.
3739 * The container should then be shrunk by @c -offs elements
3740 * (running destructors as appropriate).
3743 void DATAVECTOR::shift (size_t pos, ptrdiff_t offs)
3745 SG::AuxVectorBase::shift (*this, pos, offs);
3750 * @brief Helper to shorten calls to @c DataModel_detail::DVLCast.
3751 * @param p The value to convert.
3752 * @return The value as a @c const @c T*.
3754 * This is a no-op for the base class.
3758 const T* DATAVECTOR::do_cast (const typename PtrVector::value_type p)
3765 * @brief Helper to shorten calls to @c DataModel_detail::DVLCast.
3766 * @param p The value to convert.
3767 * @return The value as a @c T*.
3769 * This is a no-op for the base class.
3773 T* DATAVECTOR::do_cast_nc (typename PtrVector::value_type p)
3780 * @brief Find the most-derived @c DataVector class in the hierarchy.
3781 * @return The @c type_info for the class for which this method gets run.
3783 * This is used to generate a nice error message when the most-derived
3784 * check for insertions fails.
3785 * Every @c DataVector defines this virtual method, so when it's
3786 * called, the one corresponding to the most-derived @c DataVector
3790 const std::type_info& DATAVECTOR::dv_typeid() const
3792 return typeid(DataVector);
3797 * @brief Helper for @c erase(). Remove element at a given position.
3798 * @param position Iterator pointing to the element to be removed.
3799 * @return An iterator pointing to the next element (or @c end()).
3801 * This function factors out common code between @c erase() in the
3802 * base and derived @c DataVector classes. It deals with the
3803 * @c std::vector iterators directly.
3806 typename DATAVECTOR::PtrVector::iterator
3807 DATAVECTOR::erase_base(typename PtrVector::iterator position)
3809 if (m_ownPolicy == SG::OWN_ELEMENTS && position != m_pCont.end())
3810 this->doDelete (*position);
3811 return m_pCont.erase(position);
3816 * @brief Helper for @c erase(). Remove a range of elements.
3817 * @param first Iterator pointing to the first element to be removed.
3818 * @param last Iterator pointing one past the last element to be removed.
3819 * @return An iterator pointing to the element pointed to by @a last
3820 * prior to erasing (or @c end()).
3822 * This function factors out common code between @c erase() in the
3823 * base and derived @c DataVector classes. It deals with the
3824 * @c std::vector iterators directly.
3827 typename DATAVECTOR::PtrVector::iterator
3828 DATAVECTOR::erase_base(typename PtrVector::iterator first,
3829 typename PtrVector::iterator last)
3831 if (first == last) return first;
3832 if (m_ownPolicy == SG::OWN_ELEMENTS) {
3833 typename PtrVector::iterator new_end =
3834 DataVector_detail::remove_duplicates(first, last);
3835 this->doDelete (first, new_end);
3837 return m_pCont.erase(first, last);
3842 * @brief Delete an element
3843 * @param p The element to delete.
3847 void DATAVECTOR::doDelete (value_type p)
3850 m_deleter->doDelete (p);
3859 * @brief Delete a range of elements
3860 * @param first Start of range to delete.
3861 * @param last End of range to delete.
3865 void DATAVECTOR::doDelete (typename PtrVector::iterator first,
3866 typename PtrVector::iterator last)
3869 m_deleter->doDelete (first, last);
3872 for (; first != last; ++first) {
3880 * @brief Test if we can insert; raise an exception if not.
3881 * @param op Description of the attempted operation.
3883 * In order to maintain type-safety, we can only allow insertions
3884 * using the most-derived instance of @c DataVector. This checks
3885 * this by testing the @c m_isMostDerived, which is set by the constructors
3886 * to true only for the most-derived instance.
3887 * If the test fails, we call to potentially out-of-line code to continue.
3891 void DATAVECTOR::testInsert (const char* op)
3893 if (ATHCONTAINERS_LIKELY (m_isMostDerived))
3895 this->testInsertOol (op);
3900 * @brief Test if we can insert; raise an exception if not.
3901 * @param op Description of the attempted operation.
3903 * This continues the test of @c testInsert. There is one case
3904 * where @c m_isMostDerived may not be set correctly. If this container
3905 * was made via copy construction, then all the @c m_isMostDerived flags
3906 * will be false. So we call @c setMostDerived to set the flags correctly
3907 * and test again. If the test fails again, then we raise an exception.
3910 void DATAVECTOR::testInsertOol (const char* op)
3912 this->setMostDerived();
3913 if (!m_isMostDerived)
3914 throw SG::ExcInsertionInBaseClass (op, typeid(DataVector), dv_typeid());
3919 * @brief Clear @c m_isMostDerived for this instance and for all bases.
3921 * Called from the constructor after setting @c m_isMostDerived.
3925 void DATAVECTOR::clearMostDerived()
3927 this->m_isMostDerived = false;
3932 * @brief Set @c m_isMostDerived for this instance and clear it for all bases.
3934 * Called from @c testInsert if the test fails. The flag may not have
3935 * been set if this container was made via copy construction, so set
3936 * it appropriately now so we can test again.
3939 void DATAVECTOR::setMostDerived()
3941 m_isMostDerived = true;
3948 //****************************************************************************
3949 // Free function implementations.
3954 * @brief Vector equality comparison.
3955 * @param a A @c DataVector.
3956 * @param b A @c DataVector of the same type as @a b.
3957 * @return True iff the size and elements of the vectors are equal.
3959 * This is an equivalence relation. It is linear in the size of the
3960 * vectors. Vectors are considered equivalent if their sizes are equal,
3961 * and if corresponding elements compare equal.
3964 bool operator== (const DataVector<T>& a, const DataVector<T>& b)
3966 return a.stdcont() == b.stdcont();
3970 /// Based on operator==
3972 bool operator!= (const DataVector<T>& a, const DataVector<T>& b)
3974 return a.stdcont() != b.stdcont();
3979 * @brief Vector ordering relation.
3980 * @param a A @c DataVector.
3981 * @param b A @c DataVector of the same type as @a x.
3982 * @return True iff @a a is lexicographically less than @a b.
3984 * This is a total ordering relation. It is linear in the size of the
3985 * vectors. Comparisons are done on the pointer values of the elements.
3987 * See @c std::lexicographical_compare() for how the determination is made.
3990 bool operator< (const DataVector<T>& a, const DataVector<T>& b)
3992 return a.stdcont() < b.stdcont();
3996 /// Based on operator<
3998 bool operator> (const DataVector<T>& a, const DataVector<T>& b)
4000 return a.stdcont() > b.stdcont();
4004 /// Based on operator<
4006 bool operator<= (const DataVector<T>& a, const DataVector<T>& b)
4008 return a.stdcont() <= b.stdcont();
4012 /// Based on operator<
4014 bool operator>= (const DataVector<T>& a, const DataVector<T>& b)
4016 return a.stdcont() >= b.stdcont();
4020 /// See @c DataVector<T, BASE>::swap().
4022 void swap (DataVector<T>& a, DataVector<T>& b)
4029 * @brief Specialization of @c ClassName for @c DataVector.
4031 * This overrides the default implementation of @c ClassName
4032 * to hide @c DataVector's second template parameter.
4035 std::string ClassName<DataVector<T> >::name()
4037 std::string out = "DataVector<";
4038 out += ClassName<T>::name();
4039 if (out[out.size()-1] == '>')
4046 #ifndef XAOD_STANDALONE
4049 // Set up initialization of element type BaseInfo
4050 namespace DataVector_detail {
4051 #define DVLTYPE DataVector
4052 #include "AthContainers/tools/DVLEltBaseInfo.icc"
4054 } // namespace DataVector_detail
4060 namespace DataVector_detail {
4061 /// Dummy implementation for the DVLEltBaseInit structure
4063 struct DVLEltBaseInit {};
4064 } // namespace DataVector_detail
4067 #endif // not XAOD_STANDALONE
4071 // We need to specialize the function that DVLInfo uses to create the container
4074 * @brief Construct a new container.
4075 * @param nreserve Number of elements for which to reserve space.
4076 * (Ignored if not appropriate.)
4077 * @param cont[out] Pointer to the constructed container.
4078 * (Returned via an argument to allow for template
4079 * argument deduction.)
4081 * Specialization for DataVector.
4084 void dvl_makecontainer (size_t nreserve, DataVector<T>*& cont)
4086 cont = new DataVector<T> (SG::VIEW_ELEMENTS);
4087 cont->reserve (nreserve);