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