@@ -48,6 +48,9 @@ namespace Death { namespace Containers {
4848 /* * @brief Creates a new allocation big enough for @p minSize and pass back its size in @p newCapacity */
4949 void * mallocForGrow (void * firstEl, std::size_t minSize, std::size_t typeSize, std::size_t & newCapacity);
5050
51+ /* * @brief Creates a new allocation for shrinking operation */
52+ void * mallocForShrink (void * firstEl, std::size_t newCapacity, std::size_t typeSize);
53+
5154 /* * @brief Grows the allocated memory (without initializing new elements) for trivial types */
5255 void growTrivial (void * firstEl, std::size_t minSize, std::size_t typeSize);
5356
@@ -158,13 +161,13 @@ namespace Death { namespace Containers {
158161 /* * @brief Returns `true` unless @p elt will be invalidated by resizing the vector to @p newSize */
159162 bool isSafeToReferenceAfterResize (const void * elt, std::size_t newSize) {
160163 // Past the end.
161- if DEATH_LIKELY (!isReferenceToStorage (elt))
164+ if DEATH_LIKELY (!isReferenceToStorage (elt)) {
162165 return true ;
163-
166+ }
164167 // Return false if Elt will be destroyed by shrinking
165- if (newSize <= this ->size ())
168+ if (newSize <= this ->size ()) {
166169 return elt < this ->begin () + newSize;
167-
170+ }
168171 // Return false if we need to grow
169172 return newSize <= this ->capacity ();
170173 }
@@ -182,8 +185,9 @@ namespace Death { namespace Containers {
182185
183186 /* * @brief Checks whether any part of the range will be invalidated by clearing */
184187 void assertSafeToReferenceAfterClear (const T* from, const T* to) {
185- if (from == to)
188+ if (from == to) {
186189 return ;
190+ }
187191 this ->assertSafeToReferenceAfterResize (from, 0 );
188192 this ->assertSafeToReferenceAfterResize (to - 1 , 0 );
189193 }
@@ -193,8 +197,9 @@ namespace Death { namespace Containers {
193197
194198 /* * @brief Checks whether any part of the range will be invalidated by growing */
195199 void assertSafeToAddRange (const T* from, const T* to) {
196- if (from == to)
200+ if (from == to) {
197201 return ;
202+ }
198203 this ->assertSafeToAdd (from, to - from);
199204 this ->assertSafeToAdd (to - 1 , to - from);
200205 }
@@ -206,9 +211,9 @@ namespace Death { namespace Containers {
206211 template <class U >
207212 static const T* reserveForParamAndGetAddressImpl (U* _this, const T& elt, std::size_t n) {
208213 std::size_t newSize = _this->size () + n;
209- if DEATH_LIKELY (newSize <= _this->capacity ())
214+ if DEATH_LIKELY (newSize <= _this->capacity ()) {
210215 return &elt;
211-
216+ }
212217 bool referencesStorage = false ;
213218 std::int64_t index = -1 ;
214219 if (!U::TakesParamByValue) {
@@ -487,9 +492,9 @@ namespace Death { namespace Containers {
487492 template <typename T, bool TriviallyCopyable>
488493 void SmallVectorTemplate<T, TriviallyCopyable>::takeAllocationForGrow(T* newElts, std::size_t newCapacity) {
489494 // If this wasn't grown from the inline copy, deallocate the old space
490- if (!this ->isSmall ())
495+ if (!this ->isSmall ()) {
491496 std::free (this ->begin ());
492-
497+ }
493498 this ->setAllocationRange (newElts, newCapacity);
494499 }
495500
@@ -536,8 +541,9 @@ namespace Death { namespace Containers {
536541 // Use memcpy for PODs iterated by pointers (which includes SmallVector iterators):
537542 // std::uninitialized_copy optimizes to memmove, but we can use memcpy here. Note that
538543 // I and E are iterators and thus might be invalid for memcpy if they are equal
539- if (i != e)
544+ if (i != e) {
540545 std::memcpy (reinterpret_cast <void *>(dest), i, (e - i) * sizeof (T));
546+ }
541547 }
542548
543549 /* * @brief Doubles the size of the allocated memory, guaranteeing space for at least one more element or @p minSize if specified */
@@ -626,8 +632,9 @@ namespace Death { namespace Containers {
626632 /* * @brief Assigns the content of the specified vector */
627633 void assignRemote (SmallVectorImpl&& other) {
628634 this ->destroyRange (this ->begin (), this ->end ());
629- if (!this ->isSmall ())
635+ if (!this ->isSmall ()) {
630636 std::free (this ->begin ());
637+ }
631638 this ->BeginX = other.BeginX ;
632639 this ->Size = other.Size ;
633640 this ->Capacity = other.Capacity ;
@@ -638,8 +645,9 @@ namespace Death { namespace Containers {
638645 ~SmallVectorImpl () {
639646 // Subclass has already destructed this vector's elements
640647 // If this wasn't grown from the inline copy, deallocate the old space
641- if (!this ->isSmall ())
648+ if (!this ->isSmall ()) {
642649 std::free (this ->begin ());
650+ }
643651 }
644652
645653 public:
@@ -667,11 +675,13 @@ namespace Death { namespace Containers {
667675 }
668676
669677 this ->reserve (n);
670- for (auto i = this ->end (), e = this ->begin () + n; i != e; ++i)
671- if (ForOverwrite)
678+ for (auto i = this ->end (), e = this ->begin () + n; i != e; ++i) {
679+ if (ForOverwrite) {
672680 new (&*i) T;
673- else
681+ } else {
674682 new (&*i) T ();
683+ }
684+ }
675685 this ->setSize (n);
676686 }
677687
@@ -696,7 +706,7 @@ namespace Death { namespace Containers {
696706 return ;
697707 }
698708
699- // N > this->size(). Defer to append
709+ // N > this->size() - defer to append
700710 this ->append (n - this ->size (), nv);
701711 }
702712
@@ -713,6 +723,19 @@ namespace Death { namespace Containers {
713723 this ->grow (n);
714724 }
715725
726+ /* * @brief Try to shrink the vector to given capacity without discarding any elements */
727+ void shrink (size_type newCapacity) {
728+ if (newCapacity < this ->Size ) {
729+ newCapacity = this ->Size ;
730+ }
731+ if (newCapacity >= this ->capacity () || this ->isSmall ()) {
732+ return ;
733+ }
734+
735+ void * newElts = this ->mallocForShrink (this ->BeginX , newCapacity, sizeof (T));
736+ this ->setAllocationRange (newElts, newCapacity);
737+ }
738+
716739 /* * @brief Removes the last @p n elements */
717740 void pop_back_n (size_type n) {
718741 DEATH_DEBUG_ASSERT (this ->size () >= n);
@@ -751,8 +774,8 @@ namespace Death { namespace Containers {
751774 append (il.begin (), il.end ());
752775 }
753776
754- /* * @brief Appends the specified vector to the end */
755- void append (const SmallVectorImpl& other) {
777+ /* * @brief Appends the specified view to the end */
778+ void append (ArrayView< const T> other) {
756779 append (other.begin (), other.end ());
757780 }
758781
@@ -766,10 +789,11 @@ namespace Death { namespace Containers {
766789
767790 // Assign over existing elements
768791 std::fill_n (this ->begin (), std::min (n, this ->size ()), elt);
769- if (n > this ->size ())
792+ if (n > this ->size ()) {
770793 std::uninitialized_fill_n (this ->end (), n - this ->size (), elt);
771- else if (n < this ->size ())
794+ } else if (n < this ->size ()) {
772795 this ->destroyRange (this ->begin () + n, this ->end ());
796+ }
773797 this ->setSize (n);
774798 }
775799
@@ -872,9 +896,9 @@ namespace Death { namespace Containers {
872896 // If we just moved the element we're inserting, be sure to update the reference (never happens if TakesParamByValue)
873897 static_assert (!TakesParamByValue || std::is_same<ArgType, T>::value,
874898 " ArgType must be 'T' when taking by value" );
875- if (!TakesParamByValue && this ->isReferenceToRange (eltPtr, i, this ->end ()))
899+ if (!TakesParamByValue && this ->isReferenceToRange (eltPtr, i, this ->end ())) {
876900 ++eltPtr;
877-
901+ }
878902 *i = Death::forward<ArgType>(*eltPtr);
879903 return i;
880904 }
@@ -919,9 +943,9 @@ namespace Death { namespace Containers {
919943 std::move_backward (i, oldEnd - numToInsert, oldEnd);
920944
921945 // If we just moved the element we're inserting, be sure to update the reference (never happens if TakesParamByValue)
922- if (!TakesParamByValue && i <= eltPtr && eltPtr < this ->end ())
946+ if (!TakesParamByValue && i <= eltPtr && eltPtr < this ->end ()) {
923947 eltPtr += numToInsert;
924-
948+ }
925949 std::fill_n (i, numToInsert, *eltPtr);
926950 return i;
927951 }
@@ -935,9 +959,9 @@ namespace Death { namespace Containers {
935959 this ->uninitializedMove (i, oldEnd, this ->end () - numOverwritten);
936960
937961 // If we just moved the element we're inserting, be sure to update the reference (never happens if TakesParamByValue)
938- if (!TakesParamByValue && i <= eltPtr && eltPtr < this ->end ())
962+ if (!TakesParamByValue && i <= eltPtr && eltPtr < this ->end ()) {
939963 eltPtr += numToInsert;
940-
964+ }
941965 // Replace the overwritten part
942966 std::fill_n (i, numOverwritten, *eltPtr);
943967
@@ -1010,8 +1034,9 @@ namespace Death { namespace Containers {
10101034 /* * @brief Constructs elements in-place at the end */
10111035 template <typename ...ArgTypes>
10121036 reference emplace_back (ArgTypes&&... args) {
1013- if (this ->size () >= this ->capacity ())
1037+ if (this ->size () >= this ->capacity ()) {
10141038 return this ->growAndEmplaceBack (Death::forward<ArgTypes>(args)...);
1039+ }
10151040
10161041 ::new ((void *)this ->end ()) T (Death::forward<ArgTypes>(args)...);
10171042 this ->setSize (this ->size () + 1 );
@@ -1062,8 +1087,9 @@ namespace Death { namespace Containers {
10621087 // Swap the shared elements
10631088 std::size_t numShared = this ->size ();
10641089 if (numShared > other.size ()) numShared = other.size ();
1065- for (size_type i = 0 ; i != numShared; ++i)
1090+ for (size_type i = 0 ; i != numShared; ++i) {
10661091 std::swap ((*this )[i], other[i]);
1092+ }
10671093
10681094 // Copy over the extra elts
10691095 if (this ->size () > other.size ()) {
@@ -1092,10 +1118,11 @@ namespace Death { namespace Containers {
10921118 if (currentSize >= otherSize) {
10931119 // Assign common elements
10941120 iterator newEnd;
1095- if (otherSize)
1121+ if (otherSize) {
10961122 newEnd = std::copy (other.begin (), other.begin () + otherSize, this ->begin ());
1097- else
1123+ } else {
10981124 newEnd = this ->begin ();
1125+ }
10991126
11001127 // Destroy excess elements
11011128 this ->destroyRange (newEnd, this ->end ());
@@ -1321,20 +1348,23 @@ namespace Death { namespace Containers {
13211348
13221349 /* * @brief Copy constructor */
13231350 SmallVector (const SmallVector& other) : SmallVectorImpl<T>(N) {
1324- if (!other.empty ())
1351+ if (!other.empty ()) {
13251352 SmallVectorImpl<T>::operator =(other);
1353+ }
13261354 }
13271355
13281356 /* * @brief Move constructor */
13291357 SmallVector (SmallVector&& other) : SmallVectorImpl<T>(N) {
1330- if (!other.empty ())
1358+ if (!other.empty ()) {
13311359 SmallVectorImpl<T>::operator =(Death::move (other));
1360+ }
13321361 }
13331362
13341363 /* * @overload */
13351364 SmallVector (SmallVectorImpl<T>&& other) : SmallVectorImpl<T>(N) {
1336- if (!other.empty ())
1365+ if (!other.empty ()) {
13371366 SmallVectorImpl<T>::operator =(Death::move (other));
1367+ }
13381368 }
13391369
13401370 /* * @brief Destructor */
@@ -1400,6 +1430,7 @@ namespace Death { namespace Containers {
14001430 using SmallVectorImpl::resize_for_overwrite;
14011431 using SmallVectorImpl::truncate;
14021432 using SmallVectorImpl::reserve;
1433+ using SmallVectorImpl::shrink;
14031434 using SmallVectorTemplate::push_back;
14041435 using SmallVectorTemplate::pop_back;
14051436 using SmallVectorImpl::pop_back_n;
0 commit comments